1 | /*
|
2 | * Copyright 2020 Adobe. All rights reserved.
|
3 | * This file is licensed to you under the Apache License, Version 2.0 (the "License");
|
4 | * you may not use this file except in compliance with the License. You may obtain a copy
|
5 | * of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6 | *
|
7 | * Unless required by applicable law or agreed to in writing, software distributed under
|
8 | * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
|
9 | * OF ANY KIND, either express or implied. See the License for the specific language
|
10 | * governing permissions and limitations under the License.
|
11 | */
|
12 | /* eslint-disable no-underscore-dangle */
|
13 | const fse = require('fs-extra');
|
14 | const path = require('path');
|
15 | const ActionBuilder = require('./action_builder.js');
|
16 |
|
17 | /**
|
18 | * Development server to use with a expressified openwhisk app.
|
19 | *
|
20 | * Example:
|
21 | *
|
22 | * ```
|
23 | * // test/dev.js
|
24 | *
|
25 | * const { DevelopmentServer } = require('@adobe/openwhisk-action-builder');
|
26 | * const App = require('../src/app.js');
|
27 | *
|
28 | * async function run() {
|
29 | * const devServer = await new DevelopmentServer(App).init();
|
30 | * return devServer.start();
|
31 | * }
|
32 | * run().catch(console.error);
|
33 | * ```
|
34 | *
|
35 | * @type {DevelopmentServer}
|
36 | */
|
37 | module.exports = class DevelopmentServer {
|
38 | /**
|
39 | * Creates a new development server using the given express app.
|
40 | * @param {function} appFn - The function that creates an express app.
|
41 | */
|
42 | constructor(appFn) {
|
43 | this._appFn = appFn;
|
44 | this._cwd = process.cwd();
|
45 | this._port = process.env.WEBSERVER_PORT || 3000;
|
46 | }
|
47 |
|
48 | withPort(value) {
|
49 | this._port = value;
|
50 | return this;
|
51 | }
|
52 |
|
53 | /**
|
54 | * Initializes the development server.
|
55 | * It uses the `wsk.package.params-file` and `wsk.params-file` to read the environment for
|
56 | * the action params.
|
57 | *
|
58 | * @returns this
|
59 | */
|
60 | async init() {
|
61 | // load the action params params
|
62 | let pkgJson = {};
|
63 | try {
|
64 | pkgJson = await fse.readJson(path.resolve('package.json'));
|
65 | } catch (e) {
|
66 | // ignore
|
67 | }
|
68 | const builder = new ActionBuilder();
|
69 | if (pkgJson.wsk && pkgJson.wsk['params-file']) {
|
70 | builder.withParamsFile(pkgJson.wsk['params-file']);
|
71 | }
|
72 | if (pkgJson.wsk && pkgJson.wsk.package && pkgJson.wsk.package['params-file']) {
|
73 | builder.withParamsFile(pkgJson.wsk.package['params-file']);
|
74 | }
|
75 | if (pkgJson.wsk && pkgJson.wsk['dev-params-file']) {
|
76 | const file = pkgJson.wsk['dev-params-file'];
|
77 | if (await fse.exists(file)) {
|
78 | builder.withParamsFile(file);
|
79 | }
|
80 | }
|
81 | await builder.initWskProps();
|
82 |
|
83 | const params = await ActionBuilder.resolveParams(builder._params);
|
84 |
|
85 | // set openwhisk coordinates for transparent ow client usage.
|
86 | process.env.__OW_API_KEY = builder._wskAuth;
|
87 | process.env.__OW_API_HOST = builder._wskApiHost;
|
88 | process.env.__OW_NAMESPACE = builder._wskNamespace;
|
89 |
|
90 | this.params = params;
|
91 | return this;
|
92 | }
|
93 |
|
94 | /**
|
95 | * Starts the development server
|
96 | * @returns {Promise<void>}
|
97 | */
|
98 | async start() {
|
99 | const app = await this._appFn(this.params);
|
100 |
|
101 | // bind default params like expressify does
|
102 | Object.defineProperty(app.request, 'owActionParams', {
|
103 | value: this.params,
|
104 | enumerable: false,
|
105 | });
|
106 |
|
107 | await new Promise((resolve, reject) => {
|
108 | try {
|
109 | this.server = app.listen(this._port, () => {
|
110 | // eslint-disable-next-line no-console
|
111 | console.log(`Started development server on port ${this.server.address().port}`);
|
112 | resolve();
|
113 | });
|
114 | } catch (e) {
|
115 | reject(e);
|
116 | }
|
117 | });
|
118 | }
|
119 |
|
120 | /**
|
121 | * Stops the development server.
|
122 | * @returns {Promise<void>}
|
123 | */
|
124 | async stop() {
|
125 | return new Promise((resolve, reject) => {
|
126 | this.server.close((err) => {
|
127 | if (err) {
|
128 | reject(err);
|
129 | } else {
|
130 | resolve();
|
131 | }
|
132 | });
|
133 | });
|
134 | }
|
135 | };
|