test run mesh subs

This commit is contained in:
Samuel Andert 2023-08-24 12:35:22 +02:00
parent 91ce34e260
commit 4f6fba7e71
4 changed files with 34 additions and 126 deletions

View File

@ -8,21 +8,20 @@ sources:
endpoint: https://directus.andert.me/graphql endpoint: https://directus.andert.me/graphql
source: ./src/schemas/directus.graphql source: ./src/schemas/directus.graphql
operationHeaders: operationHeaders:
Authorization: Bearer {env.DIRECTUS_API} Authorization: "Bearer {env.DIRECTUS_API}"
additionalResolvers: connectionParams:
- ./src/resolvers/subs_directus.js access_token: "Bv5RknRvv5AZouxcYdBJgVOe3ZC493Y3"
# - name: Cloudron
# - name: Cloudron # handler:
# handler: # openapi:
# openapi: # endpoint: https://my.andert.me/api/v1
# endpoint: https://my.andert.me/api/v1 # source: ./src/schemas/cloudron.json
# source: ./src/schemas/cloudron.json # operationHeaders:
# operationHeaders: # Authorization: Bearer {env.CLOUDRON_API}
# Authorization: Bearer {env.CLOUDRON_API} # - name: Gitea
# - name: Gitea # handler:
# handler: # openapi:
# openapi: # endpoint: https://git.andert.me/api/v1
# endpoint: https://git.andert.me/api/v1 # source: ./src/schemas/gitea.yml
# source: ./src/schemas/gitea.yml # operationHeaders:
# operationHeaders: # Authorization: Bearer {env.GITEA_API}
# Authorization: Bearer {env.GITEA_API}

View File

@ -33,8 +33,10 @@
"fs": "0.0.1-security", "fs": "0.0.1-security",
"graphql": "^16.7.1", "graphql": "^16.7.1",
"graphql-request": "^6.1.0", "graphql-request": "^6.1.0",
"graphql-sse": "^2.2.3",
"graphql-subscriptions": "^2.0.0", "graphql-subscriptions": "^2.0.0",
"graphql-ws": "^5.14.0", "graphql-ws": "^5.14.0",
"isomorphic-ws": "^5.0.0",
"next": "13.4.9", "next": "13.4.9",
"node-fetch": "^3.3.2", "node-fetch": "^3.3.2",
"path": "^0.12.7", "path": "^0.12.7",

View File

@ -58,12 +58,18 @@ dependencies:
graphql-request: graphql-request:
specifier: ^6.1.0 specifier: ^6.1.0
version: 6.1.0(graphql@16.7.1) version: 6.1.0(graphql@16.7.1)
graphql-sse:
specifier: ^2.2.3
version: 2.2.3(graphql@16.7.1)
graphql-subscriptions: graphql-subscriptions:
specifier: ^2.0.0 specifier: ^2.0.0
version: 2.0.0(graphql@16.7.1) version: 2.0.0(graphql@16.7.1)
graphql-ws: graphql-ws:
specifier: ^5.14.0 specifier: ^5.14.0
version: 5.14.0(graphql@16.7.1) version: 5.14.0(graphql@16.7.1)
isomorphic-ws:
specifier: ^5.0.0
version: 5.0.0(ws@8.13.0)
next: next:
specifier: 13.4.9 specifier: 13.4.9
version: 13.4.9(@babel/core@7.22.8)(react-dom@18.2.0)(react@18.2.0) 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 tslib: 2.6.0
dev: false 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): /graphql-subscriptions@2.0.0(graphql@16.7.1):
resolution: {integrity: sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA==} resolution: {integrity: sha512-s6k2b8mmt9gF9pEfkxsaO1lTxaySfKoEJzEfmwguBbQ//Oq23hIXCfR1hm4kdh5hnR20RdwB+s3BCb+0duHSZA==}
peerDependencies: peerDependencies:

View File

@ -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,
};