UNPKG

@apollo/federation-internals

Version:
79 lines (69 loc) 3.06 kB
import { DirectiveLocation } from "graphql"; import { CorePurpose, FeatureDefinition, FeatureDefinitions, FeatureUrl, FeatureVersion, } from "./coreSpec"; import {DirectiveDefinition, ListType, NonNullType, Schema} from "../definitions"; import { createDirectiveSpecification, createScalarTypeSpecification } from "../directiveAndTypeSpecification"; import { registerKnownFeature } from "../knownCoreFeatures"; import { ARGUMENT_COMPOSITION_STRATEGIES } from "../argumentCompositionStrategies"; import { assert } from "../utils"; export enum RequiresScopesTypeName { SCOPE = 'Scope', } export class RequiresScopesSpecDefinition extends FeatureDefinition { public static readonly directiveName = "requiresScopes"; public static readonly identity = `https://specs.apollo.dev/${RequiresScopesSpecDefinition.directiveName}`; constructor(version: FeatureVersion) { super( new FeatureUrl( RequiresScopesSpecDefinition.identity, RequiresScopesSpecDefinition.directiveName, version, ) ); this.registerType(createScalarTypeSpecification({ name: RequiresScopesTypeName.SCOPE })); // WARNING: we cannot declare staticArgumentTransform() as access control merge logic needs to propagate // requirements upwards/downwards between types and interfaces. We hijack the merge process by providing // implementations/interfaces as "additional sources". This means that we cannot apply staticArgumentTransform() // as subgraph index index will be wrong/undefined. this.registerDirective(createDirectiveSpecification({ name: RequiresScopesSpecDefinition.directiveName, args: [{ name: 'scopes', type: (schema, feature) => { assert(feature, "Shouldn't be added without being attached to a @link spec"); const scopeName = feature.typeNameInSchema(RequiresScopesTypeName.SCOPE); const scopeType = schema.type(scopeName); assert(scopeType, () => `Expected "${scopeName}" to be defined`); return new NonNullType(new ListType(new NonNullType(new ListType(new NonNullType(scopeType))))); }, compositionStrategy: ARGUMENT_COMPOSITION_STRATEGIES.DNF_CONJUNCTION, }], locations: [ DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.OBJECT, DirectiveLocation.INTERFACE, DirectiveLocation.SCALAR, DirectiveLocation.ENUM, ], composes: true, supergraphSpecification: () => REQUIRES_SCOPES_VERSIONS.latest(), })); } requiresScopesDirective(schema: Schema): DirectiveDefinition<{scopes: string[][]}> | undefined { return this.directive(schema, RequiresScopesSpecDefinition.directiveName); } get defaultCorePurpose(): CorePurpose { return 'SECURITY'; } } export const REQUIRES_SCOPES_VERSIONS = new FeatureDefinitions<RequiresScopesSpecDefinition>( RequiresScopesSpecDefinition.identity ).add(new RequiresScopesSpecDefinition(new FeatureVersion(0, 1))); registerKnownFeature(REQUIRES_SCOPES_VERSIONS);