test run mesh subs
This commit is contained in:
		
							
								
								
									
										35
									
								
								.meshrc.yml
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								.meshrc.yml
									
									
									
									
									
								
							@@ -8,21 +8,20 @@ sources:
 | 
			
		||||
        endpoint: https://directus.andert.me/graphql
 | 
			
		||||
        source: ./src/schemas/directus.graphql
 | 
			
		||||
        operationHeaders:
 | 
			
		||||
          Authorization: Bearer {env.DIRECTUS_API}
 | 
			
		||||
additionalResolvers:
 | 
			
		||||
  - ./src/resolvers/subs_directus.js
 | 
			
		||||
 | 
			
		||||
  # - name: Cloudron
 | 
			
		||||
  #   handler:
 | 
			
		||||
  #     openapi:
 | 
			
		||||
  #       endpoint: https://my.andert.me/api/v1
 | 
			
		||||
  #       source: ./src/schemas/cloudron.json
 | 
			
		||||
  #       operationHeaders:
 | 
			
		||||
  #         Authorization: Bearer {env.CLOUDRON_API}
 | 
			
		||||
  # - name: Gitea
 | 
			
		||||
  #   handler:
 | 
			
		||||
  #     openapi:
 | 
			
		||||
  #       endpoint: https://git.andert.me/api/v1
 | 
			
		||||
  #       source: ./src/schemas/gitea.yml
 | 
			
		||||
  #       operationHeaders:
 | 
			
		||||
  #         Authorization: Bearer {env.GITEA_API}
 | 
			
		||||
          Authorization: "Bearer {env.DIRECTUS_API}"
 | 
			
		||||
        connectionParams:
 | 
			
		||||
          access_token: "Bv5RknRvv5AZouxcYdBJgVOe3ZC493Y3"
 | 
			
		||||
# - name: Cloudron
 | 
			
		||||
#   handler:
 | 
			
		||||
#     openapi:
 | 
			
		||||
#       endpoint: https://my.andert.me/api/v1
 | 
			
		||||
#       source: ./src/schemas/cloudron.json
 | 
			
		||||
#       operationHeaders:
 | 
			
		||||
#         Authorization: Bearer {env.CLOUDRON_API}
 | 
			
		||||
# - name: Gitea
 | 
			
		||||
#   handler:
 | 
			
		||||
#     openapi:
 | 
			
		||||
#       endpoint: https://git.andert.me/api/v1
 | 
			
		||||
#       source: ./src/schemas/gitea.yml
 | 
			
		||||
#       operationHeaders:
 | 
			
		||||
#         Authorization: Bearer {env.GITEA_API}
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,10 @@
 | 
			
		||||
    "fs": "0.0.1-security",
 | 
			
		||||
    "graphql": "^16.7.1",
 | 
			
		||||
    "graphql-request": "^6.1.0",
 | 
			
		||||
    "graphql-sse": "^2.2.3",
 | 
			
		||||
    "graphql-subscriptions": "^2.0.0",
 | 
			
		||||
    "graphql-ws": "^5.14.0",
 | 
			
		||||
    "isomorphic-ws": "^5.0.0",
 | 
			
		||||
    "next": "13.4.9",
 | 
			
		||||
    "node-fetch": "^3.3.2",
 | 
			
		||||
    "path": "^0.12.7",
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										15
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										15
									
								
								pnpm-lock.yaml
									
									
									
										generated
									
									
									
								
							@@ -58,12 +58,18 @@ dependencies:
 | 
			
		||||
  graphql-request:
 | 
			
		||||
    specifier: ^6.1.0
 | 
			
		||||
    version: 6.1.0(graphql@16.7.1)
 | 
			
		||||
  graphql-sse:
 | 
			
		||||
    specifier: ^2.2.3
 | 
			
		||||
    version: 2.2.3(graphql@16.7.1)
 | 
			
		||||
  graphql-subscriptions:
 | 
			
		||||
    specifier: ^2.0.0
 | 
			
		||||
    version: 2.0.0(graphql@16.7.1)
 | 
			
		||||
  graphql-ws:
 | 
			
		||||
    specifier: ^5.14.0
 | 
			
		||||
    version: 5.14.0(graphql@16.7.1)
 | 
			
		||||
  isomorphic-ws:
 | 
			
		||||
    specifier: ^5.0.0
 | 
			
		||||
    version: 5.0.0(ws@8.13.0)
 | 
			
		||||
  next:
 | 
			
		||||
    specifier: 13.4.9
 | 
			
		||||
    version: 13.4.9(@babel/core@7.22.8)(react-dom@18.2.0)(react@18.2.0)
 | 
			
		||||
@@ -5808,6 +5814,15 @@ packages:
 | 
			
		||||
      tslib: 2.6.0
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /graphql-sse@2.2.3(graphql@16.7.1):
 | 
			
		||||
    resolution: {integrity: sha512-pcSbaPa2IAFm/oT5e7tu4kE0FaaZ32mWMQZa2hh+08bbjhmTlHInCGousYEYohWMUSKOrOFpFifpdWHms51JbA==}
 | 
			
		||||
    engines: {node: '>=12'}
 | 
			
		||||
    peerDependencies:
 | 
			
		||||
      graphql: '>=0.11 <=16'
 | 
			
		||||
    dependencies:
 | 
			
		||||
      graphql: 16.7.1
 | 
			
		||||
    dev: false
 | 
			
		||||
 | 
			
		||||
  /graphql-subscriptions@2.0.0(graphql@16.7.1):
 | 
			
		||||
    resolution: {integrity: sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA==}
 | 
			
		||||
    peerDependencies:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,108 +0,0 @@
 | 
			
		||||
const { createClient } = require('graphql-ws');
 | 
			
		||||
const WebSocket = require('ws');
 | 
			
		||||
const { PubSub } = require('graphql-subscriptions');
 | 
			
		||||
const { parse } = require('graphql');
 | 
			
		||||
 | 
			
		||||
const pubsub = new PubSub();
 | 
			
		||||
 | 
			
		||||
const schema = require('raw-loader!../schemas/directus.graphql').default;
 | 
			
		||||
 | 
			
		||||
// Parse the schema
 | 
			
		||||
const document = parse(schema);
 | 
			
		||||
 | 
			
		||||
// Function to find a type definition by name
 | 
			
		||||
const findTypeDefinition = (typeName) => {
 | 
			
		||||
  return document.definitions.find(
 | 
			
		||||
    def => def.kind === 'ObjectTypeDefinition' && def.name.value === typeName
 | 
			
		||||
  );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Extract the fields excluding the ones ending with '_func', of object type, and specific fields
 | 
			
		||||
const extractFields = (type, depth = 0) => {
 | 
			
		||||
  return type.fields
 | 
			
		||||
    .filter(field => !field.name.value.endsWith('_func') && !['avatar', 'role'].includes(field.name.value))
 | 
			
		||||
    .map(field => {
 | 
			
		||||
      if (field.type.kind === 'NamedType' && depth < 1) {
 | 
			
		||||
        // If the field is of object type and we are not too deep, recursively extract its fields
 | 
			
		||||
        const nestedType = findTypeDefinition(field.type.name.value);
 | 
			
		||||
        if (nestedType) {
 | 
			
		||||
          return `${field.name.value} {\n${extractFields(nestedType, depth + 1)}\n}`;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      return field.name.value;
 | 
			
		||||
    })
 | 
			
		||||
    .join('\n');
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const client = createClient({
 | 
			
		||||
  url: 'wss://directus.andert.me/graphql',
 | 
			
		||||
  keepAlive: 30000,
 | 
			
		||||
  webSocketImpl: WebSocket,
 | 
			
		||||
  connectionParams: async () => {
 | 
			
		||||
    return { access_token: process.env.DIRECTUS_API };
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const generateSubscriptionQuery = (typeName) => {
 | 
			
		||||
  const typeDefinition = findTypeDefinition(typeName);
 | 
			
		||||
  const fields = extractFields(typeDefinition);
 | 
			
		||||
 | 
			
		||||
  return `
 | 
			
		||||
    subscription {
 | 
			
		||||
      ${typeName}_mutated {
 | 
			
		||||
        key
 | 
			
		||||
        event
 | 
			
		||||
        data {
 | 
			
		||||
          ${fields}
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  `;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const handleSubscription = (typeName) => {
 | 
			
		||||
  const MUTATED = `${typeName.toUpperCase()}_MUTATED`;
 | 
			
		||||
 | 
			
		||||
  const type = findTypeDefinition(typeName);
 | 
			
		||||
  const fields = extractFields(type);
 | 
			
		||||
 | 
			
		||||
  const query = generateSubscriptionQuery(typeName);
 | 
			
		||||
 | 
			
		||||
  client.subscribe(
 | 
			
		||||
    {
 | 
			
		||||
      query: query,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      next: data => {
 | 
			
		||||
        if (data && data.data && data.data[`${typeName}_mutated`]) {
 | 
			
		||||
          pubsub.publish(MUTATED, { [`${typeName}_mutated`]: data.data[`${typeName}_mutated`] });
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      error: error => console.error('error:', error),
 | 
			
		||||
    }
 | 
			
		||||
  );
 | 
			
		||||
 | 
			
		||||
  return {
 | 
			
		||||
    [`${typeName}_mutated`]: {
 | 
			
		||||
      subscribe: () => pubsub.asyncIterator([MUTATED]),
 | 
			
		||||
      resolve: payload => payload[`${typeName}_mutated`],
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Find the Subscription type definition
 | 
			
		||||
const subscriptionType = findTypeDefinition('Subscription');
 | 
			
		||||
 | 
			
		||||
// Extract the subscription type names, excluding the ones starting with 'directus_'
 | 
			
		||||
const subscriptionTypeNames = subscriptionType.fields
 | 
			
		||||
  .map(field => field.name.value.replace('_mutated', ''))
 | 
			
		||||
  .filter(name => !name.startsWith('directus_'));
 | 
			
		||||
 | 
			
		||||
// Generate subscriptions for each type
 | 
			
		||||
const subscriptions = subscriptionTypeNames.reduce((acc, typeName) => {
 | 
			
		||||
  return { ...acc, ...handleSubscription(typeName) };
 | 
			
		||||
}, {});
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
  Subscription: subscriptions,
 | 
			
		||||
};
 | 
			
		||||
		Reference in New Issue
	
	Block a user