Skip to content
This repository has been archived by the owner on Feb 17, 2023. It is now read-only.

Commit

Permalink
wip: Working on new compiler
Browse files Browse the repository at this point in the history
  • Loading branch information
ex3ndr committed Jun 4, 2021
1 parent e247ec2 commit 1bf9d40
Show file tree
Hide file tree
Showing 36 changed files with 10,053 additions and 4,262 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
node_modules
output
packages/sample/lib
packages/spacex-cli/lib
packages/spacex/lib
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module.exports = {
globals: {
'ts-jest': {
tsConfig: './tsconfig.test.json',
tsConfig: './tsconfig.json',
},
},
testEnvironment: 'jsdom',
Expand Down
6 changes: 0 additions & 6 deletions journey.json

This file was deleted.

9 changes: 9 additions & 0 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"lerna": "2.2.0",
"packages": [
"packages/*"
],
"npmClient": "yarn",
"useWorkspaces": true,
"version": "11.11.0"
}
57 changes: 36 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,47 @@
{
"name": "spacex-monorepo",
"version": "1.0.0",
"private": true,
"workspaces": {
"packages": [
"packages/*"
]
},
"publishConfig": {
"access": "public"
},
"scripts": {
"dev": "journey dev sample",
"build": "journey build",
"clean": "journey clean",
"build": "tsc --build",
"clean": "yarn tsc --build --clean",
"test": "yarn jest",
"release": "yarn build && yarn jest && cd ./packages/spacex && yarn publish",
"export": "journey export sample"
},
"devDependencies": {
"@haystackjs/journey": "2.2.1",
"@types/jest": "^25.2.1",
"@types/react": "^16.9.19",
"@types/react-dom": "^16.9.5",
"@types/uuid": "^3.4.7",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"ts-jest": "^25.4.0"
"release": "yarn clean && yarn build && yarn test && yarn lerna publish --force-publish",
"cli": "yarn tsc --build --incremental=false && node ./packages/spacex-cli/lib/index.js",
"cli:test": "yarn cli compile --path \"./packages/spacex-cli/test_data/queries/*.graphql\" --schema ./packages/spacex-cli/test_data/schema.json --output ./packages/spacex-cli/test_data"
},
"dependencies": {
"@openland/spacex-cli": "3.1.1",
"@types/ws": "^7.2.1",
"@graphql-tools/optimize": "1.0.1",
"@graphql-tools/relay-operation-optimizer": "^6.3.0",
"@types/commander": "2.12.2",
"@types/glob": "7.1.3",
"@types/graphql": "14.5.0",
"@types/jest": "25.2.1",
"@types/ora": "3.2.0",
"@types/prompts": "2.0.12",
"@types/react": "16.9.19",
"@types/react-dom": "16.9.5",
"@types/uuid": "3.4.7",
"@types/ws": "7.2.1",
"apollo": "2.33.4",
"commander": "7.2.0",
"glob": "7.1.7",
"graphql": "15.5.0",
"isomorphic-ws": "4.0.1",
"jest": "^25.5.0",
"jest": "25.5.0",
"ora": "5.4.0",
"prompts": "2.4.1",
"react": "16.12.0",
"react-dom": "16.12.0",
"ts-jest": "25.4.0",
"typescript": "*",
"uuid": "3.4.0",
"ws": "7.2.1"
}
}
}
5 changes: 0 additions & 5 deletions packages/sample/package.json

This file was deleted.

1 change: 0 additions & 1 deletion packages/sample/src/index.css

This file was deleted.

5 changes: 0 additions & 5 deletions packages/sample/src/index.html

This file was deleted.

7 changes: 0 additions & 7 deletions packages/sample/src/index.tsx

This file was deleted.

19 changes: 19 additions & 0 deletions packages/spacex-cli/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{
"name": "spacex-cli",
"version": "3.1.1",
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"bin": {
"spacex-cli": "lib/index.js"
},
"dependencies": {
"commander": "7.2.0",
"ora": "5.4.0",
"prompts": "2.4.1",
"glob": "7.1.7",
"graphql": "15.5.0",
"@graphql-tools/optimize": "1.0.1",
"@graphql-tools/relay-operation-optimizer": "6.3.0",
"apollo": "2.33.4"
}
}
130 changes: 130 additions & 0 deletions packages/spacex-cli/src/compiler/compile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import fs from 'fs';
import glob from 'glob';
import { buildClientSchema, parse, GraphQLSchema, FragmentDefinitionNode, OperationDefinitionNode, SelectionSetNode, DocumentNode } from 'graphql';
import { optimizeDocuments } from '@graphql-tools/relay-operation-optimizer';
import { withTypenameFieldAddedWhereNeeded } from './utils/withTypenameFieldAddedWhereNeeded';
import { astToString } from './utils/astToString';
import { compileDescriptor } from './compileDescriptor';
import { compileTypes } from './compileTypes';

export type CompileContext = {
schema: GraphQLSchema,
documents: DocumentNode[],
queries: Map<string, { definition: OperationDefinitionNode, source: string, usesFragments: Set<string> }>,
mutations: Map<string, { definition: OperationDefinitionNode, source: string, usesFragments: Set<string> }>,
subscriptions: Map<string, { definition: OperationDefinitionNode, source: string, usesFragments: Set<string> }>,
fragments: Map<string, { definition: FragmentDefinitionNode, source: string, usesFragments: Set<string>, usedBy: Set<string> }>
}

export async function compile(path: string, schemaPath: string, output: string, name: string) {

// Load schema
const schema = buildClientSchema(JSON.parse(fs.readFileSync(schemaPath, 'utf-8')));

// Load queries
const files = glob.sync(path).map((f) => fs.readFileSync(f, 'utf-8'));
const documents = files.map((f) => parse(f));

// Add __typename
const withTypenames = documents.map((d) => withTypenameFieldAddedWhereNeeded(d));

// Optimize via relay compiler
const optimized = optimizeDocuments(schema, withTypenames.map((v) => v), { includeFragments: true });

// Resolve model
const queries = new Map<string, { definition: OperationDefinitionNode, source: string, usesFragments: Set<string> }>();
const mutations = new Map<string, { definition: OperationDefinitionNode, source: string, usesFragments: Set<string> }>();
const subscriptions = new Map<string, { definition: OperationDefinitionNode, source: string, usesFragments: Set<string> }>();
const fragments = new Map<string, { definition: FragmentDefinitionNode, source: string, usesFragments: Set<string>, usedBy: Set<string> }>();

// Collect definitions
for (let i = 0; i < optimized.length; i++) {
const document = optimized[i];
for (let def of document.definitions) {
const source = astToString(def);
if (def.kind === 'OperationDefinition') {
if (!def.name) {
throw Error('Operations without names are not supported');
}
if (def.operation === 'query') {
queries.set(def.name.value, { definition: def, source, usesFragments: new Set() });
} else if (def.operation === 'mutation') {
mutations.set(def.name.value, { definition: def, source, usesFragments: new Set() });
} else if (def.operation === 'subscription') {
subscriptions.set(def.name.value, { definition: def, source, usesFragments: new Set() });
} else {
throw Error('Unsupported operation type: ' + def.operation);
}
} else if (def.kind === 'FragmentDefinition') {
if (!def.name) {
throw Error('Operations without names are not supported');
}
fragments.set(def.name.value, { definition: def, source, usesFragments: new Set(), usedBy: new Set() });
} else {
throw Error('Unsupported definition: ' + def.kind);
}
}
}

function _collectDependencies(selectionSet: SelectionSetNode, output: Set<string>) {
for (let s of selectionSet.selections) {
if (s.kind === 'FragmentSpread') {
if (output.has(s.name.value)) {
continue;
}
_collectDependencies(fragments.get(s.name.value)!.definition.selectionSet, output);
} else if (s.kind === 'Field') {
continue;
} else if (s.kind === 'InlineFragment') {
_collectDependencies(s.selectionSet, output);
}
}
}
function collectDependencies(selectionSet: SelectionSetNode) {
const res = new Set<string>();
_collectDependencies(selectionSet, res);
return Array.from(res);
}

// Collect references
for (const [name, fragment] of fragments.entries()) {
const deps = collectDependencies(fragment.definition.selectionSet);
for (let dep of deps) {
fragment.usesFragments.add(dep);
fragments.get(dep)!.usedBy.add(name);
}
}
for (const [name, query] of queries.entries()) {
const deps = collectDependencies(query.definition.selectionSet);
for (let dep of deps) {
query.usesFragments.add(dep);
fragments.get(dep)!.usedBy.add(name);
}
}
for (const [name, mutation] of mutations.entries()) {
const deps = collectDependencies(mutation.definition.selectionSet);
for (let dep of deps) {
mutation.usesFragments.add(dep);
fragments.get(dep)!.usedBy.add(name);
}
}
for (const [name, subscription] of subscriptions.entries()) {
const deps = collectDependencies(subscription.definition.selectionSet);
for (let dep of deps) {
subscription.usesFragments.add(dep);
fragments.get(dep)!.usedBy.add(name);
}
}

// Context
const context: CompileContext = {
queries, mutations, subscriptions, fragments, schema, documents
};

// Compile execution descriptor
const descriptor = compileDescriptor(context);
fs.writeFileSync(output + '/spacex.descriptor.json', descriptor, 'utf-8');

// Compile types
await compileTypes(output, context);
}
5 changes: 5 additions & 0 deletions packages/spacex-cli/src/compiler/compileClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { CompileContext } from "./compile";

export function compileClient(context: CompileContext) {
let res = '';
}
Loading

0 comments on commit 1bf9d40

Please sign in to comment.