@tinacms/graphql 0.59.7 → 0.59.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,61 @@
1
1
  # tina-graphql
2
2
 
3
+ ## 0.59.10
4
+
5
+ ### Patch Changes
6
+
7
+ - cf33bcec1: Fix issue where store.clear() was not being awaited causing an invalid state after reindex
8
+
9
+ ## 0.59.9
10
+
11
+ ### Patch Changes
12
+
13
+ - 82174ff50: Modify Database.indexContentByPaths to not require collection parameter
14
+ - a87e1e6fa: Enable query filtering, pagination, sorting
15
+ - abf25c673: The schema can now to used on the frontend (optional for now but will be the main path moving forward).
16
+
17
+ ### How to migrate.
18
+
19
+ 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.
20
+
21
+ ```tsx
22
+ import TinaCMS from 'tinacms'
23
+ import schema, { tinaConfig } from '../schema.ts'
24
+
25
+ // Importing the TinaProvider directly into your page will cause Tina to be added to the production bundle.
26
+ // Instead, import the tina/provider/index default export to have it dynamially imported in edit-moode
27
+ /**
28
+ *
29
+ * @private Do not import this directly, please import the dynamic provider instead
30
+ */
31
+ const TinaProvider = ({ children }) => {
32
+ return (
33
+ <TinaCMS {...tinaConfig} schema={schema}>
34
+ {children}
35
+ </TinaCMS>
36
+ )
37
+ }
38
+
39
+ export default TinaProvider
40
+ ```
41
+
42
+ - 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.
43
+
44
+ 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>`).
45
+
46
+ - 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.
47
+ - Updated dependencies [8b3be903f]
48
+ - Updated dependencies [a87e1e6fa]
49
+ - Updated dependencies [b01f2e382]
50
+ - @tinacms/datalayer@0.1.0
51
+
52
+ ## 0.59.8
53
+
54
+ ### Patch Changes
55
+
56
+ - e7b27ba3b: Fix issue where un-normalized rich-text fields which send `null` values to the server on save would cause a parsing error
57
+ - 11d55f441: Add experimental useGraphQLForms hook
58
+
3
59
  ## 0.59.7
4
60
 
5
61
  ### Patch Changes
@@ -10,21 +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 type { BinaryFilter, IndexDefinition, Store, TernaryFilter } from '@tinacms/datalayer';
13
14
  import type { DocumentNode } from 'graphql';
14
15
  import type { TinaSchema } from '../schema';
15
16
  import type { TinaCloudSchemaBase } from '../types';
16
- import type { Store } from './store';
17
17
  import type { Bridge } from './bridge';
18
18
  declare type CreateDatabase = {
19
19
  bridge: Bridge;
20
20
  store: Store;
21
21
  };
22
22
  export declare const createDatabase: (config: CreateDatabase) => Promise<Database>;
23
+ /** Options for {@link Database.query} **/
24
+ export declare type QueryOptions = {
25
+ collection: string;
26
+ filterChain?: (BinaryFilter | TernaryFilter)[];
27
+ sort?: string;
28
+ first?: number;
29
+ last?: number;
30
+ after?: string;
31
+ before?: string;
32
+ };
23
33
  export declare class Database {
24
34
  config: CreateDatabase;
25
35
  bridge: Bridge;
26
36
  store: Store;
27
37
  private tinaSchema;
38
+ private collectionIndexDefinitions;
28
39
  private _lookup;
29
40
  private _graphql;
30
41
  private _tinaSchema;
@@ -51,8 +62,20 @@ export declare class Database {
51
62
  getGraphQLSchemaFromBridge: () => Promise<DocumentNode>;
52
63
  getTinaSchema: () => Promise<TinaCloudSchemaBase>;
53
64
  getSchema: () => Promise<TinaSchema>;
65
+ getIndexDefinitions: () => Promise<Record<string, Record<string, IndexDefinition>>>;
54
66
  documentExists: (fullpath: unknown) => Promise<boolean>;
55
- query: (queryStrings: string[], hydrator: any) => Promise<object[]>;
67
+ query: (queryOptions: QueryOptions, hydrator: any) => Promise<{
68
+ edges: {
69
+ node: any;
70
+ cursor: string;
71
+ }[];
72
+ pageInfo: {
73
+ hasPreviousPage: boolean;
74
+ hasNextPage: boolean;
75
+ startCursor: string;
76
+ endCursor: string;
77
+ };
78
+ }>;
56
79
  putConfigFiles: ({ graphQLSchema, tinaSchema, }: {
57
80
  graphQLSchema: DocumentNode;
58
81
  tinaSchema: TinaSchema;
package/dist/index.d.ts CHANGED
@@ -13,9 +13,10 @@ limitations under the License.
13
13
  export { indexDB } from './build';
14
14
  export { resolve } from './resolve';
15
15
  export { createDatabase } from './database';
16
+ export type { QueryOptions } from './database';
16
17
  import type { Database } from './database';
17
18
  export type { Database } from './database';
18
- export type { Store } from './database/store';
19
+ export type { Store } from '@tinacms/datalayer';
19
20
  export type { Bridge } from './database/bridge';
20
21
  export { sequential, assertShape } from './util';
21
22
  export { stringifyFile, parseFile } from './database/util';
package/dist/index.js CHANGED
@@ -11902,6 +11902,11 @@ var Builder = class {
11902
11902
  astBuilder.InputValueDefinition({
11903
11903
  name: "exists",
11904
11904
  type: astBuilder.TYPES.Boolean
11905
+ }),
11906
+ astBuilder.InputValueDefinition({
11907
+ name: "in",
11908
+ type: astBuilder.TYPES.Number,
11909
+ list: true
11905
11910
  })
11906
11911
  ]
11907
11912
  })
@@ -11927,6 +11932,11 @@ var Builder = class {
11927
11932
  astBuilder.InputValueDefinition({
11928
11933
  name: "exists",
11929
11934
  type: astBuilder.TYPES.Boolean
11935
+ }),
11936
+ astBuilder.InputValueDefinition({
11937
+ name: "in",
11938
+ type: astBuilder.TYPES.String,
11939
+ list: true
11930
11940
  })
11931
11941
  ]
11932
11942
  })
@@ -11949,6 +11959,11 @@ var Builder = class {
11949
11959
  astBuilder.InputValueDefinition({
11950
11960
  name: "exists",
11951
11961
  type: astBuilder.TYPES.Boolean
11962
+ }),
11963
+ astBuilder.InputValueDefinition({
11964
+ name: "in",
11965
+ type: astBuilder.TYPES.String,
11966
+ list: true
11952
11967
  })
11953
11968
  ]
11954
11969
  })
@@ -12256,6 +12271,10 @@ var listArgs = [
12256
12271
  astBuilder.InputValueDefinition({
12257
12272
  name: "last",
12258
12273
  type: astBuilder.TYPES.Number
12274
+ }),
12275
+ astBuilder.InputValueDefinition({
12276
+ name: "sort",
12277
+ type: astBuilder.TYPES.String
12259
12278
  })
12260
12279
  ];
12261
12280
  var filterSelections = (arr) => {
@@ -12370,7 +12389,7 @@ var validateField = async (field) => {
12370
12389
 
12371
12390
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/graphql/package.json
12372
12391
  var name = "@tinacms/graphql";
12373
- var version = "0.59.7";
12392
+ var version = "0.59.10";
12374
12393
  var main = "dist/index.js";
12375
12394
  var typings = "dist/index.d.ts";
12376
12395
  var files = [
@@ -12415,6 +12434,8 @@ var scripts = {
12415
12434
  test: "jest"
12416
12435
  };
12417
12436
  var dependencies = {
12437
+ "@graphql-tools/relay-operation-optimizer": "^6.4.1",
12438
+ "@tinacms/datalayer": "workspace:*",
12418
12439
  "body-parser": "^1.19.0",
12419
12440
  cors: "^2.8.5",
12420
12441
  dataloader: "^2.0.0",
@@ -12430,6 +12451,7 @@ var dependencies = {
12430
12451
  "graphql-type-json": "^0.3.2",
12431
12452
  "gray-matter": "^4.0.2",
12432
12453
  "js-yaml": "^3.14.0",
12454
+ leveldown: "^6.1.0",
12433
12455
  lodash: "^4.17.20",
12434
12456
  mdast: "^3.0.0",
12435
12457
  "mdast-util-from-markdown": "^1.0.0",
@@ -12437,7 +12459,6 @@ var dependencies = {
12437
12459
  "mdast-util-mdx-expression": "^1.1.0",
12438
12460
  "mdast-util-to-markdown": "^1.2.1",
12439
12461
  "micromark-extension-mdxjs": "^1.0.0",
12440
- mocha: "^9.1.1",
12441
12462
  "normalize-path": "^3.0.0",
12442
12463
  prettier: "^2.2.1",
12443
12464
  "rehype-format": "^3.1.0",
@@ -12472,7 +12493,6 @@ var devDependencies = {
12472
12493
  "@types/fs-extra": "^9.0.2",
12473
12494
  "@types/jest": "^26.0.4",
12474
12495
  "@types/js-yaml": "^3.12.5",
12475
- "@types/level": "^6.0.0",
12476
12496
  "@types/lodash": "^4.14.161",
12477
12497
  "@types/lodash.camelcase": "^4.3.6",
12478
12498
  "@types/lodash.upperfirst": "^4.3.6",
@@ -12753,6 +12773,17 @@ var _buildSchema = async (builder, tinaSchema) => {
12753
12773
  const queryTypeDefinitionFields = [];
12754
12774
  const mutationTypeDefinitionFields = [];
12755
12775
  const collections = tinaSchema.getCollections();
12776
+ queryTypeDefinitionFields.push(astBuilder.FieldDefinition({
12777
+ name: "getOptimizedQuery",
12778
+ args: [
12779
+ astBuilder.InputValueDefinition({
12780
+ name: "queryString",
12781
+ type: astBuilder.TYPES.String,
12782
+ required: true
12783
+ })
12784
+ ],
12785
+ type: astBuilder.TYPES.String
12786
+ }));
12756
12787
  queryTypeDefinitionFields.push(await builder.buildCollectionDefinition(collections));
12757
12788
  queryTypeDefinitionFields.push(await builder.buildMultiCollectionDefinition(collections));
12758
12789
  queryTypeDefinitionFields.push(await builder.multiNodeDocument());
@@ -20345,6 +20376,7 @@ var defaultNodeTypes = {
20345
20376
  delete_mark: plateElements.MARK_STRIKETHROUGH,
20346
20377
  inline_code_mark: plateElements.ELEMENT_CODE_LINE,
20347
20378
  thematic_break: plateElements.ELEMENT_HR,
20379
+ break: "break",
20348
20380
  image: plateElements.ELEMENT_IMAGE
20349
20381
  };
20350
20382
  function remarkToSlate(node) {
@@ -20442,6 +20474,8 @@ function remarkToSlate(node) {
20442
20474
  return __spreadProps(__spreadValues({}, node), {
20443
20475
  children: void 0
20444
20476
  });
20477
+ case "break":
20478
+ return { type: types.break, children: [{ type: "text", text: "" }] };
20445
20479
  default:
20446
20480
  console.log("unknown", node);
20447
20481
  return { type: "text", text: "" };
@@ -21883,6 +21917,9 @@ var allChildrenEmpty = (children) => {
21883
21917
  return false;
21884
21918
  };
21885
21919
  var stringifyChildren = (children, field) => {
21920
+ if (!children) {
21921
+ return [];
21922
+ }
21886
21923
  return children.map((child) => stringify(child, field)).filter(Boolean);
21887
21924
  };
21888
21925
  var stringify = (node, field) => {
@@ -22232,6 +22269,10 @@ ${out}
22232
22269
  } catch (e) {
22233
22270
  console.log(e);
22234
22271
  }
22272
+ case "break":
22273
+ return {
22274
+ type: "break"
22275
+ };
22235
22276
  case "text":
22236
22277
  if (node == null ? void 0 : node.code) {
22237
22278
  return {
@@ -22258,7 +22299,102 @@ ${out}
22258
22299
  };
22259
22300
 
22260
22301
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/graphql/src/resolver/index.ts
22261
- var import_flat = __toModule(require("flat"));
22302
+ var import_datalayer = __toModule(require("@tinacms/datalayer"));
22303
+
22304
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/graphql/src/resolver/filter-utils.ts
22305
+ var resolveReferences = async (filter, fields, resolver2) => {
22306
+ for (const fieldKey of Object.keys(filter)) {
22307
+ const fieldDefinition = fields.find((f) => f.name === fieldKey);
22308
+ if (fieldDefinition) {
22309
+ if (fieldDefinition.type === "reference") {
22310
+ const { edges, values } = await resolver2(filter, fieldDefinition);
22311
+ if (edges.length === 1) {
22312
+ filter[fieldKey] = {
22313
+ eq: values[0]
22314
+ };
22315
+ } else if (edges.length > 1) {
22316
+ filter[fieldKey] = {
22317
+ in: values
22318
+ };
22319
+ } else {
22320
+ filter[fieldKey] = {
22321
+ eq: "___null___"
22322
+ };
22323
+ }
22324
+ } else if (fieldDefinition.type === "object") {
22325
+ if (fieldDefinition.templates) {
22326
+ const globalTemplates = {};
22327
+ for (const template of fieldDefinition.templates) {
22328
+ if (typeof template === "string") {
22329
+ globalTemplates[template] = 1;
22330
+ }
22331
+ }
22332
+ for (const templateName of Object.keys(filter[fieldKey])) {
22333
+ if (templateName in globalTemplates) {
22334
+ throw new Error("Global templates not yet supported for queries");
22335
+ }
22336
+ const template = fieldDefinition.templates.find((template2) => !(typeof template2 === "string") && template2.name === templateName);
22337
+ if (template) {
22338
+ await resolveReferences(filter[fieldKey][templateName], template.fields, resolver2);
22339
+ } else {
22340
+ throw new Error(`Template ${templateName} not found`);
22341
+ }
22342
+ }
22343
+ } else {
22344
+ await resolveReferences(filter[fieldKey], fieldDefinition.fields, resolver2);
22345
+ }
22346
+ }
22347
+ } else {
22348
+ throw new Error(`Unable to find field ${fieldKey}`);
22349
+ }
22350
+ }
22351
+ };
22352
+ var collectConditionsForChildFields = (filterNode, fields, pathExpression, collectCondition) => {
22353
+ for (const childFieldName of Object.keys(filterNode)) {
22354
+ const childField = fields.find((field) => field.name === childFieldName);
22355
+ if (!childField) {
22356
+ throw new Error(`Unable to find type for field ${childFieldName}`);
22357
+ }
22358
+ collectConditionsForField(childFieldName, childField, filterNode[childFieldName], pathExpression, collectCondition);
22359
+ }
22360
+ };
22361
+ var collectConditionsForObjectField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
22362
+ if (field.list && field.templates) {
22363
+ const globalTemplates = {};
22364
+ for (const template of field.templates) {
22365
+ if (typeof template === "string") {
22366
+ globalTemplates[template] = 1;
22367
+ }
22368
+ }
22369
+ for (const [filterKey, childFilterNode] of Object.entries(filterNode)) {
22370
+ if (filterKey in globalTemplates) {
22371
+ throw new Error("Global templates not yet supported for queries");
22372
+ }
22373
+ const template = field.templates.find((template2) => !(typeof template2 === "string") && template2.name === filterKey);
22374
+ const jsonPath = `${fieldName}[?(@._template=="${filterKey}")]`;
22375
+ const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : jsonPath;
22376
+ collectConditionsForChildFields(childFilterNode, template.fields, filterPath, collectCondition);
22377
+ }
22378
+ } else {
22379
+ const jsonPath = `${fieldName}${field.list ? "[*]" : ""}`;
22380
+ const filterPath = pathExpression ? `${pathExpression}.${jsonPath}` : `${jsonPath}`;
22381
+ collectConditionsForChildFields(filterNode, field.fields, filterPath, collectCondition);
22382
+ }
22383
+ };
22384
+ var collectConditionsForField = (fieldName, field, filterNode, pathExpression, collectCondition) => {
22385
+ if (field.type === "object") {
22386
+ collectConditionsForObjectField(fieldName, field, filterNode, pathExpression, collectCondition);
22387
+ } else {
22388
+ collectCondition({
22389
+ filterPath: pathExpression ? `${pathExpression}.${fieldName}` : fieldName,
22390
+ filterExpression: __spreadValues({
22391
+ _type: field.type
22392
+ }, filterNode)
22393
+ });
22394
+ }
22395
+ };
22396
+
22397
+ // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/graphql/src/resolver/index.ts
22262
22398
  var createResolver2 = (args) => {
22263
22399
  return new Resolver(args);
22264
22400
  };
@@ -22287,11 +22423,13 @@ var Resolver = class {
22287
22423
  data: rawData,
22288
22424
  collection
22289
22425
  });
22290
- const basename = import_path3.default.basename(fullPath);
22291
- const extension2 = import_path3.default.extname(fullPath);
22292
- const filename = basename.replace(extension2, "");
22426
+ const {
22427
+ base: basename,
22428
+ ext: extension2,
22429
+ name: filename
22430
+ } = import_path3.default.parse(fullPath);
22293
22431
  const relativePath = fullPath.replace("\\", "/").replace(collection.path, "").replace(/^\/|\/$/g, "");
22294
- const breadcrumbs = filename.split("/");
22432
+ const breadcrumbs = relativePath.replace(extension2, "").split("/");
22295
22433
  const form = {
22296
22434
  label: collection.label,
22297
22435
  name: basename,
@@ -22556,46 +22694,76 @@ var Resolver = class {
22556
22694
  const collection = this.tinaSchema.getCollection(collectionName);
22557
22695
  return this.database.store.glob(collection.path, this.getDocument);
22558
22696
  };
22697
+ this.referenceResolver = async (filter, fieldDefinition) => {
22698
+ const referencedCollection = this.tinaSchema.getCollection(fieldDefinition.collections[0]);
22699
+ if (!referencedCollection) {
22700
+ throw new Error(`Unable to find collection for ${fieldDefinition.collections[0]} querying ${fieldDefinition.name}`);
22701
+ }
22702
+ const sortKeys = Object.keys(filter[fieldDefinition.name][referencedCollection.name]);
22703
+ const resolvedCollectionConnection = await this.resolveCollectionConnection({
22704
+ args: {
22705
+ sort: sortKeys.length === 1 ? sortKeys[0] : void 0,
22706
+ filter: __spreadValues({}, filter[fieldDefinition.name][referencedCollection.name]),
22707
+ first: -1
22708
+ },
22709
+ collection: referencedCollection,
22710
+ hydrator: (path6) => path6
22711
+ });
22712
+ const { edges } = resolvedCollectionConnection;
22713
+ const values = edges.map((edge) => edge.node);
22714
+ return { edges, values };
22715
+ };
22559
22716
  this.resolveCollectionConnection = async ({
22560
22717
  args,
22561
- lookup
22718
+ collection,
22719
+ hydrator
22562
22720
  }) => {
22563
- let documents;
22564
- if (args.filter) {
22565
- const queries = [];
22566
- const flattenedArgs = (0, import_flat.default)(args.filter, { delimiter: "#" });
22567
- Object.entries(flattenedArgs).map(([key2, value]) => {
22568
- const keys2 = key2.split("#");
22569
- const maybeTemplateName = keys2[0];
22570
- const realKey = keys2.slice(0, keys2.length - 1).join("#");
22571
- const collection = this.tinaSchema.getCollection(lookup.collection);
22572
- let templateName = collection.name;
22573
- if (collection.templates) {
22574
- const template = collection.templates.find((template2) => {
22575
- if (typeof template2 === "string") {
22576
- throw new Error("Global templates not yet supported for queries");
22721
+ let edges;
22722
+ let pageInfo;
22723
+ if (args.filter || args.sort) {
22724
+ let conditions;
22725
+ if (args.filter) {
22726
+ if (collection.fields) {
22727
+ conditions = await this.resolveFilterConditions(args.filter, collection.fields, collection.name);
22728
+ } else if (collection.templates) {
22729
+ for (const templateName of Object.keys(args.filter)) {
22730
+ const template = collection.templates.find((template2) => template2.name === templateName);
22731
+ if (template) {
22732
+ conditions = await this.resolveFilterConditions(args.filter[templateName], template.fields, `${collection.name}.${templateName}`);
22733
+ } else {
22734
+ throw new Error(`Error template not found: ${templateName} in collection ${collection.name}`);
22577
22735
  }
22578
- return template2.name === maybeTemplateName;
22579
- });
22580
- if (typeof template === "string") {
22581
- throw new Error("Global templates not yet supported for queries");
22582
- }
22583
- if (template) {
22584
- templateName = template.name;
22585
22736
  }
22586
22737
  }
22587
- queries.push(`__attribute__${lookup.collection}#${templateName}#${realKey}#${value}`);
22588
- });
22589
- documents = await this.database.query(queries, this.getDocument);
22738
+ }
22739
+ const queryOptions = {
22740
+ filterChain: (0, import_datalayer.makeFilterChain)({
22741
+ conditions: conditions || []
22742
+ }),
22743
+ collection: collection.name,
22744
+ sort: args.sort,
22745
+ first: args.first,
22746
+ last: args.last,
22747
+ before: args.before,
22748
+ after: args.after
22749
+ };
22750
+ const result = await this.database.query(queryOptions, hydrator ? hydrator : this.getDocument);
22751
+ edges = result.edges;
22752
+ pageInfo = result.pageInfo;
22590
22753
  } else {
22591
- const collection = await this.tinaSchema.getCollection(lookup.collection);
22592
- documents = await this.database.store.glob(collection.path, this.getDocument);
22754
+ edges = (await this.database.store.glob(collection.path, this.getDocument)).map((document3) => ({
22755
+ node: document3
22756
+ }));
22593
22757
  }
22594
22758
  return {
22595
- totalCount: documents.length,
22596
- edges: documents.map((document3) => {
22597
- return { node: document3 };
22598
- })
22759
+ totalCount: edges.length,
22760
+ edges,
22761
+ pageInfo: pageInfo || {
22762
+ hasPreviousPage: false,
22763
+ hasNextPage: false,
22764
+ startCursor: "",
22765
+ endCursor: ""
22766
+ }
22599
22767
  };
22600
22768
  };
22601
22769
  this.buildFieldMutations = (fieldParams, template) => {
@@ -22729,6 +22897,7 @@ var Resolver = class {
22729
22897
  } = _d, field = __objRest(_d, [
22730
22898
  "namespace"
22731
22899
  ]);
22900
+ field.parentTypename = NAMER.dataTypeName(namespace.filter((_6, i) => i < namespace.length - 1));
22732
22901
  const extraFields = field.ui || {};
22733
22902
  switch (field.type) {
22734
22903
  case "number":
@@ -22856,6 +23025,27 @@ var Resolver = class {
22856
23025
  this.database = init.database;
22857
23026
  this.tinaSchema = init.tinaSchema;
22858
23027
  }
23028
+ async resolveFilterConditions(filter, fields, collectionName) {
23029
+ const conditions = [];
23030
+ const conditionCollector = (condition) => {
23031
+ if (!condition.filterPath) {
23032
+ throw new Error("Error parsing filter - unable to generate filterPath");
23033
+ }
23034
+ if (!condition.filterExpression) {
23035
+ throw new Error(`Error parsing filter - missing expression for ${condition.filterPath}`);
23036
+ }
23037
+ conditions.push(condition);
23038
+ };
23039
+ await resolveReferences(filter, fields, this.referenceResolver);
23040
+ for (const fieldName of Object.keys(filter)) {
23041
+ const field = fields.find((field2) => field2.name === fieldName);
23042
+ if (!field) {
23043
+ throw new Error(`${fieldName} not found in collection ${collectionName}`);
23044
+ }
23045
+ collectConditionsForField(fieldName, field, filter[fieldName], "", conditionCollector);
23046
+ }
23047
+ return conditions;
23048
+ }
22859
23049
  };
22860
23050
  var resolveDateInput = (value) => {
22861
23051
  const date = new Date(value);
@@ -22866,6 +23056,7 @@ var resolveDateInput = (value) => {
22866
23056
  };
22867
23057
 
22868
23058
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/graphql/src/resolve.ts
23059
+ var import_relay_operation_optimizer = __toModule(require("@graphql-tools/relay-operation-optimizer"));
22869
23060
  var resolve = async ({
22870
23061
  query,
22871
23062
  variables,
@@ -22966,6 +23157,18 @@ var resolve = async ({
22966
23157
  if (info.fieldName === "getDocumentFields") {
22967
23158
  return resolver2.getDocumentFields();
22968
23159
  }
23160
+ if (info.fieldName === "getOptimizedQuery") {
23161
+ try {
23162
+ const [optimizedQuery] = (0, import_relay_operation_optimizer.optimizeDocuments)(info.schema, [(0, import_graphql3.parse)(args.queryString)], {
23163
+ assumeValid: true,
23164
+ includeFragments: false,
23165
+ noLocation: true
23166
+ });
23167
+ return (0, import_graphql3.print)(optimizedQuery);
23168
+ } catch (e) {
23169
+ throw new Error(`Invalid query provided, Error message: ${e.message}`);
23170
+ }
23171
+ }
22969
23172
  if (!lookup) {
22970
23173
  return value;
22971
23174
  }
@@ -23041,7 +23244,10 @@ var resolve = async ({
23041
23244
  }
23042
23245
  return result;
23043
23246
  case "collectionDocumentList":
23044
- return resolver2.resolveCollectionConnection({ args, lookup });
23247
+ return resolver2.resolveCollectionConnection({
23248
+ args,
23249
+ collection: tinaSchema.getCollection(lookup.collection)
23250
+ });
23045
23251
  case "unionData":
23046
23252
  return value;
23047
23253
  default:
@@ -23350,7 +23556,7 @@ var parseFile = (content3, format, yupSchema) => {
23350
23556
  };
23351
23557
 
23352
23558
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/graphql/src/database/index.ts
23353
- var import_lodash7 = __toModule(require("lodash"));
23559
+ var import_datalayer2 = __toModule(require("@tinacms/datalayer"));
23354
23560
  var createDatabase = async (config) => {
23355
23561
  return new Database(__spreadProps(__spreadValues({}, config), {
23356
23562
  bridge: config.bridge,
@@ -23401,27 +23607,42 @@ var Database = class {
23401
23607
  };
23402
23608
  this.addPendingDocument = async (filepath, data) => {
23403
23609
  const { stringifiedFile, payload, keepTemplateKey } = await this.stringifyFile(filepath, data);
23610
+ const tinaSchema = await this.getSchema();
23611
+ const collection = tinaSchema.schema.collections.find((collection2) => filepath.startsWith(collection2.path));
23612
+ let collectionIndexDefinitions;
23613
+ if (collection) {
23614
+ const indexDefinitions = await this.getIndexDefinitions();
23615
+ collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
23616
+ }
23404
23617
  if (this.store.supportsSeeding()) {
23405
23618
  await this.bridge.put(filepath, stringifiedFile);
23406
23619
  }
23407
- await this.store.put(filepath, payload, keepTemplateKey);
23620
+ await this.store.put(filepath, payload, {
23621
+ keepTemplateKey,
23622
+ collection: collection.name,
23623
+ indexDefinitions: collectionIndexDefinitions
23624
+ });
23408
23625
  };
23409
23626
  this.put = async (filepath, data) => {
23410
23627
  if (SYSTEM_FILES.includes(filepath)) {
23411
23628
  throw new Error(`Unexpected put for config file ${filepath}`);
23412
23629
  } else {
23630
+ const tinaSchema = await this.getSchema();
23631
+ const collection = tinaSchema.schema.collections.find((collection2) => filepath.startsWith(collection2.path));
23632
+ let collectionIndexDefinitions;
23633
+ if (collection) {
23634
+ const indexDefinitions = await this.getIndexDefinitions();
23635
+ collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
23636
+ }
23413
23637
  const { stringifiedFile, payload, keepTemplateKey } = await this.stringifyFile(filepath, data);
23414
23638
  if (this.store.supportsSeeding()) {
23415
23639
  await this.bridge.put(filepath, stringifiedFile);
23416
23640
  }
23417
- if (this.store.supportsIndexing()) {
23418
- await indexDocument({
23419
- filepath,
23420
- data,
23421
- database: this
23422
- });
23423
- }
23424
- await this.store.put(filepath, payload, keepTemplateKey);
23641
+ await this.store.put(filepath, payload, {
23642
+ keepTemplateKey,
23643
+ collection: collection.name,
23644
+ indexDefinitions: collectionIndexDefinitions
23645
+ });
23425
23646
  }
23426
23647
  return true;
23427
23648
  };
@@ -23508,6 +23729,56 @@ var Database = class {
23508
23729
  this.tinaSchema = await createSchema({ schema });
23509
23730
  return this.tinaSchema;
23510
23731
  };
23732
+ this.getIndexDefinitions = async () => {
23733
+ if (!this.collectionIndexDefinitions) {
23734
+ await new Promise(async (resolve2, reject) => {
23735
+ try {
23736
+ const schema = await this.getSchema();
23737
+ const collections = schema.getCollections();
23738
+ for (const collection of collections) {
23739
+ const indexDefinitions = {
23740
+ [import_datalayer2.DEFAULT_COLLECTION_SORT_KEY]: { fields: [] }
23741
+ };
23742
+ if (collection.fields) {
23743
+ for (const field of collection.fields) {
23744
+ if (field.indexed !== void 0 && field.indexed === false || field.type === "object") {
23745
+ continue;
23746
+ }
23747
+ indexDefinitions[field.name] = {
23748
+ fields: [
23749
+ {
23750
+ name: field.name,
23751
+ type: field.type,
23752
+ pad: field.type === "number" ? { fillString: "0", maxLength: import_datalayer2.DEFAULT_NUMERIC_LPAD } : void 0
23753
+ }
23754
+ ]
23755
+ };
23756
+ }
23757
+ }
23758
+ if (collection.indexes) {
23759
+ for (const index2 of collection.indexes) {
23760
+ indexDefinitions[index2.name] = {
23761
+ fields: index2.fields.map((indexField) => {
23762
+ var _a;
23763
+ return {
23764
+ name: indexField.name,
23765
+ type: (_a = collection.fields.find((field) => indexField.name === field.name)) == null ? void 0 : _a.type
23766
+ };
23767
+ })
23768
+ };
23769
+ }
23770
+ }
23771
+ this.collectionIndexDefinitions = this.collectionIndexDefinitions || {};
23772
+ this.collectionIndexDefinitions[collection.name] = indexDefinitions;
23773
+ }
23774
+ resolve2();
23775
+ } catch (err) {
23776
+ reject(err);
23777
+ }
23778
+ });
23779
+ }
23780
+ return this.collectionIndexDefinitions;
23781
+ };
23511
23782
  this.documentExists = async (fullpath) => {
23512
23783
  try {
23513
23784
  await this.get(fullpath);
@@ -23516,8 +23787,52 @@ var Database = class {
23516
23787
  }
23517
23788
  return true;
23518
23789
  };
23519
- this.query = async (queryStrings, hydrator) => {
23520
- return await this.store.query(queryStrings, hydrator);
23790
+ this.query = async (queryOptions, hydrator) => {
23791
+ const { first, after, last, before, sort, collection, filterChain } = queryOptions;
23792
+ const storeQueryOptions = {
23793
+ sort,
23794
+ collection,
23795
+ filterChain
23796
+ };
23797
+ if (first) {
23798
+ storeQueryOptions.limit = first;
23799
+ } else if (last) {
23800
+ storeQueryOptions.limit = last;
23801
+ } else {
23802
+ storeQueryOptions.limit = 10;
23803
+ }
23804
+ if (after) {
23805
+ storeQueryOptions.gt = (0, import_datalayer2.atob)(after);
23806
+ } else if (before) {
23807
+ storeQueryOptions.lt = (0, import_datalayer2.atob)(before);
23808
+ }
23809
+ if (last) {
23810
+ storeQueryOptions.reverse = true;
23811
+ }
23812
+ const indexDefinitions = await this.getIndexDefinitions();
23813
+ storeQueryOptions.indexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[queryOptions.collection];
23814
+ if (!storeQueryOptions.indexDefinitions) {
23815
+ throw new Error(`No indexDefinitions for collection ${queryOptions.collection}`);
23816
+ }
23817
+ const {
23818
+ edges,
23819
+ pageInfo: { hasPreviousPage, hasNextPage, startCursor, endCursor }
23820
+ } = await this.store.query(storeQueryOptions);
23821
+ return {
23822
+ edges: await sequential(edges, async (edge) => {
23823
+ const node = await hydrator(edge.path);
23824
+ return {
23825
+ node,
23826
+ cursor: (0, import_datalayer2.btoa)(edge.cursor)
23827
+ };
23828
+ }),
23829
+ pageInfo: {
23830
+ hasPreviousPage,
23831
+ hasNextPage,
23832
+ startCursor: (0, import_datalayer2.btoa)(startCursor),
23833
+ endCursor: (0, import_datalayer2.btoa)(endCursor)
23834
+ }
23835
+ };
23521
23836
  };
23522
23837
  this.putConfigFiles = async ({
23523
23838
  graphQLSchema,
@@ -23534,7 +23849,7 @@ var Database = class {
23534
23849
  }) => {
23535
23850
  const lookup = JSON.parse(await this.bridge.get(import_path4.default.join(GENERATED_FOLDER, "_lookup.json")));
23536
23851
  if (this.store.supportsSeeding()) {
23537
- this.store.clear();
23852
+ await this.store.clear();
23538
23853
  await this.store.seed(import_path4.default.join(GENERATED_FOLDER, "_graphql.json"), graphQLSchema);
23539
23854
  await this.store.seed(import_path4.default.join(GENERATED_FOLDER, "_schema.json"), tinaSchema.schema);
23540
23855
  await this.store.seed(import_path4.default.join(GENERATED_FOLDER, "_lookup.json"), lookup);
@@ -23546,13 +23861,32 @@ var Database = class {
23546
23861
  }
23547
23862
  };
23548
23863
  this.indexContentByPaths = async (documentPaths) => {
23549
- await _indexContent(this, documentPaths);
23864
+ const pathsByCollection = {};
23865
+ const nonCollectionPaths = [];
23866
+ const collections = {};
23867
+ const tinaSchema = await this.getSchema();
23868
+ for (const documentPath of documentPaths) {
23869
+ const collection = tinaSchema.schema.collections.find((collection2) => documentPath.startsWith(collection2.path));
23870
+ if (collection) {
23871
+ if (!pathsByCollection[collection.name]) {
23872
+ pathsByCollection[collection.name] = [];
23873
+ }
23874
+ collections[collection.name] = collection;
23875
+ pathsByCollection[collection.name].push(documentPath);
23876
+ } else {
23877
+ nonCollectionPaths.push(documentPath);
23878
+ }
23879
+ }
23880
+ for (const collection of Object.keys(pathsByCollection)) {
23881
+ await _indexContent(this, pathsByCollection[collection], collections[collection]);
23882
+ }
23883
+ await _indexContent(this, nonCollectionPaths);
23550
23884
  };
23551
23885
  this._indexAllContent = async () => {
23552
23886
  const tinaSchema = await this.getSchema();
23553
23887
  await sequential(tinaSchema.getCollections(), async (collection) => {
23554
23888
  const documentPaths = await this.bridge.glob(collection.path);
23555
- await _indexContent(this, documentPaths);
23889
+ await _indexContent(this, documentPaths, collection);
23556
23890
  });
23557
23891
  };
23558
23892
  this.addToLookupMap = async (lookup) => {
@@ -23575,138 +23909,31 @@ var Database = class {
23575
23909
  function hasOwnProperty2(obj, prop) {
23576
23910
  return obj.hasOwnProperty(prop);
23577
23911
  }
23578
- var _indexContent = async (database, documentPaths) => {
23912
+ var _indexContent = async (database, documentPaths, collection) => {
23913
+ let seedOptions = void 0;
23914
+ if (collection) {
23915
+ const indexDefinitions = await database.getIndexDefinitions();
23916
+ const collectionIndexDefinitions = indexDefinitions == null ? void 0 : indexDefinitions[collection.name];
23917
+ if (!collectionIndexDefinitions) {
23918
+ throw new Error(`No indexDefinitions for collection ${collection.name}`);
23919
+ }
23920
+ const numIndexes = Object.keys(collectionIndexDefinitions).length;
23921
+ if (numIndexes > 20) {
23922
+ throw new Error(`A maximum of 20 indexes are allowed per field. Currently collection ${collection.name} has ${numIndexes} indexes. Add 'indexed: false' to exclude a field from indexing.`);
23923
+ }
23924
+ seedOptions = {
23925
+ collection: collection.name,
23926
+ indexDefinitions: collectionIndexDefinitions
23927
+ };
23928
+ }
23579
23929
  await sequential(documentPaths, async (filepath) => {
23580
23930
  const dataString = await database.bridge.get(filepath);
23581
23931
  const data = parseFile(dataString, import_path4.default.extname(filepath), (yup3) => yup3.object({}));
23582
23932
  if (database.store.supportsSeeding()) {
23583
- await database.store.seed(filepath, data);
23584
- }
23585
- if (database.store.supportsIndexing()) {
23586
- return indexDocument({ filepath, data, database });
23933
+ await database.store.seed(filepath, data, seedOptions);
23587
23934
  }
23588
23935
  });
23589
23936
  };
23590
- var indexDocument = async ({
23591
- filepath,
23592
- data,
23593
- database
23594
- }) => {
23595
- var _a;
23596
- const schema = await database.getSchema();
23597
- const collection = await schema.getCollectionByFullPath(filepath);
23598
- let existingData;
23599
- try {
23600
- existingData = await database.get(filepath);
23601
- } catch (err) {
23602
- if (((_a = err.extensions) == null ? void 0 : _a["status"]) !== 404) {
23603
- throw err;
23604
- }
23605
- }
23606
- if (existingData) {
23607
- const attributesToFilterOut = await _indexCollectable({
23608
- record: filepath,
23609
- value: existingData,
23610
- field: collection,
23611
- prefix: collection.name,
23612
- database
23613
- });
23614
- await sequential(attributesToFilterOut, async (attribute) => {
23615
- const records = await database.store.get(attribute) || [];
23616
- await database.store.put(attribute, records.filter((item) => item !== filepath));
23617
- return true;
23618
- });
23619
- }
23620
- const attributes = await _indexCollectable({
23621
- record: filepath,
23622
- field: collection,
23623
- value: data,
23624
- prefix: `${lastItem(collection.namespace)}`,
23625
- database
23626
- });
23627
- await sequential(attributes, async (fieldName) => {
23628
- const existingRecords = await database.store.get(fieldName) || [];
23629
- const uniqueItems = [...new Set([...existingRecords, filepath])];
23630
- await database.store.put(fieldName, uniqueItems);
23631
- });
23632
- };
23633
- var _indexCollectable = async (_a) => {
23634
- var _b = _a, {
23635
- field,
23636
- value
23637
- } = _b, rest = __objRest(_b, [
23638
- "field",
23639
- "value"
23640
- ]);
23641
- let template;
23642
- let extra = "";
23643
- if (field.templates) {
23644
- template = field.templates.find((t) => {
23645
- if (typeof t === "string") {
23646
- throw new Error(`Global templates not yet supported`);
23647
- }
23648
- if (hasOwnProperty2(value, "_template")) {
23649
- return t.name === value._template;
23650
- } else {
23651
- throw new Error(`Expected value for collectable with multiple templates to have property _template`);
23652
- }
23653
- });
23654
- extra = `#${lastItem(template.namespace)}`;
23655
- } else {
23656
- template = field;
23657
- }
23658
- const atts = await _indexAttributes({
23659
- record: rest.record,
23660
- data: value,
23661
- prefix: `${rest.prefix}${extra}#${template.name}`,
23662
- fields: template.fields,
23663
- database: rest.database
23664
- });
23665
- return (0, import_lodash7.flatten)(atts).filter((item) => !(0, import_lodash7.isBoolean)(item));
23666
- };
23667
- var _indexAttributes = async (_a) => {
23668
- var _b = _a, {
23669
- data,
23670
- fields
23671
- } = _b, rest = __objRest(_b, [
23672
- "data",
23673
- "fields"
23674
- ]);
23675
- return sequential(fields, async (field) => {
23676
- const value = data[field.name];
23677
- if (!value) {
23678
- return true;
23679
- }
23680
- switch (field.type) {
23681
- case "boolean":
23682
- case "string":
23683
- case "number":
23684
- case "datetime":
23685
- return _indexAttribute(__spreadValues({ value, field }, rest));
23686
- case "object":
23687
- if (field.list) {
23688
- await sequential(value, async (item) => {
23689
- return _indexCollectable(__spreadValues({ field, value: item }, rest));
23690
- });
23691
- } else {
23692
- return _indexCollectable(__spreadValues({ field, value }, rest));
23693
- }
23694
- return true;
23695
- case "reference":
23696
- return _indexAttribute(__spreadValues({ value, field }, rest));
23697
- }
23698
- return true;
23699
- });
23700
- };
23701
- var _indexAttribute = async ({
23702
- value,
23703
- prefix,
23704
- field
23705
- }) => {
23706
- const stringValue = value.toString().substr(0, 100);
23707
- const fieldName = `__attribute__${prefix}#${field.name}#${stringValue}`;
23708
- return fieldName;
23709
- };
23710
23937
 
23711
23938
  // pnp:/home/runner/work/tinacms/tinacms/packages/@tinacms/graphql/src/index.ts
23712
23939
  var buildSchema = async (rootPath, database) => {
@@ -96,6 +96,7 @@ export interface NodeTypes {
96
96
  delete_mark: string;
97
97
  inline_code_mark: string;
98
98
  thematic_break: string;
99
+ break: string;
99
100
  }
100
101
  export declare type SlateNodeType = {
101
102
  type: 'heading_one';
@@ -0,0 +1,22 @@
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 { ReferenceTypeInner, TinaFieldInner } from '../types';
14
+ import type { FilterCondition } from '@tinacms/datalayer';
15
+ export declare type ReferenceResolver = (filter: Record<string, object>, fieldDefinition: ReferenceTypeInner) => Promise<{
16
+ edges: {
17
+ node: any;
18
+ }[];
19
+ values: any[];
20
+ }>;
21
+ export declare const resolveReferences: (filter: any, fields: TinaFieldInner<false>[], resolver: ReferenceResolver) => Promise<void>;
22
+ export declare const collectConditionsForField: (fieldName: string, field: TinaFieldInner<false>, filterNode: Record<string, object>, pathExpression: string, collectCondition: (condition: FilterCondition) => void) => void;
@@ -11,8 +11,9 @@ See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
13
  import { TinaSchema } from '../schema';
14
- import { Database, CollectionDocumentListLookup } from '../database';
15
- import type { Collectable, TinaCloudCollection } from '../types';
14
+ import { Database } from '../database';
15
+ import type { Collectable, ReferenceTypeWithNamespace, TinaCloudCollection } from '../types';
16
+ import { TinaFieldInner } from '../types';
16
17
  interface ResolverConfig {
17
18
  database: Database;
18
19
  tinaSchema: TinaSchema;
@@ -28,32 +29,34 @@ export declare class Resolver {
28
29
  tinaSchema: TinaSchema;
29
30
  constructor(init: ResolverConfig);
30
31
  resolveCollection: (collectionName: string, hasDocuments?: boolean) => Promise<{
31
- fields: string | import("../types").TinaFieldInner<true>[];
32
+ fields: string | TinaFieldInner<true>[];
32
33
  templates?: undefined;
33
- references?: import("../types").ReferenceTypeWithNamespace[];
34
+ references?: ReferenceTypeWithNamespace[];
34
35
  namespace: string[];
35
36
  label?: string;
36
37
  name: string;
37
38
  path: string;
38
39
  format?: "json" | "md" | "markdown" | "mdx";
39
40
  match?: string;
41
+ indexes?: import("../types").TinaIndex[];
40
42
  documents: {};
41
43
  } | {
42
44
  templates: (string | {
43
45
  label: string;
44
46
  name: string;
45
- fields: import("../types").TinaFieldInner<true>[];
47
+ fields: TinaFieldInner<true>[];
46
48
  ui?: object;
47
49
  namespace: string[];
48
50
  })[];
49
51
  fields?: undefined;
50
- references?: import("../types").ReferenceTypeWithNamespace[];
52
+ references?: ReferenceTypeWithNamespace[];
51
53
  namespace: string[];
52
54
  label?: string;
53
55
  name: string;
54
56
  path: string;
55
57
  format?: "json" | "md" | "markdown" | "mdx";
56
58
  match?: string;
59
+ indexes?: import("../types").TinaIndex[];
57
60
  documents: {};
58
61
  }>;
59
62
  getDocument: (fullPath: unknown) => Promise<{
@@ -243,12 +246,16 @@ export declare class Resolver {
243
246
  }[];
244
247
  }>;
245
248
  getDocumentsForCollection: (collectionName: string) => Promise<string[]>;
246
- resolveCollectionConnection: ({ args, lookup, }: {
247
- args: Record<string, Record<string, object>>;
248
- lookup: CollectionDocumentListLookup;
249
+ private referenceResolver;
250
+ private resolveFilterConditions;
251
+ resolveCollectionConnection: ({ args, collection, hydrator, }: {
252
+ args: Record<string, Record<string, object> | string | number>;
253
+ collection: TinaCloudCollection<true>;
254
+ hydrator?: (string: any) => any;
249
255
  }) => Promise<{
250
256
  totalCount: any;
251
257
  edges: any;
258
+ pageInfo: any;
252
259
  }>;
253
260
  private buildFieldMutations;
254
261
  private resolveFieldData;
@@ -11,7 +11,7 @@ See the License for the specific language governing permissions and
11
11
  limitations under the License.
12
12
  */
13
13
  import { Database } from '../database';
14
- import type { Store } from '../database/store';
14
+ import type { Store } from '@tinacms/datalayer';
15
15
  import type { TinaCloudSchema } from '../types';
16
16
  export declare const setup: (rootPath: string, schema: TinaCloudSchema<false>, store: Store) => Promise<{
17
17
  database: Database;
package/dist/types.d.ts CHANGED
@@ -36,6 +36,7 @@ interface BaseCollection {
36
36
  path: string;
37
37
  format?: FormatType;
38
38
  match?: string;
39
+ indexes?: TinaIndex[];
39
40
  }
40
41
  declare type CollectionTemplates<WithNamespace extends boolean> = WithNamespace extends true ? CollectionTemplatesWithNamespace<WithNamespace> : CollectionTemplatesInner<WithNamespace>;
41
42
  interface CollectionTemplatesInner<WithNamespace extends boolean> extends BaseCollection {
@@ -60,6 +61,12 @@ interface CollectionFieldsInner<WithNamespace extends boolean> extends BaseColle
60
61
  templates?: undefined;
61
62
  }
62
63
  export declare type TinaFieldInner<WithNamespace extends boolean> = ScalarType<WithNamespace> | ObjectType<WithNamespace> | ReferenceType<WithNamespace> | RichType<WithNamespace>;
64
+ export declare type TinaIndex = {
65
+ name: string;
66
+ fields: {
67
+ name: string;
68
+ }[];
69
+ };
63
70
  export declare type TinaFieldBase = TinaFieldInner<false>;
64
71
  export declare type TinaFieldEnriched = TinaFieldInner<true>;
65
72
  interface TinaField {
@@ -68,6 +75,7 @@ interface TinaField {
68
75
  description?: string;
69
76
  required?: boolean;
70
77
  list?: boolean;
78
+ indexed?: boolean;
71
79
  /**
72
80
  * Any items passed to the UI field will be passed to the underlying field.
73
81
  * NOTE: only serializable values are supported, so functions like `validate`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tinacms/graphql",
3
- "version": "0.59.7",
3
+ "version": "0.59.10",
4
4
  "main": "dist/index.js",
5
5
  "typings": "dist/index.d.ts",
6
6
  "files": [
@@ -45,6 +45,8 @@
45
45
  "test": "jest"
46
46
  },
47
47
  "dependencies": {
48
+ "@graphql-tools/relay-operation-optimizer": "^6.4.1",
49
+ "@tinacms/datalayer": "0.1.0",
48
50
  "body-parser": "^1.19.0",
49
51
  "cors": "^2.8.5",
50
52
  "dataloader": "^2.0.0",
@@ -60,6 +62,7 @@
60
62
  "graphql-type-json": "^0.3.2",
61
63
  "gray-matter": "^4.0.2",
62
64
  "js-yaml": "^3.14.0",
65
+ "leveldown": "^6.1.0",
63
66
  "lodash": "^4.17.20",
64
67
  "mdast": "^3.0.0",
65
68
  "mdast-util-from-markdown": "^1.0.0",
@@ -67,7 +70,6 @@
67
70
  "mdast-util-mdx-expression": "^1.1.0",
68
71
  "mdast-util-to-markdown": "^1.2.1",
69
72
  "micromark-extension-mdxjs": "^1.0.0",
70
- "mocha": "^9.1.1",
71
73
  "normalize-path": "^3.0.0",
72
74
  "prettier": "^2.2.1",
73
75
  "rehype-format": "^3.1.0",
@@ -94,15 +96,14 @@
94
96
  "directory": "packages/tina-graphql"
95
97
  },
96
98
  "devDependencies": {
97
- "@tinacms/datalayer": "0.0.2",
98
- "@tinacms/scripts": "0.50.6",
99
+ "@tinacms/datalayer": "0.1.0",
100
+ "@tinacms/scripts": "0.50.7",
99
101
  "@types/cors": "^2.8.7",
100
102
  "@types/estree": "^0.0.50",
101
103
  "@types/express": "^4.17.8",
102
104
  "@types/fs-extra": "^9.0.2",
103
105
  "@types/jest": "^26.0.4",
104
106
  "@types/js-yaml": "^3.12.5",
105
- "@types/level": "^6.0.0",
106
107
  "@types/lodash": "^4.14.161",
107
108
  "@types/lodash.camelcase": "^4.3.6",
108
109
  "@types/lodash.upperfirst": "^4.3.6",
@@ -1,72 +0,0 @@
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
- export interface Store {
14
- glob(pattern: string, hydrator?: (fullPath: string) => Promise<object>): Promise<string[]>;
15
- get<T extends object>(filepath: string): Promise<T>;
16
- clear(): void;
17
- /**
18
- *
19
- * @param queryStrings
20
- * Queries are currently structured as prefixed keys where that last portion
21
- * of the key is the value provided by the query
22
- * ```graphql
23
- * {
24
- * getPostsList(filter: {
25
- * title: {
26
- * eq: "Hello, World"
27
- * }
28
- * }) {
29
- * ...
30
- * }
31
- * }
32
- * ```
33
- * Would equate to a query string of:
34
- * ```
35
- * __attribute__#posts#posts#title#Hello, World
36
- * ```
37
- * This can be used by a data store as a secondary index of sorts
38
- *
39
- * It's important to note that for now each query string acts as an "AND" clause,
40
- * meaning the resulting records need to be present in _each_ query string.
41
- *
42
- * @param hydrator
43
- * hydrator is an optional callback, which may be useful depending on the storage mechanism.
44
- * For example, the in-memory storage only stores the path to its records as its value,
45
- * but in something like DynamoDB the query strings may be used to look up the full record,
46
- * meaning there's no need to "hydrate" the return value
47
- */
48
- query(queryStrings: string[], hydrator?: (fullPath: string) => Promise<object>): Promise<object[]>;
49
- /**
50
- * In this context, seeding is the act of putting records and indexing data into an ephemeral
51
- * storage layer for use during the GraphQL runtime. What might seem suprising is that some stores
52
- * don't support seeding, this is because they're behaving more like a "bridge" (GithubStore and FilesystemStore).
53
- * Currently they're acting as a way to swap out true data-layer behavior with a backwards-compatible
54
- * "store". In the future, all stores should be able to query and seed data.
55
- *
56
- * At this time it seems that it would never make sense to be able to "query" without "seed"-ing, and
57
- * there'd be no value in "seeding" without "query"-ing.
58
- */
59
- seed(filepath: string, data: object, options?: {
60
- includeTemplate?: boolean;
61
- }): Promise<void>;
62
- supportsSeeding(): boolean;
63
- /**
64
- * Whether this store supports the ability to index data.
65
- * Indexing data requires writing arbitrary keys/values to
66
- * the external service, so is not advisable to use for
67
- * something like Github, which would write commits to the
68
- * user's repo.
69
- */
70
- supportsIndexing(): boolean;
71
- put(filepath: string, data: object, keepTemplateKey?: boolean): Promise<void>;
72
- }