tinacms 0.66.9 → 0.66.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,63 @@
1
1
  # tinacms
2
2
 
3
+ ## 0.66.10
4
+
5
+ ### Patch Changes
6
+
7
+ - 39a8c4f7d: Fix issue with unstableFormify where `Document` interface fields were not being formified properly
8
+ - ec28a129b: Update to tina admin to use the frontend schema
9
+ - a28b787c5: With the rich-text editor, inserting a soft-break (`shift+enter`), this will now result in a `<br>` tag being inserted. Note that this will save the markdown with a backslash to indicate line break (instead of multiple empty spaces):
10
+
11
+ ```markdown
12
+ 123 Abc St\
13
+ Charlottetown, PEI
14
+ ```
15
+
16
+ - 93363dfc2: Prevent error on reset when nested blocks have changed in unstable formify hook
17
+ - abf25c673: The schema can now to used on the frontend (optional for now but will be the main path moving forward).
18
+
19
+ ### How to migrate.
20
+
21
+ If you gone though the `tinacms init` process there should be a file called `.tina/components/TinaProvider`. In that file you can import the schema from `schema.ts` and add it to the TinaCMS wrapper component.
22
+
23
+ ```tsx
24
+ import TinaCMS from 'tinacms'
25
+ import schema, { tinaConfig } from '../schema.ts'
26
+
27
+ // Importing the TinaProvider directly into your page will cause Tina to be added to the production bundle.
28
+ // Instead, import the tina/provider/index default export to have it dynamially imported in edit-moode
29
+ /**
30
+ *
31
+ * @private Do not import this directly, please import the dynamic provider instead
32
+ */
33
+ const TinaProvider = ({ children }) => {
34
+ return (
35
+ <TinaCMS {...tinaConfig} schema={schema}>
36
+ {children}
37
+ </TinaCMS>
38
+ )
39
+ }
40
+
41
+ export default TinaProvider
42
+ ```
43
+
44
+ - 591640db0: Fixes a bug with `breadcrumbs` to account for subfolders (instead of just the `filename`) and allows Documents to be created and updated within subfolders.
45
+
46
+ Before this fix, `breadcrumbs` was only the `basename` of the file minus the `extension`. So `my-folder-a/my-folder-b/my-file.md` would have `breadcrumbs` of `['my-file']`. With this change, `breadcrumbs` will be `['my-folder-a','my-folder-b','my-file']` (leaving out the `content/<collection>`).
47
+
48
+ - 875779ac6: Don't attempt to formify nodes which don't have data fields (ie. ...on Node)
49
+ - e8b0de1f7: Add `parentTypename` to fields to allow us to disambiguate between fields which have the same field names but different types. Example, an event from field name of `blocks.0.title` could belong to a `Cta` block or a `Hero` block, both of which have a `title` field.
50
+ - Updated dependencies [429d8e93e]
51
+ - Updated dependencies [6c517b5da]
52
+ - Updated dependencies [e81cf8867]
53
+ - Updated dependencies [abf25c673]
54
+ - Updated dependencies [801f39f62]
55
+ - Updated dependencies [0e270d878]
56
+ - Updated dependencies [e8b0de1f7]
57
+ - @tinacms/sharedctx@0.1.1
58
+ - @tinacms/toolkit@0.56.19
59
+ - @tinacms/schema-tools@0.0.2
60
+
3
61
  ## 0.66.9
4
62
 
5
63
  ### Patch Changes
@@ -14,12 +14,14 @@ import { TokenObject } from '../auth/authenticate';
14
14
  import { BranchData, EventBus } from '@tinacms/toolkit';
15
15
  import { DocumentNode, GraphQLSchema } from 'graphql';
16
16
  import gql from 'graphql-tag';
17
+ import { TinaSchema, TinaCloudSchema } from '@tinacms/schema-tools';
17
18
  export declare type TinaIOConfig = {
18
19
  frontendUrlOverride?: string;
19
20
  identityApiUrlOverride?: string;
20
21
  contentApiUrlOverride?: string;
21
22
  };
22
23
  interface ServerOptions {
24
+ schema?: TinaCloudSchema<false>;
23
25
  clientId: string;
24
26
  branch: string;
25
27
  customContentApiUrl?: string;
@@ -31,7 +33,8 @@ export declare class Client {
31
33
  frontendUrl: string;
32
34
  contentApiUrl: string;
33
35
  identityApiUrl: string;
34
- schema: GraphQLSchema;
36
+ gqlSchema: GraphQLSchema;
37
+ schema?: TinaSchema;
35
38
  clientId: string;
36
39
  contentApiBase: string;
37
40
  query: string;
@@ -103,6 +106,7 @@ export declare const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/
103
106
  export declare class LocalClient extends Client {
104
107
  constructor(props?: {
105
108
  customContentApiUrl?: string;
109
+ schema?: TinaCloudSchema<false>;
106
110
  });
107
111
  isAuthorized(): Promise<boolean>;
108
112
  isAuthenticated(): Promise<boolean>;
@@ -0,0 +1,89 @@
1
+ /**
2
+ Copyright 2021 Forestry.io Holdings, Inc.
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
12
+ */
13
+ import * as G from 'graphql';
14
+ import type { BlueprintPath } from './types';
15
+ /**
16
+ *
17
+ * This check ensures that at type is a Document, but only one
18
+ * that can be "formified". When using `Node` or `Document`, those
19
+ * query fields should not have forms generated since they can't contain
20
+ * fields.
21
+ *
22
+ * ```graphql
23
+ * # Can be formified
24
+ * {
25
+ * getPostDocument(relativePath: "") {
26
+ * data {
27
+ * title
28
+ * }
29
+ * }
30
+ * }
31
+ * ```
32
+ *
33
+ * ```graphql
34
+ * # cannot be formified, even though it is a document field
35
+ * {
36
+ * getPostDocument(relativePath: "") {
37
+ * ...on Document {
38
+ * id
39
+ * }
40
+ * }
41
+ * }
42
+ * ```
43
+ */
44
+ export declare const isFormifiableDocument: (t: G.GraphQLOutputType) => boolean;
45
+ export declare const isScalarType: (t: G.GraphQLOutputType) => boolean;
46
+ export declare const isConnectionField: (t: G.GraphQLOutputType) => boolean;
47
+ /**
48
+ * Selects the appropriate field from a GraphQLObject based on the selection's name
49
+ */
50
+ export declare const getObjectField: (object: G.GraphQLOutputType, selectionNode: G.FieldNode) => G.GraphQLField<any, any, {
51
+ [key: string]: any;
52
+ }>;
53
+ /**
54
+ * Selects the appropriate type from a union based on the selection's typeCondition
55
+ *
56
+ * ```graphql
57
+ * post {
58
+ * # would return PostDocument
59
+ * ...on PostDocument { ... }
60
+ * }
61
+ * ```
62
+ */
63
+ export declare const getSelectedUnionType: (unionType: G.GraphQLOutputType, selectionNode: G.InlineFragmentNode) => any;
64
+ /**
65
+ * Checks if the given type is a list type. Even though
66
+ * this function is built-in to GraphQL it doesn't handle
67
+ * the scenario where the list type is wrapped in a non-null
68
+ * type, so the extra check here is needed.
69
+ */
70
+ export declare function isListType(type: unknown): boolean;
71
+ /**
72
+ *
73
+ * Throws an error if the provided type is not a GraphQLUnionType
74
+ */
75
+ export declare function ensureOperationDefinition(type: G.DefinitionNode): asserts type is G.OperationDefinitionNode;
76
+ /**
77
+ * Generates the name and alias information for a given field node
78
+ * and appends it to a shallow copy of the path provided
79
+ */
80
+ export declare function buildPath({ fieldNode, type, parentTypename, path, }: {
81
+ fieldNode: G.FieldNode;
82
+ type: G.GraphQLOutputType;
83
+ parentTypename?: string;
84
+ path?: BlueprintPath[];
85
+ }): BlueprintPath[];
86
+ export declare const metaFields: G.SelectionNode[];
87
+ export declare const getRelativeBlueprint: (path: BlueprintPath[]) => string;
88
+ export declare const getBlueprintId: (path: BlueprintPath[]) => string;
89
+ export declare const getFieldAliasForBlueprint: (path: BlueprintPath[]) => string;
@@ -17,6 +17,7 @@ export declare const buildChangeSet: (event: OnChangeEvent, formNode: FormNode)
17
17
  name: string;
18
18
  type: "string" | "object" | "reference";
19
19
  list?: boolean;
20
+ parentTypename: string;
20
21
  };
21
22
  name: string;
22
23
  formId: string;
@@ -10,4 +10,4 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
10
  See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
- export declare const testRunner: (query: any, events: any, dirname: any) => Promise<void>;
13
+ export declare const testRunner: (query: any, events: any, dirname: any, expectNoChange?: boolean) => Promise<void>;
File without changes
@@ -14,6 +14,11 @@ limitations under the License.
14
14
  import type * as G from 'graphql';
15
15
  import type { Form, Field } from '@tinacms/toolkit';
16
16
  export declare type Action = {
17
+ type: 'start';
18
+ value: {
19
+ query: string;
20
+ };
21
+ } | {
17
22
  type: 'setData';
18
23
  value: object;
19
24
  } | {
@@ -53,9 +58,9 @@ export declare type FormifiedDocumentNode = {
53
58
  id: string;
54
59
  _internalSys: {
55
60
  path: string;
56
- };
57
- collection: {
58
- name: any;
61
+ collection: {
62
+ name: any;
63
+ };
59
64
  };
60
65
  form: {
61
66
  mutationInfo: {
@@ -106,6 +111,7 @@ export declare type OnChangeEvent = {
106
111
  name: string;
107
112
  type: 'string' | 'reference' | 'object';
108
113
  list?: boolean;
114
+ parentTypename: string;
109
115
  };
110
116
  };
111
117
  name: string;
@@ -128,6 +134,7 @@ export declare type ChangeSet = {
128
134
  export declare type BlueprintPath = {
129
135
  name: string;
130
136
  alias: string;
137
+ parentTypename?: string;
131
138
  list?: boolean;
132
139
  isNode?: boolean;
133
140
  };
@@ -165,7 +172,7 @@ export declare type State = {
165
172
  schema: G.GraphQLSchema;
166
173
  query: G.DocumentNode;
167
174
  queryString: string;
168
- status: 'initialized' | 'formified' | 'ready' | 'done';
175
+ status: 'idle' | 'initialized' | 'formified' | 'ready' | 'done';
169
176
  count: number;
170
177
  data: object;
171
178
  changeSets: ChangeSet[];
@@ -10,75 +10,32 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
10
  See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
- import * as G from 'graphql';
14
13
  import { Form, Field, TinaCMS } from '@tinacms/toolkit';
15
- import type { DocumentBlueprint, FieldBlueprint, BlueprintPath, FormifiedDocumentNode, OnChangeEvent, FormNode, State, ChangeSet } from './types';
14
+ import type { DocumentBlueprint, FieldBlueprint, FormifiedDocumentNode, OnChangeEvent, FormNode, State, ChangeSet, BlueprintPath } from './types';
16
15
  import { formifyCallback, onSubmitArgs } from '../use-graphql-forms';
17
16
  interface RecursiveFormifiedDocumentNode<T extends object> extends Array<RecursiveFormifiedDocumentNode<T> | T> {
18
17
  }
19
- export declare const isNodeField: (type: G.GraphQLNamedType) => boolean;
20
- export declare const isConnectionField: (type: G.GraphQLNamedType) => boolean;
21
18
  /**
22
- * Selects the appropriate field from a GraphQLObject based on the selection's name
23
- */
24
- export declare const getObjectField: (object: G.GraphQLObjectType<any, any>, selectionNode: G.FieldNode) => G.GraphQLField<any, any, {
25
- [key: string]: any;
26
- }>;
27
- /**
28
- * Selects the appropriate type from a union based on the selection's typeCondition
29
- *
30
- * ```graphql
31
- * post {
32
- * # would return PostDocument
33
- * ...on PostDocument { ... }
19
+ * Gets the value from an object for a given blueprint for _all_ possible values.
20
+ * eg. If the blueprint is `getCollection.documents.edges.[].node` and the value is:
21
+ * ```
22
+ * {
23
+ * getCollection: {
24
+ * documents: {
25
+ * edges: [{
26
+ * node: valueA
27
+ * },
28
+ * {
29
+ * node: valueB
30
+ * }]
31
+ * }
32
+ * }
34
33
  * }
35
34
  * ```
36
- */
37
- export declare const getSelectedUnionType: (unionType: G.GraphQLUnionType, selectionNode: G.InlineFragmentNode) => G.GraphQLObjectType<any, any>;
38
- /**
39
- * Checks if the given type is a list type. Even though
40
- * this function is built-in to GraphQL it doesn't handle
41
- * the scenario where the list type is wrapped in a non-null
42
- * type, so the extra check here is needed.
43
- */
44
- export declare function isListType(type: unknown): boolean;
45
- /**
46
- *
47
- * Throws an error if the provided type is no a GraphQLUnionType
48
- */
49
- export declare function ensureNodeField(field: G.GraphQLNamedType): void;
50
- /**
51
- *
52
- * Throws an error if the provided type is no a GraphQLUnionType
53
- */
54
- export declare function ensureUnionType(type: unknown): asserts type is G.GraphQLUnionType;
55
- /**
56
- *
57
- * Throws an error if the provided type is no a GraphQLUnionType
58
- */
59
- export declare function ensureObjectType(type: unknown): asserts type is G.GraphQLObjectType;
60
- /**
35
+ * The response would be an array containing `valueA` and `valueB`
61
36
  *
62
- * Throws an error if the provided type is no a GraphQLUnionType
63
37
  */
64
- export declare function ensureOperationDefinition(type: G.DefinitionNode): asserts type is G.OperationDefinitionNode;
65
- export declare function getNameAndAlias(fieldNode: G.FieldNode, list: boolean, isNode: boolean): {
66
- name: string;
67
- alias: string;
68
- list: boolean;
69
- isNode: boolean;
70
- };
71
- export declare const metaFields: G.SelectionNode[];
72
- export declare const getRelativeBlueprint: (path: BlueprintPath[]) => string;
73
- export declare const getFieldAliasForBlueprint: (path: BlueprintPath[]) => string;
74
- /**
75
- *
76
- *
77
- * ./index utilities
78
- *
79
- *
80
- */
81
- export declare const getIn2: <T extends object>(state: object, path: string) => T | RecursiveFormifiedDocumentNode<T>;
38
+ export declare const getValueForBlueprint: <T extends object>(state: object, path: string) => T | RecursiveFormifiedDocumentNode<T>;
82
39
  /**
83
40
  * Returns the name of the field. In the example query, `title` and `t` would both be blueprint fields
84
41
  *
@@ -99,25 +56,52 @@ export declare const formNodeId: (formNode: FormNode) => string;
99
56
  export declare const formNodePath: (formNode: FormNode) => string;
100
57
  export declare const formNodeNotIn: (formNode: FormNode, formNodes: FormNode[]) => boolean;
101
58
  export declare const sequential: <A, B>(items: A[], callback: (args: A, idx: number) => Promise<B>) => Promise<B[]>;
102
- export declare const getBlueprintId: (path: BlueprintPath[]) => string;
103
59
  export declare const getFormNodesForField: (fieldBlueprint: FieldBlueprint, formNode: FormNode, event: OnChangeEvent, state: State) => {
104
60
  pathToChange: string;
105
61
  formNodes: FormNode[];
106
62
  eventLocation: any[];
107
63
  existing: any;
108
64
  };
109
- export declare const matchLocation: (eventLocation: number[], formNode: FormNode) => boolean;
110
- export declare const bumpLocation: (location: number[]) => number[];
111
- export declare const maybeLowerLocation: (location: number[], at: number) => number[];
112
- export declare const matchesAt: (location: number[], at: number) => boolean;
113
- export declare const swapLocation: (location: number[], mapping: {
114
- [key: number]: number;
115
- }) => number[];
116
65
  export declare const getBlueprintAliasPath: (blueprint: DocumentBlueprint) => string;
66
+ export declare const getFieldAliasForBlueprint: (path: BlueprintPath[]) => string;
67
+ /**
68
+ *
69
+ * Determines the appropriate fields which should recieve an update from a form change
70
+ *
71
+ * In cases where there's polymorphic blocks, it's possible that an update would affect
72
+ * multiple locations that it shouldn't.
73
+ *
74
+ * An OnChange event name can look like: `blocks.2.title`, but if there are 2 block elements
75
+ * with a field of the same name, an event name it wouldn't be enough information for us.
76
+ *
77
+ * To get around this, the event sends the current `typename` along with it, and we use that
78
+ * to determine where in our blueprint the value should be updated.
79
+ *
80
+ */
117
81
  export declare const getBlueprintFieldsForEvent: (blueprint: DocumentBlueprint, event: OnChangeEvent) => FieldBlueprint[];
118
- export declare const getBlueprintNamePath: (blueprint: Pick<DocumentBlueprint, 'path'>) => string;
82
+ export declare const filterFieldBlueprintsByParentTypename: (fbp: FieldBlueprint, typename: any) => boolean;
83
+ /**
84
+ *
85
+ * Returns the human-readable path to a blueprint or blueprint field.
86
+ * Optionally, appends a disambiguator to the string where necessary.
87
+ *
88
+ * eg. if a blocks field is polymporphic, specifying `true` for the disambiguator
89
+ *
90
+ * ```
91
+ * getPageDocument.data.blocks[].PageBlocksCta.title
92
+ * ```
93
+ */
94
+ export declare const getBlueprintNamePath: (blueprint: Pick<DocumentBlueprint, 'path'>, disambiguator?: boolean) => string;
119
95
  export declare const stripIndices: (string: any) => any[];
120
96
  export declare const replaceRealNum: (string: any) => any;
97
+ export declare const getMatchName: ({ field, prefix, blueprint }: {
98
+ field: any;
99
+ prefix: any;
100
+ blueprint: any;
101
+ }) => {
102
+ matchName: string;
103
+ fieldName: any;
104
+ };
121
105
  export declare const getFormNodesFromEvent: (state: State, event: OnChangeEvent) => FormNode[];
122
106
  export declare const printState: (state: State) => string;
123
107
  export declare const printEvent: (event: OnChangeEvent) => {
@@ -132,6 +116,7 @@ export declare const printEvent: (event: OnChangeEvent) => {
132
116
  name: string;
133
117
  type: "string" | "object" | "reference";
134
118
  list?: boolean;
119
+ parentTypename: string;
135
120
  };
136
121
  };
137
122
  name: string;
@@ -141,10 +126,13 @@ export declare const getFormNodeBlueprint: (formNode: FormNode, state: State) =>
141
126
  export declare const getMoveMapping: (existing: any, from: any, to: any) => {
142
127
  [key: number]: number;
143
128
  };
144
- export declare const getPathsToChange: (event: OnChangeEvent, state: State) => {
145
- formNode: FormNode;
146
- pathToChange: string;
147
- }[];
129
+ export declare const matchLocation: (eventLocation: number[], formNode: FormNode) => boolean;
130
+ export declare const bumpLocation: (location: number[]) => number[];
131
+ export declare const maybeLowerLocation: (location: number[], at: number) => number[];
132
+ export declare const matchesAt: (location: number[], at: number) => boolean;
133
+ export declare const swapLocation: (location: number[], mapping: {
134
+ [key: number]: number;
135
+ }) => number[];
148
136
  /**
149
137
  *
150
138
  * Gets the sub-fields for an object field, if it's a polymorphic
@@ -10,7 +10,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
10
  See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
- import { Form } from '@tinacms/toolkit';
13
+ import { Form, AnyField } from '@tinacms/toolkit';
14
14
  import type { FormOptions, TinaCMS } from '@tinacms/toolkit';
15
15
  export declare function useGraphqlFormsUnstable<T extends object>({ variables, onSubmit, query, formify, eventList, }: {
16
16
  query: string;
@@ -40,7 +40,7 @@ export declare const transformDocumentIntoMutationRequestPayload: (document: {
40
40
  includeTemplate?: boolean;
41
41
  }) => any;
42
42
  export declare const generateFormCreatorsUnstable: (cms: TinaCMS, showInSidebar?: boolean) => {
43
- createForm: (formConfig: any) => Form<any, import("@tinacms/toolkit").AnyField>;
43
+ createForm: (formConfig: any) => Form<any, AnyField>;
44
44
  createGlobalForm: GlobalFormCreator;
45
45
  };
46
46
  declare type FormCreator = (formConfig: FormOptions<any>) => Form;
package/dist/index.d.ts CHANGED
@@ -23,9 +23,8 @@ export { TinaAdminApi } from './admin/api';
23
23
  import { TinaCMSProvider2, TinaCMSProviderDefaultProps } from './tina-cms';
24
24
  export type { TinaCMSProviderDefaultProps };
25
25
  export default TinaCMSProvider2;
26
- import type { TinaCloudSchema as TinaCloudSchemaBase, TinaCloudCollection as TinaCloudCollectionBase, TinaCloudTemplateBase as TinaTemplate, TinaFieldBase } from './types';
26
+ import type { TinaCloudSchema as TinaCloudSchemaBase, TinaCloudCollection as TinaCloudCollectionBase, TinaCloudTemplateBase as TinaTemplate, TinaFieldBase } from '@tinacms/schema-tools';
27
27
  export declare type TinaCloudSchema = TinaCloudSchemaBase<false>;
28
- export declare type TinaSchema = TinaCloudSchema;
29
28
  export declare type TinaCloudCollection = TinaCloudCollectionBase<false>;
30
29
  export declare type TinaCollection = TinaCloudCollectionBase<false>;
31
30
  export declare type TinaField = TinaFieldBase;