From caf0659900a79650bb11877ffaeadbc30be9f922 Mon Sep 17 00:00:00 2001 From: Jim Crossley Date: Tue, 25 May 2021 13:49:48 -0400 Subject: [PATCH] src(templates)!: modify the nodejs event template to accept a cloudevent (#356) * Simplify the nodejs events template Pretty-printing the contents of the event and its envelope for each request. This is handy when invoked as a Knative event sink as some sources, e.g. Kafka, ignore the response body. Co-authored-by: Lance Ball * Expect the event parameter to be the entire CloudEvent This will require a change to the faas-js-runtime, but at least the template won't need to change when that's released * Update nodejs guide to reflect 2nd arg's type is CloudEvent * Templates now using faas-js-runtime 0.7.1 Co-authored-by: Lance Ball --- docs/guides/nodejs.md | 60 +++++++++------- templates/node/events/README.md | 11 +-- templates/node/events/index.js | 43 ++++-------- templates/node/events/package-lock.json | 64 ++++++++--------- templates/node/events/package.json | 2 +- templates/node/events/test/integration.js | 46 ++++++------ templates/node/events/test/unit.js | 4 +- templates/node/http/index.js | 3 +- templates/node/http/package-lock.json | 64 ++++++++--------- templates/node/http/package.json | 2 +- templates/node/http/test/integration.js | 85 ++++++++++++----------- 11 files changed, 190 insertions(+), 194 deletions(-) diff --git a/docs/guides/nodejs.md b/docs/guides/nodejs.md index 221c7c9fca..49345147de 100644 --- a/docs/guides/nodejs.md +++ b/docs/guides/nodejs.md @@ -86,20 +86,27 @@ If you prefer another, that's no problem. Just remove the `tape` dependency from ## Function reference -Boson Node.js functions have very few restrictions. You can add any required dependencies -in `package.json`, and you may include additional local JavaScript files. The only real -requirements are that your project contain an `index.js` file which exports a single function. -In this section, we will look in a little more detail at how Boson functions are invoked, -and what APIs are available to you as a developer. +Boson Node.js functions have very few restrictions. You can add any +required dependencies in `package.json`, and you may include +additional local JavaScript files. The only real requirements are that +your project contain an `index.js` file which exports a single +function. In this section, we will look in a little more detail at +how Boson functions are invoked, and what APIs are available to you as +a developer. ### Invocation parameters -When using the `func` CLI to create a function project, you may choose to generate a project -that responds to a `CloudEvent` or simple HTTP. `CloudEvents` in Knative are transported over -HTTP as a `POST` request, so in many ways, the two types of functions are very much the same. -They each will listen and respond to incoming HTTP events. +When using the `func` CLI to create a function project, you may choose +to generate a project that responds to a `CloudEvent` or simple +HTTP. `CloudEvents` in Knative are transported over HTTP as a `POST` +request, so in many ways, the two types of functions are very much the +same. They each will listen and respond to incoming HTTP events. -When an incoming request is received, your function will be invoked with a `Context` object as the first parameter. If the incoming request is a `CloudEvent`, any data associated with the `CloudEvent` is extracted from the event and provided as a second parameter. For example, a `CloudEvent` is received which contains a JSON string such as this in its data property, +When an incoming request is received, your function will be invoked +with a `Context` object as the first parameter. If the incoming +request is a `CloudEvent`, it will be provided as the second +parameter. For example, a `CloudEvent` is received which contains a +JSON string such as this in its data property, ```json { @@ -108,12 +115,12 @@ When an incoming request is received, your function will be invoked with a `Cont } ``` -When invoked, the second parameter to the function, after the `Context` object, will be -a JavaScript object having `customerId` and `productId` properties. The function -signature might look like this, with the `data` parameter having these properties. +So to log that string from your function, you might do this: ```js -function processPurchase(context, data) +function handle(context, event) { + console.log(JSON.stringify(event.data, null, 2)); +} ``` ### Return Values Functions may return any valid JavaScript type, or nothing at all. When a @@ -126,7 +133,10 @@ the returned values are extracted and sent with the response. #### Example ```js -function processCustomer(context, customer) { +function handle(context, event) { + return processCustomer(event.data) +} +function processCustomer(customer) { // process customer and return a new CloudEvent return new CloudEvent({ source: 'customer.processor', @@ -142,7 +152,7 @@ extracted and sent with the response to the caller. #### Example ```js -function processCustomer(context, customer) { +function processCustomer(customer) { // process customer and return custom headers // the response will be '204 No content' return { headers: { customerid: customer.id } }; @@ -155,7 +165,7 @@ Developers may set the response code returned to the caller by adding a #### Example ```js -function processCustomer(context, customer) { +function processCustomer(customer) { // process customer if (customer.restricted) { return { statusCode: 451 } @@ -167,7 +177,7 @@ This also works with `Error` objects thrown from the function. #### Example ```js -function processCustomer(context, customer) { +function processCustomer(customer) { // process customer if (customer.restricted) { const err = new Error(‘Unavailable for legal reasons’); @@ -193,7 +203,7 @@ The log adheres to the Pino logging API (https://getpino.io/#/docs/api). #### Example ```js -Function myFunction(context) { +Function handle(context) { context.log.info(“Processing customer”); } ``` @@ -216,7 +226,7 @@ attributes are also found on the context object itself. #### Example ```js -Function myFunction(context) { +Function handle(context) { // Log the 'name' query parameter context.log.info(context.query.name); // Query parameters also are attached to the context @@ -242,7 +252,7 @@ be parsed so that the attributes are directly available. #### Example ```js -Function myFunction(context) { +Function handle(context) { // log the incoming request body's 'hello' parameter context.log.info(context.body.hello); } @@ -264,7 +274,7 @@ Returns the HTTP request headers as an object. #### Example ```js -Function myFunction(context) { +Function handle(context) { context.log.info(context.headers[custom-header]); } ``` @@ -309,10 +319,10 @@ A function which accepts a data value and returns a CloudEvent. #### Example ```js // Expects to receive a CloudEvent with customer data -function processCustomer(context, customer) { +function handle(context, event) { // process the customer - const processed = processCustomer(customer); - return context.cloudEventResponse(customer); + const processed = processCustomer(event.data); + return context.cloudEventResponse(processed); } ``` diff --git a/templates/node/events/README.md b/templates/node/events/README.md index 01d30c1cb9..3078032606 100644 --- a/templates/node/events/README.md +++ b/templates/node/events/README.md @@ -1,13 +1,8 @@ # Node.js Cloud Events Function -Welcome to your new Node.js function project! The boilerplate function code can -be found in [`index.js`](./index.js). This function is meant to respond -exclusively to [Cloud Events](https://cloudevents.io/), but you can remove the -check for this in the function and it will respond just fine to plain vanilla -incoming HTTP requests. Additionally, this example function is written -asynchronously, returning a `Promise`. If your function does not perform any -asynchronous execution, you can safely remove the `async` keyword from the -function, and return raw values instead of a `Promise`. +Welcome to your new Node.js function project! The boilerplate function +code can be found in [`index.js`](./index.js). This function is meant +to respond to [Cloud Events](https://cloudevents.io/). ## Local execution diff --git a/templates/node/events/index.js b/templates/node/events/index.js index 088a7bb575..d855a09992 100644 --- a/templates/node/events/index.js +++ b/templates/node/events/index.js @@ -2,8 +2,10 @@ const { CloudEvent, HTTP } = require('cloudevents'); /** - * An example function that responds to incoming CloudEvents over HTTP. For example, - * from the Knative event Broker. Try invoking with a request such as this. + * A function that responds to incoming CloudEvents over HTTP from, + * for example, a Knative event Source, Channel or Broker. + * + * If running via 'npm run local', it can be invoked like so: * * curl -X POST -d '{"name": "Tiger", "customerId": "0123456789"}' \ * -H'Content-type: application/json' \ @@ -13,37 +15,22 @@ const { CloudEvent, HTTP } = require('cloudevents'); * -H'Ce-specversion: 1.0' \ * http://localhost:8080 * - * The event data is extracted from the incoming event and provided as the first - * parameter to the function. The CloudEvent object itself may be accessed via the - * context parameter, For example: - * - * const incomingEvent = context.cloudevent; - * * @param {Context} context the invocation context - * @param {Object} user the CloudEvent data. If the data content type is application/json - * this will be converted to an Object via JSON.parse() + * @param {Object} event the CloudEvent */ -function verifyUser(context, user) { - if (!context.cloudevent) { - return { - message: 'No cloud event received' - }; - } +function handle(context, event) { - context.log.info('Processing user', user); - context.log.info(`CloudEvent received: ${context.cloudevent.toString()}`); + context.log.info("context"); + console.log(JSON.stringify(context, null, 2)); + + context.log.info("event"); + console.log(JSON.stringify(event, null, 2)); - user = verify(user); return HTTP.binary(new CloudEvent({ - source: 'function.verifyUser', - type: 'user:verified', - data: user + source: 'event.handler', + type: 'echo', + data: event })); }; -function verify(user) { - // do something with the user - return user; -} - -module.exports = verifyUser; +module.exports = handle; diff --git a/templates/node/events/package-lock.json b/templates/node/events/package-lock.json index 8b91af0da9..3928a14e00 100644 --- a/templates/node/events/package-lock.json +++ b/templates/node/events/package-lock.json @@ -178,9 +178,9 @@ } }, "avvio": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.1.tgz", - "integrity": "sha512-b+gox68dqD6c3S3t+bZBKN6rYbVWdwpN12sHQLFTiacDT2rcq7fm07Ww+IKt/AvAkyCIe1f5ArP1bC/vAlx97A==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz", + "integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==", "dev": true, "requires": { "archy": "^1.0.0", @@ -356,9 +356,9 @@ "dev": true }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -704,13 +704,13 @@ "dev": true }, "faas-js-runtime": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.6.0.tgz", - "integrity": "sha512-p4D8sRw7PArjlD02C9V8m42FBOs79qdqVP/BgWUX6pRIY2pJ6Vd6qTqZ99uBQqjb5HZJfACEcbFtWnUz9RE2Bw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.7.1.tgz", + "integrity": "sha512-BrIP4UtdCOOmCaX/oEpFOP24RIbikaCBQ8Iiaf6Zn54++nkTIvy6HyXzu+35sx4sQdB4w8G4uPFAzOphUQjbJA==", "dev": true, "requires": { "chalk": "^4.1.0", - "cloudevents": "^4.0.0", + "cloudevents": "^4.0.2", "commander": "^6.1.0", "death": "^1.1.0", "fastify": "^3.3.0", @@ -719,9 +719,9 @@ }, "dependencies": { "cloudevents": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.1.tgz", - "integrity": "sha512-6Q0jwDOuDbBw9FS31YPggS+baB7/Lv44i6Hp7rMaivAQFdPrMZkdmchONwrKMamLD16myEeb7HNvx+NDqdU57Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.2.tgz", + "integrity": "sha512-tIgdbZApPVT81PAOhmUcq8INkppmWeAsMAjp2EFmMoYc7Uez1B62m6AddxG9oVIUXyALWdATtzEeaSMhC83c/g==", "dev": true, "requires": { "ajv": "~6.12.3", @@ -747,9 +747,9 @@ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" }, "fast-json-stringify": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.5.4.tgz", - "integrity": "sha512-fu74X0fRzQqADX6LFJ+5lSal1+j/QmX4oWrDnrfVAXV4qT6PwyymZmhGa/1SWgouOmf0tBJzZrHZPLymO00Lxg==", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.5.tgz", + "integrity": "sha512-VClYNkPo7tyZr0BMrRWraDMTJwjH6dIaHc/b/BiA4Z2MpxpKZBu45akYVb0dOVwQbF22zUMmhdg1WjrUjzAN2g==", "dev": true, "requires": { "ajv": "^6.11.0", @@ -759,9 +759,9 @@ } }, "fast-redact": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz", - "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz", + "integrity": "sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw==", "dev": true }, "fast-safe-stringify": { @@ -771,9 +771,9 @@ "dev": true }, "fastify": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.14.2.tgz", - "integrity": "sha512-/PY//7gJnGxLQORaRHCEW148vpFKFpBIQNz1Yo/DxbHuk5EQqK2comzyE2ug8FSEldDX8nleapTshl0m78Px2w==", + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.15.1.tgz", + "integrity": "sha512-QZBGrSOwcR+IJF5OwYTZ5662wEd68SqC6sG4aMu0GncKbYlG9GF88EF2PzN2HfXCCD9K0d/+ZNowuF8S893mOg==", "dev": true, "requires": { "@fastify/proxy-addr": "^3.0.0", @@ -795,9 +795,9 @@ } }, "fastify-error": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.0.tgz", - "integrity": "sha512-Jm2LMTB5rsJqlS1+cmgqqM9tTs0UrlgYR7TvDT3ZgXsUI5ib1NjQlqZHf+tDK5tVPdFGwyq02wAoJtyYIRSiFA==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz", + "integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ==", "dev": true }, "fastify-warning": { @@ -1557,16 +1557,16 @@ "dev": true }, "pino": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.2.tgz", - "integrity": "sha512-bmzxwbrIPxQUlAuMkF4PWVErUGERU4z37HazlhflKFg08crsNE3fACGN6gPwg5xtKOK47Ux5cZm8YCuLV4wWJg==", + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.3.tgz", + "integrity": "sha512-drPtqkkSf0ufx2gaea3TryFiBHdNIdXKf5LN0hTM82SXI4xVIve2wLwNg92e1MT6m3jASLu6VO7eGY6+mmGeyw==", "dev": true, "requires": { "fast-redact": "^3.0.0", "fast-safe-stringify": "^2.0.7", "flatstr": "^1.0.12", "pino-std-serializers": "^3.1.0", - "quick-format-unescaped": "4.0.1", + "quick-format-unescaped": "^4.0.3", "sonic-boom": "^1.0.2" } }, @@ -1643,9 +1643,9 @@ "dev": true }, "quick-format-unescaped": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz", - "integrity": "sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", + "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==", "dev": true }, "rc": { diff --git a/templates/node/events/package.json b/templates/node/events/package.json index 45909eeb25..7b4fb84d6e 100644 --- a/templates/node/events/package.json +++ b/templates/node/events/package.json @@ -13,7 +13,7 @@ "debug": "nodemon --inspect ./node_modules/faas-js-runtime/bin/cli.js ./index.js" }, "devDependencies": { - "faas-js-runtime": "0.6.0", + "faas-js-runtime": "0.7.1", "nodemon": "^2.0.4", "supertest": "^4.0.2", "tape": "^4.13.0" diff --git a/templates/node/events/test/integration.js b/templates/node/events/test/integration.js index 5b1a3e7637..df611cfd26 100644 --- a/templates/node/events/test/integration.js +++ b/templates/node/events/test/integration.js @@ -1,6 +1,6 @@ 'use strict'; const { CloudEvent } = require('cloudevents'); -const runtime = require('faas-js-runtime'); +const { start } = require('faas-js-runtime'); const request = require('supertest'); const func = require('..'); @@ -19,26 +19,26 @@ const data = { } test('Integration: handles a valid event', t => { - runtime(func, server => { - t.plan(5); - request(server) - .post('/') - .send(data) - .set(Spec.id, '01234') - .set(Spec.source, '/test') - .set(Spec.type, 'com.example.cloudevents.test') - .set(Spec.version, '1.0') - .expect(200) - .expect('Content-Type', /json/) - .end((err, result) => { - t.error(err, 'No error'); - t.ok(result); - t.deepEqual(result.body, data); - t.equal(result.headers['ce-type'], 'user:verified'); - t.equal(result.headers['ce-source'], 'function.verifyUser'); - t.end(); - server.close(); - }); - }, { log: false }); + start(func) + .then(server => { + t.plan(5); + request(server) + .post('/') + .send(data) + .set(Spec.id, '01234') + .set(Spec.source, '/test') + .set(Spec.type, 'com.example.cloudevents.test') + .set(Spec.version, '1.0') + .expect(200) + .expect('Content-Type', /json/) + .end((err, result) => { + t.error(err, 'No error'); + t.ok(result); + t.deepEqual(result.body.data, data); + t.equal(result.headers['ce-type'], 'echo'); + t.equal(result.headers['ce-source'], 'event.handler'); + t.end(); + server.close(); + }); + }); }); - diff --git a/templates/node/events/test/unit.js b/templates/node/events/test/unit.js index ff22af7a5c..98a9e86df5 100644 --- a/templates/node/events/test/unit.js +++ b/templates/node/events/test/unit.js @@ -26,8 +26,8 @@ test('Unit: handles a valid event', t => { const result = func(mockContext, data); t.ok(result); t.equal(result.body, data); - t.equal(result.headers['ce-type'], 'user:verified'); - t.equal(result.headers['ce-source'], 'function.verifyUser'); + t.equal(result.headers['ce-type'], 'echo'); + t.equal(result.headers['ce-source'], 'event.handler'); t.end(); }); diff --git a/templates/node/http/index.js b/templates/node/http/index.js index debf296b77..f3c62c0fb0 100644 --- a/templates/node/http/index.js +++ b/templates/node/http/index.js @@ -28,6 +28,7 @@ function handlePost(context) { */ function invoke(context) { context.log.info(`Handling HTTP ${context.httpVersion} request`); + console.log(JSON.stringify(context, null, 2)); if (context.method === 'POST') { return handlePost(context); } else if (context.method === 'GET') { @@ -51,4 +52,4 @@ function invokeDestructured({ name }) { return `Hello ${name}!`; } -module.exports = invoke; \ No newline at end of file +module.exports = invoke; diff --git a/templates/node/http/package-lock.json b/templates/node/http/package-lock.json index 941788cda0..2559a788ed 100644 --- a/templates/node/http/package-lock.json +++ b/templates/node/http/package-lock.json @@ -201,9 +201,9 @@ } }, "avvio": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.1.tgz", - "integrity": "sha512-b+gox68dqD6c3S3t+bZBKN6rYbVWdwpN12sHQLFTiacDT2rcq7fm07Ww+IKt/AvAkyCIe1f5ArP1bC/vAlx97A==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/avvio/-/avvio-7.2.2.tgz", + "integrity": "sha512-XW2CMCmZaCmCCsIaJaLKxAzPwF37fXi1KGxNOvedOpeisLdmxZnblGc3hpHWYnlP+KOUxZsazh43WXNHgXpbqw==", "dev": true, "requires": { "archy": "^1.0.0", @@ -371,9 +371,9 @@ "dev": true }, "chalk": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz", - "integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz", + "integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==", "dev": true, "requires": { "ansi-styles": "^4.1.0", @@ -435,9 +435,9 @@ } }, "cloudevents": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.1.tgz", - "integrity": "sha512-6Q0jwDOuDbBw9FS31YPggS+baB7/Lv44i6Hp7rMaivAQFdPrMZkdmchONwrKMamLD16myEeb7HNvx+NDqdU57Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cloudevents/-/cloudevents-4.0.2.tgz", + "integrity": "sha512-tIgdbZApPVT81PAOhmUcq8INkppmWeAsMAjp2EFmMoYc7Uez1B62m6AddxG9oVIUXyALWdATtzEeaSMhC83c/g==", "dev": true, "requires": { "ajv": "~6.12.3", @@ -725,13 +725,13 @@ "dev": true }, "faas-js-runtime": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.6.0.tgz", - "integrity": "sha512-p4D8sRw7PArjlD02C9V8m42FBOs79qdqVP/BgWUX6pRIY2pJ6Vd6qTqZ99uBQqjb5HZJfACEcbFtWnUz9RE2Bw==", + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/faas-js-runtime/-/faas-js-runtime-0.7.1.tgz", + "integrity": "sha512-BrIP4UtdCOOmCaX/oEpFOP24RIbikaCBQ8Iiaf6Zn54++nkTIvy6HyXzu+35sx4sQdB4w8G4uPFAzOphUQjbJA==", "dev": true, "requires": { "chalk": "^4.1.0", - "cloudevents": "^4.0.0", + "cloudevents": "^4.0.2", "commander": "^6.1.0", "death": "^1.1.0", "fastify": "^3.3.0", @@ -758,9 +758,9 @@ "dev": true }, "fast-json-stringify": { - "version": "2.5.4", - "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.5.4.tgz", - "integrity": "sha512-fu74X0fRzQqADX6LFJ+5lSal1+j/QmX4oWrDnrfVAXV4qT6PwyymZmhGa/1SWgouOmf0tBJzZrHZPLymO00Lxg==", + "version": "2.7.5", + "resolved": "https://registry.npmjs.org/fast-json-stringify/-/fast-json-stringify-2.7.5.tgz", + "integrity": "sha512-VClYNkPo7tyZr0BMrRWraDMTJwjH6dIaHc/b/BiA4Z2MpxpKZBu45akYVb0dOVwQbF22zUMmhdg1WjrUjzAN2g==", "dev": true, "requires": { "ajv": "^6.11.0", @@ -770,9 +770,9 @@ } }, "fast-redact": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.0.tgz", - "integrity": "sha512-a/S/Hp6aoIjx7EmugtzLqXmcNsyFszqbt6qQ99BdG61QjBZF6shNis0BYR6TsZOQ1twYc0FN2Xdhwwbv6+KD0w==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-redact/-/fast-redact-3.0.1.tgz", + "integrity": "sha512-kYpn4Y/valC9MdrISg47tZOpYBNoTXKgT9GYXFpHN/jYFs+lFkPoisY+LcBODdKVMY96ATzvzsWv+ES/4Kmufw==", "dev": true }, "fast-safe-stringify": { @@ -782,9 +782,9 @@ "dev": true }, "fastify": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.14.2.tgz", - "integrity": "sha512-/PY//7gJnGxLQORaRHCEW148vpFKFpBIQNz1Yo/DxbHuk5EQqK2comzyE2ug8FSEldDX8nleapTshl0m78Px2w==", + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/fastify/-/fastify-3.15.1.tgz", + "integrity": "sha512-QZBGrSOwcR+IJF5OwYTZ5662wEd68SqC6sG4aMu0GncKbYlG9GF88EF2PzN2HfXCCD9K0d/+ZNowuF8S893mOg==", "dev": true, "requires": { "@fastify/proxy-addr": "^3.0.0", @@ -817,9 +817,9 @@ } }, "fastify-error": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.0.tgz", - "integrity": "sha512-Jm2LMTB5rsJqlS1+cmgqqM9tTs0UrlgYR7TvDT3ZgXsUI5ib1NjQlqZHf+tDK5tVPdFGwyq02wAoJtyYIRSiFA==", + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/fastify-error/-/fastify-error-0.3.1.tgz", + "integrity": "sha512-oCfpcsDndgnDVgiI7bwFKAun2dO+4h84vBlkWsWnz/OUK9Reff5UFoFl241xTiLeHWX/vU9zkDVXqYUxjOwHcQ==", "dev": true }, "fastify-warning": { @@ -1627,16 +1627,16 @@ "dev": true }, "pino": { - "version": "6.11.2", - "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.2.tgz", - "integrity": "sha512-bmzxwbrIPxQUlAuMkF4PWVErUGERU4z37HazlhflKFg08crsNE3fACGN6gPwg5xtKOK47Ux5cZm8YCuLV4wWJg==", + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/pino/-/pino-6.11.3.tgz", + "integrity": "sha512-drPtqkkSf0ufx2gaea3TryFiBHdNIdXKf5LN0hTM82SXI4xVIve2wLwNg92e1MT6m3jASLu6VO7eGY6+mmGeyw==", "dev": true, "requires": { "fast-redact": "^3.0.0", "fast-safe-stringify": "^2.0.7", "flatstr": "^1.0.12", "pino-std-serializers": "^3.1.0", - "quick-format-unescaped": "4.0.1", + "quick-format-unescaped": "^4.0.3", "sonic-boom": "^1.0.2" } }, @@ -1714,9 +1714,9 @@ "dev": true }, "quick-format-unescaped": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.1.tgz", - "integrity": "sha512-RyYpQ6Q5/drsJyOhrWHYMWTedvjTIat+FTwv0K4yoUxzvekw2aRHMQJLlnvt8UantkZg2++bEzD9EdxXqkWf4A==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/quick-format-unescaped/-/quick-format-unescaped-4.0.3.tgz", + "integrity": "sha512-MaL/oqh02mhEo5m5J2rwsVL23Iw2PEaGVHgT2vFt8AAsr0lfvQA5dpXo9TPu0rz7tSBdUPgkbam0j/fj5ZM8yg==", "dev": true }, "rc": { diff --git a/templates/node/http/package.json b/templates/node/http/package.json index 9a5453adcb..0cc7584bd1 100644 --- a/templates/node/http/package.json +++ b/templates/node/http/package.json @@ -12,7 +12,7 @@ "author": "", "license": "Apache-2.0", "devDependencies": { - "faas-js-runtime": "0.6.0", + "faas-js-runtime": "0.7.1", "nodemon": "^2.0.4", "supertest": "^4.0.2", "tape": "^5.0.1" diff --git a/templates/node/http/test/integration.js b/templates/node/http/test/integration.js index 7c7b5d87b3..d23137af25 100644 --- a/templates/node/http/test/integration.js +++ b/templates/node/http/test/integration.js @@ -1,56 +1,59 @@ 'use strict'; -const runtime = require('faas-js-runtime'); +const { start } = require('faas-js-runtime'); const request = require('supertest'); const func = require('..'); const test = require('tape'); test('Integration: handles an HTTP GET', t => { - runtime(func, server => { - t.plan(2); - request(server) - .get('/?name=tiger') - .expect(200) - .expect('Content-Type', /json/) - .end((err, res) => { - t.error(err, 'No error'); - t.deepEqual(res.body, { query: { name: 'tiger' }, name: 'tiger' }); - t.end(); - server.close(); - }); - }, { log: false }); + start(func) + .then(server => { + t.plan(2); + request(server) + .get('/?name=tiger') + .expect(200) + .expect('Content-Type', /json/) + .end((err, res) => { + t.error(err, 'No error'); + t.deepEqual(res.body, { query: { name: 'tiger' }, name: 'tiger' }); + t.end(); + server.close(); + }); + }); }); test('Integration: handles an HTTP POST', t => { - runtime(func, server => { - t.plan(2); - request(server) - .post('/') - .send({ name: 'tiger' }) - .expect(200) - .expect('Content-Type', /json/) - .end((err, res) => { - t.error(err, 'No error'); - t.deepEqual(res.body, { name: 'tiger' }); - t.end(); - server.close(); - }); - }, { log: false }); + start(func) + .then(server => { + t.plan(2); + request(server) + .post('/') + .send({ name: 'tiger' }) + .expect(200) + .expect('Content-Type', /json/) + .end((err, res) => { + t.error(err, 'No error'); + t.deepEqual(res.body, { name: 'tiger' }); + t.end(); + server.close(); + }); + }); }); test('Integration: responds with error code if neither GET or POST', t => { - runtime(func, server => { - t.plan(1); - request(server) - .put('/') - .send({ name: 'tiger' }) - .expect(200) - .expect('Content-Type', /json/) - .end((err, res) => { - t.deepEqual(res.body, { message: 'Route PUT:/ not found', error: 'Not Found', statusCode: 404 }); - t.end(); - server.close(); - }); - }, { log: false }); + start(func) + .then(server => { + t.plan(1); + request(server) + .put('/') + .send({ name: 'tiger' }) + .expect(200) + .expect('Content-Type', /json/) + .end((err, res) => { + t.deepEqual(res.body, { message: 'Route PUT:/ not found', error: 'Not Found', statusCode: 404 }); + t.end(); + server.close(); + }); + }); });