/**
Copyright 2021 Forestry.io Holdings, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/ import _ from 'lodash' ; import fs from 'fs-extra' ; import { print , OperationDefinitionNode } from 'graphql' ; import type { FragmentDefinitionNode , FieldDefinitionNode } from 'graphql' ; import { astBuilder , NAMER } from './ast-builder' ; import { sequential } from './util' ; import { createBuilder } from './builder' ; import { createSchema } from './schema' ; import { extractInlineTypes } from './ast-builder' ; import path from 'path' ; import type { Builder } from './builder' ; import type { TinaSchema } from './schema' ; import { Database } from './database' ; export const indexDB = async ( { database , config , buildSDK = true , } ) => { const flags = [ ] ; if ( database . store . supportsIndexing ( ) ) { flags . push ( 'experimentalData' ) ; } const tinaSchema = await createSchema ( { schema : config , flags } ) ; const builder = await createBuilder ( { database , tinaSchema , } ) ; const graphQLSchema = await _buildSchema ( builder , tinaSchema ) ; await database . indexData ( { graphQLSchema , tinaSchema } ) ; if ( buildSDK ) { await _buildFragments ( builder , tinaSchema , database . bridge . rootPath ) ; await _buildQueries ( builder , tinaSchema , database . bridge . rootPath ) ; } } ; const _buildFragments = async ( builder , tinaSchema , rootPath ) => { const fragmentDefinitionsFields = [ ] ; const collections = tinaSchema . getCollections ( ) ; await sequential ( collections , async ( collection ) => { const frag = ( await builder . collectionFragment ( collection ) ) as FragmentDefinitionNode ; fragmentDefinitionsFields . push ( frag ) ; } ) ; const fragDoc = { kind : 'Document' as const , definitions : _ . uniqBy ( extractInlineTypes ( fragmentDefinitionsFields ) , ( node ) => node . name . value ) , } ; const fragPath = path . join ( rootPath , '.tina' , '__generated__' ) ; await fs . outputFileSync ( path . join ( fragPath , 'frags.gql' ) , print ( fragDoc ) ) ; } ; const _buildQueries = async ( builder , tinaSchema , rootPath ) => { const operationsDefinitions = [ ] ; const collections = tinaSchema . getCollections ( ) ; await sequential ( collections , async ( collection ) => { const queryName = NAMER . queryName ( collection . namespace ) ; const queryListName = NAMER . generateQueryListName ( collection . namespace ) ; const fragName = NAMER . fragmentName ( collection . namespace ) ; operationsDefinitions . push ( astBuilder . QueryOperationDefinition ( { fragName , queryName } ) ) ; operationsDefinitions . push ( astBuilder . ListQueryOperationDefinition ( { fragName , queryName : queryListName , } ) ) ; } ) ; const queryDoc = { kind : 'Document' as const , definitions : _ . uniqBy ( extractInlineTypes ( operationsDefinitions ) , ( node ) => node . name . value ) , } ; const fragPath = path . join ( rootPath , '.tina' , '__generated__' ) ; await fs . outputFileSync ( path . join ( fragPath , 'queries.gql' ) , print ( queryDoc ) ) ; } ; const _buildSchema = async ( builder , tinaSchema ) => { /**
     * Definitions for the GraphQL AST
     */ const definitions = [ ] ; definitions . push ( await builder . buildStaticDefinitions ( ) ) ; const queryTypeDefinitionFields = [ ] ; const mutationTypeDefinitionFields = [ ] ; const collections = tinaSchema . getCollections ( ) ; /**
     * One-off collection queries
     */ queryTypeDefinitionFields . push ( await builder . buildCollectionDefinition ( collections ) ) ; queryTypeDefinitionFields . push ( await builder . buildMultiCollectionDefinition ( collections ) ) ; /**
     * Multi-collection queries/mutation
     */ queryTypeDefinitionFields . push ( await builder . multiNodeDocument ( ) ) ; queryTypeDefinitionFields . push ( await builder . multiCollectionDocument ( collections ) ) ; mutationTypeDefinitionFields . push ( await builder . addMultiCollectionDocumentMutation ( ) ) ; mutationTypeDefinitionFields . push ( await builder . buildUpdateCollectionDocumentMutation ( collections ) ) ; mutationTypeDefinitionFields . push ( await builder . buildCreateCollectionDocumentMutation ( collections ) ) ; queryTypeDefinitionFields . push ( await builder . multiCollectionDocumentList ( collections ) ) ; queryTypeDefinitionFields . push ( await builder . multiCollectionDocumentFields ( ) ) ; /**
     * Collection queries/mutations/fragments
     */ await sequential ( collections , async ( collection ) => { queryTypeDefinitionFields . push ( await builder . collectionDocument ( collection ) ) ; mutationTypeDefinitionFields . push ( await builder . updateCollectionDocumentMutation ( collection ) ) ; mutationTypeDefinitionFields . push ( await builder . createCollectionDocumentMutation ( collection ) ) ; queryTypeDefinitionFields . push ( await builder . collectionDocumentList ( collection ) ) ; } ) ; definitions . push ( astBuilder . ObjectTypeDefinition ( { name : 'Query' , fields : queryTypeDefinitionFields , } ) ) ; definitions . push ( astBuilder . ObjectTypeDefinition ( { name : 'Mutation' , fields : mutationTypeDefinitionFields , } ) ) ; const doc = { kind : 'Document' as const , definitions : _ . uniqBy ( extractInlineTypes ( definitions ) , ( node ) => node . name . value ) , } ; return doc ; } ;