UNPKG

3.52 kBJavaScriptView Raw
1'use strict'
2
3/* eslint no-prototype-builtins: 0 */
4
5const {
6 kReply,
7 kRequest,
8 kState,
9 kHasBeenDecorated
10} = require('./symbols.js')
11
12const {
13 FST_ERR_DEC_ALREADY_PRESENT,
14 FST_ERR_DEC_MISSING_DEPENDENCY,
15 FST_ERR_DEC_AFTER_START,
16 FST_ERR_DEC_DEPENDENCY_INVALID_TYPE
17} = require('./errors')
18
19const { FSTDEP006 } = require('./warnings')
20
21function decorate (instance, name, fn, dependencies) {
22 if (Object.prototype.hasOwnProperty.call(instance, name)) {
23 throw new FST_ERR_DEC_ALREADY_PRESENT(name)
24 }
25
26 checkDependencies(instance, name, dependencies)
27
28 if (fn && (typeof fn.getter === 'function' || typeof fn.setter === 'function')) {
29 Object.defineProperty(instance, name, {
30 get: fn.getter,
31 set: fn.setter
32 })
33 } else {
34 instance[name] = fn
35 }
36}
37
38function decorateConstructor (konstructor, name, fn, dependencies) {
39 const instance = konstructor.prototype
40 if (Object.prototype.hasOwnProperty.call(instance, name) || hasKey(konstructor, name)) {
41 throw new FST_ERR_DEC_ALREADY_PRESENT(name)
42 }
43
44 konstructor[kHasBeenDecorated] = true
45 checkDependencies(konstructor, name, dependencies)
46
47 if (fn && (typeof fn.getter === 'function' || typeof fn.setter === 'function')) {
48 Object.defineProperty(instance, name, {
49 get: fn.getter,
50 set: fn.setter
51 })
52 } else if (typeof fn === 'function') {
53 instance[name] = fn
54 } else {
55 konstructor.props.push({ key: name, value: fn })
56 }
57}
58
59function checkReferenceType (name, fn) {
60 if (typeof fn === 'object' && fn && !(typeof fn.getter === 'function' || typeof fn.setter === 'function')) {
61 FSTDEP006(name)
62 }
63}
64
65function decorateFastify (name, fn, dependencies) {
66 assertNotStarted(this, name)
67 decorate(this, name, fn, dependencies)
68 return this
69}
70
71function checkExistence (instance, name) {
72 if (name) {
73 return name in instance || (instance.prototype && name in instance.prototype) || hasKey(instance, name)
74 }
75
76 return instance in this
77}
78
79function hasKey (fn, name) {
80 if (fn.props) {
81 return fn.props.find(({ key }) => key === name)
82 }
83 return false
84}
85
86function checkRequestExistence (name) {
87 if (name && hasKey(this[kRequest], name)) return true
88 return checkExistence(this[kRequest].prototype, name)
89}
90
91function checkReplyExistence (name) {
92 if (name && hasKey(this[kReply], name)) return true
93 return checkExistence(this[kReply].prototype, name)
94}
95
96function checkDependencies (instance, name, deps) {
97 if (deps === undefined || deps === null) {
98 return
99 }
100
101 if (!Array.isArray(deps)) {
102 throw new FST_ERR_DEC_DEPENDENCY_INVALID_TYPE(name)
103 }
104
105 // eslint-disable-next-line no-var
106 for (var i = 0; i !== deps.length; ++i) {
107 if (!checkExistence(instance, deps[i])) {
108 throw new FST_ERR_DEC_MISSING_DEPENDENCY(deps[i])
109 }
110 }
111}
112
113function decorateReply (name, fn, dependencies) {
114 assertNotStarted(this, name)
115 checkReferenceType(name, fn)
116 decorateConstructor(this[kReply], name, fn, dependencies)
117 return this
118}
119
120function decorateRequest (name, fn, dependencies) {
121 assertNotStarted(this, name)
122 checkReferenceType(name, fn)
123 decorateConstructor(this[kRequest], name, fn, dependencies)
124 return this
125}
126
127function assertNotStarted (instance, name) {
128 if (instance[kState].started) {
129 throw new FST_ERR_DEC_AFTER_START(name)
130 }
131}
132
133module.exports = {
134 add: decorateFastify,
135 exist: checkExistence,
136 existRequest: checkRequestExistence,
137 existReply: checkReplyExistence,
138 dependencies: checkDependencies,
139 decorateReply,
140 decorateRequest
141}