• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nuxy / lambda-lambda-lambda / 137

pending completion
137

push

travis-ci-com

nuxy
Added moving note / Removed stale docs

149 of 158 branches covered (94.3%)

Branch coverage included in aggregate %.

216 of 216 relevant lines covered (100.0%)

303.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

98.15
/src/router/Stack.js
1
/**
2
 *  lambda-lambda-lambda
3
 *  AWS Lambda@Edge serverless application router.
4
 *
5
 *  Copyright 2021-2023, Marc S. Brooks (https://mbrooks.info)
6
 *  Licensed under the MIT license:
7
 *  http://www.opensource.org/licenses/mit-license.php
8
 */
9

10
'use strict';
11

12
// Local modules.
13
const {isAsyncFunc, isPromise, isValidFunc, promiseEvents} = require('./Common');
83✔
14

15
/**
16
 * Provides Stack item handler and methods.
17
 */
18
class RouterStack {
19

20
  /**
21
   * Create new stack instance.
22
   */
23
  constructor() {
24
    this.middleware = [];
108✔
25
    this.routes     = [];
108✔
26
    this.resources  = [];
108✔
27
    this.fallback   = null;
108✔
28
  }
29

30
  /**
31
   * Add new function to stack items.
32
   *
33
   * Stack function types
34
   *  - middleware
35
   *  - route:<method>
36
   *  - resource:<method>
37
   *  - fallback
38
   *
39
   * @param {Function} func
40
   *   Route/middleware function.
41
   *
42
   * @example
43
   * const func1 = function(req, res, next) {
44
   *   if (req.method() === 'POST') {
45
   *     res.status(405).send();
46
   *   } else {
47
   *     next();
48
   *   }
49
   * };
50
   *
51
   * setFuncName(func1, 'middleware');
52
   * stack.add(func1);
53
   *
54
   *   ..
55
   *
56
   * const func2 = function(req, res) {
57
   *   res.setHeader('Content-Type', 'text/html');
58
   *   res.status(200).send('Hello World');
59
   * };
60
   *
61
   * setFuncName(func2, 'route:get');
62
   * stack.add(func2);
63
   */
64
  add(func) {
65
    if (isValidFunc(func)) {
279!
66
      const name = func.name;
279✔
67

68
      switch (true) {
279✔
69
        case /^middleware/.test(name):
70
          this.middleware.push(func);
121✔
71
          break;
121✔
72

73
        case /^route:/.test(name):
74
          this.routes.push(func);
39✔
75
          break;
39✔
76

77
        case /^resource:/.test(name):
78
          this.resources.push(func);
35✔
79
          break;
35✔
80

81
        default:
82
          this.fallback = func;
84✔
83
      }
84
    }
85
  }
86

87
  /**
88
   * Execute stored functions (a)synchronously.
89
   *
90
   * Order by priority.
91
   * > Middleware, Routes, Resources, fallback
92
   *
93
   * @param {RouterRequest} req
94
   *   Request instance.
95
   *
96
   * @param {RouterResponse} res
97
   *   Response instance.
98
   *
99
   * @return {Promise|undefined}
100
   *
101
   * @example
102
   * stack.exec(req, res);
103
   *
104
   * // updated instance
105
   * res.data();
106
   *
107
   *   ..
108
   *
109
   * stack.exec(req, res)
110
   *   .then(() => res.data())
111
   */
112
  exec(req, res) {
113
    const funcs = [].concat(this.middleware, this.routes, this.resources, [this.fallback]);
87✔
114

115
    let lastItem = true;
87✔
116
    let nextItem = true;
87✔
117
    let promises = [];
87✔
118

119
    funcs.forEach((func, index) => {
87✔
120
      if (nextItem) {
287✔
121
        lastItem = index++ === funcs.length;
222✔
122
        nextItem = false;
222✔
123

124
        if (isAsyncFunc(func) || isPromise(func) || hasReturn(func)) {
222✔
125

126
          // Asynchronous handling.
127
          promises.push(() => {
26✔
128
            return func(req, res, function() {
26✔
129
              throw new Error('Middleware next() is unsupported in async');
1✔
130
            });
131
          });
132

133
          nextItem = !lastItem;
26✔
134

135
        } else if (isValidFunc(func)) {
196✔
136

137
          // Synchronous handling.
138
          func(req, res, () => nextItem = !lastItem);
195✔
139
        }
140
      }
141
    });
142

143
    if (promises.length) {
87✔
144
      return promiseEvents(promises);
18✔
145
    }
146
  }
147
};
148

149
/**
150
 * Check if return statement exists. Assumes Promise
151
 * since there is no way to detect if a function
152
 * returns a Promise event without execution.
153
 *
154
 * @param {Function} func
155
 *   Route/Middleware Function.
156
 *
157
 * @return {Boolean}
158
 */
159
function hasReturn(func) {
160
  return (func && (typeof func === 'function' && /{\s+return\s+/.test(func.toString())));
196✔
161
}
162

163
module.exports = RouterStack;
83✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc