Skip to content

Commit b8c14a1

Browse files
feat(hooks): Add an injectHooks function that can wrap the graphqlSchemaDeclaration and inject hooks proceduraly.
1 parent bfc7041 commit b8c14a1

File tree

8 files changed

+614
-4
lines changed

8 files changed

+614
-4
lines changed

lib/index.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
33
return (mod && mod.__esModule) ? mod : { "default": mod };
44
};
55
exports.__esModule = true;
6-
exports.resolver = exports.removeUnusedAttributes = exports.injectAssociations = exports.generateSchema = exports.generateModelTypes = exports.generateCount = exports.generateApolloServer = void 0;
6+
exports.resolver = exports.removeUnusedAttributes = exports.injectHooks = exports.injectAssociations = exports.generateSchema = exports.generateModelTypes = exports.generateCount = exports.generateApolloServer = void 0;
77
var graphql_sequelize_1 = require("graphql-sequelize");
88
var inject_1 = __importDefault(require("./associations/inject"));
99
exports.injectAssociations = inject_1["default"];
1010
var generateApolloServer_1 = __importDefault(require("./generateApolloServer"));
1111
exports.generateApolloServer = generateApolloServer_1["default"];
1212
var modelTypes_1 = __importDefault(require("./generateTypes/modelTypes"));
1313
exports.generateModelTypes = modelTypes_1["default"];
14+
var injectHooks_1 = require("./injectHooks");
15+
exports.injectHooks = injectHooks_1.injectHooks;
1416
var count_1 = __importDefault(require("./queryResolvers/count"));
1517
exports.generateCount = count_1["default"];
1618
var removeUnusedAttributes_1 = __importDefault(require("./removeUnusedAttributes"));

lib/injectHooks.js

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
"use strict";
2+
exports.__esModule = true;
3+
exports.injectHooks = void 0;
4+
// Injects a function that will be called with the model and the hooks
5+
// The function can return a new list of hooks to be used instead of the original ones
6+
function injectHooks(_a) {
7+
var _b, _c, _d;
8+
var graphqlSchemaDeclaration = _a.graphqlSchemaDeclaration, injectFunctions = _a.injectFunctions;
9+
for (var key in graphqlSchemaDeclaration) {
10+
var declaration = graphqlSchemaDeclaration[key];
11+
if ('model' in declaration) {
12+
if (!declaration.list) {
13+
declaration.list = {};
14+
}
15+
var beforeList = Array.isArray(declaration.list.before)
16+
? declaration.list.before
17+
: declaration.list.before
18+
? [declaration.list.before]
19+
: [];
20+
declaration.list.before = injectFunctions.listBefore
21+
? injectFunctions.listBefore(declaration.model, beforeList)
22+
: beforeList;
23+
var afterList = Array.isArray(declaration.list.after)
24+
? declaration.list.after
25+
: declaration.list.after
26+
? [declaration.list.after]
27+
: [];
28+
declaration.list.after = injectFunctions.listAfter
29+
? injectFunctions.listAfter(declaration.model, afterList)
30+
: afterList;
31+
// Initialize update configuration if it's in actions
32+
if ((_b = declaration.actions) === null || _b === void 0 ? void 0 : _b.includes('update')) {
33+
if (!declaration.update || 'type' in declaration.update) {
34+
declaration.update = {};
35+
}
36+
var beforeUpdate = Array.isArray(declaration.update.before)
37+
? declaration.update.before
38+
: declaration.update.before
39+
? [declaration.update.before]
40+
: [];
41+
declaration.update.before = injectFunctions.updateBefore
42+
? injectFunctions.updateBefore(declaration.model, beforeUpdate)
43+
: beforeUpdate;
44+
var afterUpdate = Array.isArray(declaration.update.after)
45+
? declaration.update.after
46+
: declaration.update.after
47+
? [declaration.update.after]
48+
: [];
49+
declaration.update.after = injectFunctions.updateAfter
50+
? injectFunctions.updateAfter(declaration.model, afterUpdate)
51+
: afterUpdate;
52+
}
53+
// Initialize create configuration if it's in actions
54+
if ((_c = declaration.actions) === null || _c === void 0 ? void 0 : _c.includes('create')) {
55+
if (!declaration.create || 'type' in declaration.create) {
56+
declaration.create = {};
57+
}
58+
var beforeCreate = Array.isArray(declaration.create.before)
59+
? declaration.create.before
60+
: declaration.create.before
61+
? [declaration.create.before]
62+
: [];
63+
declaration.create.before = injectFunctions.createBefore
64+
? injectFunctions.createBefore(declaration.model, beforeCreate)
65+
: beforeCreate;
66+
var afterCreate = Array.isArray(declaration.create.after)
67+
? declaration.create.after
68+
: declaration.create.after
69+
? [declaration.create.after]
70+
: [];
71+
declaration.create.after = injectFunctions.createAfter
72+
? injectFunctions.createAfter(declaration.model, afterCreate)
73+
: afterCreate;
74+
}
75+
// Initialize delete configuration if it's in actions
76+
if ((_d = declaration.actions) === null || _d === void 0 ? void 0 : _d.includes('delete')) {
77+
if (!declaration["delete"] || 'type' in declaration["delete"]) {
78+
declaration["delete"] = {};
79+
}
80+
var beforeDelete = Array.isArray(declaration["delete"].before)
81+
? declaration["delete"].before
82+
: declaration["delete"].before
83+
? [declaration["delete"].before]
84+
: [];
85+
declaration["delete"].before = injectFunctions.deleteBefore
86+
? injectFunctions.deleteBefore(declaration.model, beforeDelete)
87+
: beforeDelete;
88+
var afterDelete = Array.isArray(declaration["delete"].after)
89+
? declaration["delete"].after
90+
: declaration["delete"].after
91+
? [declaration["delete"].after]
92+
: [];
93+
declaration["delete"].after = injectFunctions.deleteAfter
94+
? injectFunctions.deleteAfter(declaration.model, afterDelete)
95+
: afterDelete;
96+
}
97+
}
98+
}
99+
return graphqlSchemaDeclaration;
100+
}
101+
exports.injectHooks = injectHooks;

src/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { resolver as sourceResolver } from 'graphql-sequelize'
22
import injectAssociations from './associations/inject'
33
import generateApolloServer from './generateApolloServer'
44
import generateModelTypes from './generateTypes/modelTypes'
5+
import { injectHooks } from './injectHooks'
56
import generateCount from './queryResolvers/count'
67
import removeUnusedAttributes from './removeUnusedAttributes'
78
import generateSchema from './schema'
@@ -16,9 +17,11 @@ export {
1617
generateModelTypes,
1718
generateSchema,
1819
injectAssociations,
20+
injectHooks,
1921
// Functions that you can use in your resolvers
2022
removeUnusedAttributes,
2123
//We export the resolver from graphql-sequelize because
2224
//graphql-sequelize does not provide types for it.
23-
resolver,
25+
resolver
2426
}
27+

src/injectHooks.ts

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
import { ModelStatic } from 'sequelize'
2+
import {
3+
CreateAfterHook,
4+
CreateBeforeHook,
5+
CreateFieldDeclarationType,
6+
DeleteAfterHook,
7+
DeleteBeforeHook,
8+
DeleteFieldDeclarationType,
9+
GraphqlSchemaDeclarationType,
10+
QueryAfterHook,
11+
QueryBeforeHook,
12+
UpdateAfterHook,
13+
UpdateBeforeHook,
14+
UpdateFieldDeclarationType,
15+
} from './types/types'
16+
17+
// Injects a function that will be called with the model and the hooks
18+
// The function can return a new list of hooks to be used instead of the original ones
19+
export function injectHooks({
20+
graphqlSchemaDeclaration,
21+
injectFunctions,
22+
}: {
23+
graphqlSchemaDeclaration: GraphqlSchemaDeclarationType<any>
24+
injectFunctions: {
25+
listBefore?: (
26+
model: ModelStatic<any>,
27+
hooks: QueryBeforeHook<any>[]
28+
) => QueryBeforeHook<any>[]
29+
listAfter?: (
30+
model: ModelStatic<any>,
31+
hooks: QueryAfterHook<any>[]
32+
) => QueryAfterHook<any>[]
33+
updateBefore?: (
34+
model: ModelStatic<any>,
35+
hooks: UpdateBeforeHook<any>[]
36+
) => UpdateBeforeHook<any>[]
37+
updateAfter?: (
38+
model: ModelStatic<any>,
39+
hooks: UpdateAfterHook<any>[]
40+
) => UpdateAfterHook<any>[]
41+
createBefore?: (
42+
model: ModelStatic<any>,
43+
hooks: CreateBeforeHook<any>[]
44+
) => CreateBeforeHook<any>[]
45+
createAfter?: (
46+
model: ModelStatic<any>,
47+
hooks: CreateAfterHook<any>[]
48+
) => CreateAfterHook<any>[]
49+
deleteBefore?: (
50+
model: ModelStatic<any>,
51+
hooks: DeleteBeforeHook<any>[]
52+
) => DeleteBeforeHook<any>[]
53+
deleteAfter?: (
54+
model: ModelStatic<any>,
55+
hooks: DeleteAfterHook<any>[]
56+
) => DeleteAfterHook<any>[]
57+
}
58+
}): GraphqlSchemaDeclarationType<any> {
59+
for (const key in graphqlSchemaDeclaration) {
60+
const declaration = graphqlSchemaDeclaration[key]
61+
62+
if ('model' in declaration) {
63+
if (!declaration.list) {
64+
declaration.list = {}
65+
}
66+
67+
const beforeList: QueryBeforeHook<any>[] = Array.isArray(
68+
declaration.list.before
69+
)
70+
? declaration.list.before
71+
: declaration.list.before
72+
? [declaration.list.before as QueryBeforeHook<any>]
73+
: []
74+
75+
declaration.list.before = injectFunctions.listBefore
76+
? injectFunctions.listBefore(declaration.model, beforeList)
77+
: beforeList
78+
79+
const afterList: QueryAfterHook<any>[] = Array.isArray(
80+
declaration.list.after
81+
)
82+
? declaration.list.after
83+
: declaration.list.after
84+
? [declaration.list.after as QueryAfterHook<any>]
85+
: []
86+
87+
declaration.list.after = injectFunctions.listAfter
88+
? injectFunctions.listAfter(declaration.model, afterList)
89+
: afterList
90+
91+
// Initialize update configuration if it's in actions
92+
if (declaration.actions?.includes('update')) {
93+
if (!declaration.update || 'type' in declaration.update) {
94+
declaration.update = {} as UpdateFieldDeclarationType<any>
95+
}
96+
97+
const beforeUpdate: UpdateBeforeHook<any>[] = Array.isArray(
98+
declaration.update.before
99+
)
100+
? declaration.update.before
101+
: declaration.update.before
102+
? [declaration.update.before as UpdateBeforeHook<any>]
103+
: []
104+
105+
declaration.update.before = injectFunctions.updateBefore
106+
? injectFunctions.updateBefore(declaration.model, beforeUpdate)
107+
: beforeUpdate
108+
109+
const afterUpdate: UpdateAfterHook<any>[] = Array.isArray(
110+
declaration.update.after
111+
)
112+
? declaration.update.after
113+
: declaration.update.after
114+
? [declaration.update.after as UpdateAfterHook<any>]
115+
: []
116+
117+
declaration.update.after = injectFunctions.updateAfter
118+
? injectFunctions.updateAfter(declaration.model, afterUpdate)
119+
: afterUpdate
120+
}
121+
122+
// Initialize create configuration if it's in actions
123+
if (declaration.actions?.includes('create')) {
124+
if (!declaration.create || 'type' in declaration.create) {
125+
declaration.create = {} as CreateFieldDeclarationType<any>
126+
}
127+
128+
const beforeCreate: CreateBeforeHook<any>[] = Array.isArray(
129+
declaration.create.before
130+
)
131+
? declaration.create.before
132+
: declaration.create.before
133+
? [declaration.create.before as CreateBeforeHook<any>]
134+
: []
135+
136+
declaration.create.before = injectFunctions.createBefore
137+
? injectFunctions.createBefore(declaration.model, beforeCreate)
138+
: beforeCreate
139+
140+
const afterCreate: CreateAfterHook<any>[] = Array.isArray(
141+
declaration.create.after
142+
)
143+
? declaration.create.after
144+
: declaration.create.after
145+
? [declaration.create.after as CreateAfterHook<any>]
146+
: []
147+
148+
declaration.create.after = injectFunctions.createAfter
149+
? injectFunctions.createAfter(declaration.model, afterCreate)
150+
: afterCreate
151+
}
152+
153+
// Initialize delete configuration if it's in actions
154+
if (declaration.actions?.includes('delete')) {
155+
if (!declaration.delete || 'type' in declaration.delete) {
156+
declaration.delete = {} as DeleteFieldDeclarationType<any>
157+
}
158+
159+
const beforeDelete: DeleteBeforeHook<any>[] = Array.isArray(
160+
declaration.delete.before
161+
)
162+
? declaration.delete.before
163+
: declaration.delete.before
164+
? [declaration.delete.before as DeleteBeforeHook<any>]
165+
: []
166+
167+
declaration.delete.before = injectFunctions.deleteBefore
168+
? injectFunctions.deleteBefore(declaration.model, beforeDelete)
169+
: beforeDelete
170+
171+
const afterDelete: DeleteAfterHook<any>[] = Array.isArray(
172+
declaration.delete.after
173+
)
174+
? declaration.delete.after
175+
: declaration.delete.after
176+
? [declaration.delete.after as DeleteAfterHook<any>]
177+
: []
178+
179+
declaration.delete.after = injectFunctions.deleteAfter
180+
? injectFunctions.deleteAfter(declaration.model, afterDelete)
181+
: afterDelete
182+
}
183+
}
184+
}
185+
186+
return graphqlSchemaDeclaration
187+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`Test that it is possible to inject hooks for any action should inject hooks for create endpoint 1`] = `
4+
Object {
5+
"id": 25001,
6+
"name": "[CREATE] Test User [CREATED]",
7+
}
8+
`;
9+
10+
exports[`Test that it is possible to inject hooks for any action should inject hooks for delete endpoint 1`] = `
11+
Array [
12+
Object {
13+
"id": 1,
14+
"message": "The User id = 25001 was successfully deleted",
15+
},
16+
]
17+
`;
18+
19+
exports[`Test that it is possible to inject hooks for any action should inject hooks for update endpoint 1`] = `
20+
Object {
21+
"id": 1,
22+
"name": "[UPDATE] Updated User [UPDATED]",
23+
}
24+
`;

0 commit comments

Comments
 (0)