UNPKG

3.03 kBPlain TextView Raw
1import { Context } from "./Context";
2import { Strategy } from "./Strategy";
3import { GraphQLFieldConfig, GraphQLNamedType } from "graphql";
4import { Authority, AuthorityData, Credential, CredentialData } from "./model";
5
6export class StrategyCollection {
7 public map: { [name: string]: Strategy } = {};
8
9 public authorityMap: {
10 readonly [name: string]: { new (data: AuthorityData<any>): Authority<any> };
11 } = {};
12
13 public credentialMap: {
14 readonly [name: string]: {
15 new (data: CredentialData<any>): Credential<any>;
16 };
17 } = {};
18
19 public queryFields: {
20 readonly [field: string]: GraphQLFieldConfig<any, any, Context>;
21 } = {};
22
23 public mutationFields: {
24 readonly [field: string]: GraphQLFieldConfig<any, any, Context>;
25 } = {};
26
27 public types: GraphQLNamedType[] = [];
28
29 public constructor(strategies?: Iterable<Strategy>) {
30 if (strategies)
31 for (const strategy of strategies) {
32 this.add(strategy);
33 }
34 }
35
36 public add(s: Strategy): StrategyCollection {
37 if (this.map[s.name])
38 throw new Error(
39 `INVARIANT: Multiple strategies cannot use the same identifier; "${s.name}" is used twice.`
40 );
41
42 const queryFields = { ...this.queryFields };
43 for (const f of Object.keys(s.queryFields)) {
44 if (queryFields[f]) {
45 throw new Error(
46 `INVARIANT: Multiple strategies cannot use the query field; "${f}" is used twice.`
47 );
48 }
49
50 queryFields[f] = s.queryFields[f];
51 }
52
53 const mutationFields = { ...this.mutationFields };
54 for (const f of Object.keys(s.mutationFields)) {
55 if (mutationFields[f]) {
56 throw new Error(
57 `INVARIANT: Multiple strategies cannot use the mutation field; "${f}" is used twice.`
58 );
59 }
60
61 mutationFields[f] = s.mutationFields[f];
62 }
63
64 this.map = { ...this.map, [s.name]: s };
65 this.authorityMap = { ...this.authorityMap, [s.name]: s.authorityModel };
66 this.credentialMap = { ...this.credentialMap, [s.name]: s.credentialModel };
67 this.queryFields = queryFields;
68 this.mutationFields = mutationFields;
69 this.types = [...this.types, ...s.types];
70
71 return this;
72 }
73
74 public delete(s: Strategy): boolean {
75 if (!this.map[s.name]) return false;
76
77 const map = { ...this.map };
78 delete map[s.name];
79
80 const authorityMap = { ...this.authorityMap };
81 delete authorityMap[s.name];
82
83 const credentialMap = { ...this.credentialMap };
84 delete credentialMap[s.name];
85
86 const queryFields = { ...this.queryFields };
87 for (const f of Object.keys(s.queryFields)) {
88 delete queryFields[f];
89 }
90
91 const mutationFields = { ...this.mutationFields };
92 for (const f of Object.keys(s.mutationFields)) {
93 delete mutationFields[f];
94 }
95
96 this.map = map;
97 this.authorityMap = authorityMap;
98 this.credentialMap = credentialMap;
99 this.queryFields = queryFields;
100 this.mutationFields = mutationFields;
101 this.types = this.types.filter(t => !s.types.includes(t));
102
103 return true;
104 }
105}