diff --git a/.github/config/nodejs-dev.jsonc b/.github/config/nodejs-dev.jsonc index d5023eb78b..147714b6ab 100644 --- a/.github/config/nodejs-dev.jsonc +++ b/.github/config/nodejs-dev.jsonc @@ -113,6 +113,7 @@ "datacatalog/quickstart", "datacatalog/snippets", "datalabeling", + "datastore/functions", "dialogflow", "discoveryengine", "document-warehouse", diff --git a/.github/config/nodejs-prod.jsonc b/.github/config/nodejs-prod.jsonc index 36697a34d7..0cb4511647 100644 --- a/.github/config/nodejs-prod.jsonc +++ b/.github/config/nodejs-prod.jsonc @@ -84,7 +84,6 @@ "cloud-sql/sqlserver/tedious", // (untested) TypeError: The "config.server" property is required and must be of type string. "compute", // GoogleError: The resource 'projects/long-door-651/zones/us-central1-a/disks/disk-from-pool-name' was not found "dataproc", // GoogleError: Error submitting create cluster request: Multiple validation errors - "datastore/functions", // [ERR_REQUIRE_ESM]: require() of ES Module "dialogflow-cx", // NOT_FOUND: com.google.apps.framework.request.NotFoundException: Agent 'undefined' does not exist "dlp", // [ERR_REQUIRE_ESM]: require() of ES Module "document-ai", // [ERR_REQUIRE_ESM]: require() of ES Module diff --git a/datastore/functions/index.js b/datastore/functions/index.js index 35f30da559..f9a1c288fa 100644 --- a/datastore/functions/index.js +++ b/datastore/functions/index.js @@ -14,7 +14,7 @@ 'use strict'; -const {Datastore} = require('@google-cloud/datastore'); +import {Datastore} from '@google-cloud/datastore'; // Instantiates a client const datastore = new Datastore(); @@ -58,7 +58,7 @@ const getKeyFromRequestData = requestData => { * @param {object} req.body.value Value to save to Cloud Datastore, e.g. {"description":"Buy milk"} * @param {object} res Cloud Function response context. */ -exports.set = async (req, res) => { +export async function set(req, res) { // The value contains a JSON document representing the entity we want to save if (!req.body.value) { const err = makeErrorObj('Value'); @@ -80,7 +80,7 @@ exports.set = async (req, res) => { console.error(new Error(err.message)); // Add to Stackdriver Error Reporting res.status(500).send(err.message); } -}; +} /** * Retrieves a record. @@ -94,7 +94,7 @@ exports.set = async (req, res) => { * @param {string} req.body.key Key at which to retrieve the data, e.g. "sampletask1". * @param {object} res Cloud Function response context. */ -exports.get = async (req, res) => { +export async function get(req, res) { try { const key = await getKeyFromRequestData(req.body); const [entity] = await datastore.get(key); @@ -110,7 +110,7 @@ exports.get = async (req, res) => { console.error(new Error(err.message)); // Add to Stackdriver Error Reporting res.status(500).send(err.message); } -}; +} /** * Deletes a record. @@ -124,7 +124,7 @@ exports.get = async (req, res) => { * @param {string} req.body.key Key at which to delete data, e.g. "sampletask1". * @param {object} res Cloud Function response context. */ -exports.del = async (req, res) => { +export async function del(req, res) { // Deletes the entity // The delete operation will not fail for a non-existent entity, it just // doesn't delete anything @@ -136,4 +136,4 @@ exports.del = async (req, res) => { console.error(new Error(err.message)); // Add to Stackdriver Error Reporting res.status(500).send(err.message); } -}; +} diff --git a/datastore/functions/package.json b/datastore/functions/package.json index 38aca02bee..62c612fbb1 100644 --- a/datastore/functions/package.json +++ b/datastore/functions/package.json @@ -7,6 +7,7 @@ "type": "git", "url": "https://github.com/GoogleCloudPlatform/nodejs-docs-samples.git" }, + "type": "module", "engines": { "node": ">=16.0.0" }, @@ -19,7 +20,7 @@ "devDependencies": { "@google-cloud/functions-framework": "^3.0.0", "c8": "^10.0.0", - "child-process-promise": "^2.2.1", + "child-process-promise": "^2.1.3", "mocha": "^10.0.0", "node-fetch": "^3.0.0", "proxyquire": "^2.1.0", diff --git a/datastore/functions/test/index.test.js b/datastore/functions/test/index.test.js index b683d8ffbb..4bc2cd4922 100644 --- a/datastore/functions/test/index.test.js +++ b/datastore/functions/test/index.test.js @@ -14,22 +14,26 @@ 'use strict'; -const assert = require('assert'); -const execPromise = require('child-process-promise').exec; -const path = require('path'); -const uuid = require('uuid'); -const sinon = require('sinon'); -const fetch = require('node-fetch'); -const waitPort = require('wait-port'); -const {Datastore} = require('@google-cloud/datastore'); +import {ok, strictEqual, deepStrictEqual} from 'assert'; +import {exec as execPromise} from 'child-process-promise'; +import {join} from 'path'; +import {v4} from 'uuid'; +import {stub} from 'sinon'; +import fetch from 'node-fetch'; +import { fileURLToPath } from 'url'; +import { dirname } from 'path'; +import waitPort from 'wait-port'; +import {Datastore} from '@google-cloud/datastore'; const datastore = new Datastore(); -const program = require('../'); +import {set, get, del} from '../'; const FF_TIMEOUT = 3000; -const cwd = path.join(__dirname, '..'); +const __filename = fileURLToPath(import.meta.url); +const __dirname = dirname(__filename); +const cwd = join(__dirname, '..'); const NAME = 'sampletask1'; -const KIND = `Task-${uuid.v4()}`; +const KIND = `Task-${v4()}`; const VALUE = { description: 'Buy milk', }; @@ -72,14 +76,14 @@ describe('functions/datastore', () => { body: {}, }; const res = { - status: sinon.stub().returnsThis(), - send: sinon.stub(), + status: stub().returnsThis(), + send: stub(), }; - await program.set(req, res); + await set(req, res); - assert.ok(res.status.calledWith(500)); - assert.ok(res.send.calledWith(errorMsg('Value'))); + ok(res.status.calledWith(500)); + ok(res.send.calledWith(errorMsg('Value'))); }); it('set: Fails without a key', async () => { @@ -89,12 +93,12 @@ describe('functions/datastore', () => { }, }; const res = { - status: sinon.stub().returnsThis(), - send: sinon.stub(), + status: stub().returnsThis(), + send: stub(), }; - await program.set(req, res); - assert.ok(res.status.calledWith(500)); - assert.ok(res.send.calledWith(errorMsg('Key'))); + await set(req, res); + ok(res.status.calledWith(500)); + ok(res.send.calledWith(errorMsg('Key'))); }); it('set: Fails without a kind', async () => { @@ -105,14 +109,14 @@ describe('functions/datastore', () => { }, }; const res = { - status: sinon.stub().returnsThis(), - send: sinon.stub(), + status: stub().returnsThis(), + send: stub(), }; - await program.set(req, res); + await set(req, res); - assert.ok(res.status.calledWith(500)); - assert.ok(res.send.calledWith(errorMsg('Kind'))); + ok(res.status.calledWith(500)); + ok(res.send.calledWith(errorMsg('Kind'))); }); it('set: Saves an entity', async () => { @@ -125,9 +129,9 @@ describe('functions/datastore', () => { }), headers: {'Content-Type': 'application/json'}, }); - assert.strictEqual(response.status, 200); + strictEqual(response.status, 200); const body = await response.text(); - assert.ok(body.includes(`Entity ${KIND}/${NAME} saved`)); + ok(body.includes(`Entity ${KIND}/${NAME} saved`)); }); }); @@ -159,9 +163,9 @@ describe('functions/datastore', () => { validateStatus: () => true, }); - assert.strictEqual(response.status, 500); + strictEqual(response.status, 500); const body = await response.text(); - assert.ok( + ok( new RegExp( /(Missing or insufficient permissions.)|(No entity found for key)/ ).test(body) @@ -177,9 +181,9 @@ describe('functions/datastore', () => { }), headers: {'Content-Type': 'application/json'}, }); - assert.strictEqual(response.status, 200); + strictEqual(response.status, 200); const body = await response.json(); - assert.deepStrictEqual(body, { + deepStrictEqual(body, { description: 'Buy milk', }); }); @@ -189,14 +193,14 @@ describe('functions/datastore', () => { body: {}, }; const res = { - status: sinon.stub().returnsThis(), - send: sinon.stub(), + status: stub().returnsThis(), + send: stub(), }; - await program.get(req, res); + await get(req, res); - assert.ok(res.status.calledWith(500)); - assert.ok(res.send.calledWith(errorMsg('Key'))); + ok(res.status.calledWith(500)); + ok(res.send.calledWith(errorMsg('Key'))); }); it('get: Fails without a kind', async () => { @@ -206,14 +210,14 @@ describe('functions/datastore', () => { }, }; const res = { - status: sinon.stub().returnsThis(), - send: sinon.stub(), + status: stub().returnsThis(), + send: stub(), }; - await program.get(req, res); + await get(req, res); - assert.ok(res.status.calledWith(500)); - assert.ok(res.send.calledWith(errorMsg('Kind'))); + ok(res.status.calledWith(500)); + ok(res.send.calledWith(errorMsg('Kind'))); }); }); @@ -239,14 +243,14 @@ describe('functions/datastore', () => { body: {}, }; const res = { - status: sinon.stub().returnsThis(), - send: sinon.stub(), + status: stub().returnsThis(), + send: stub(), }; - await program.del(req, res); + await del(req, res); - assert.ok(res.status.calledWith(500)); - assert.ok(res.send.calledWith(errorMsg('Key'))); + ok(res.status.calledWith(500)); + ok(res.send.calledWith(errorMsg('Key'))); }); it('del: Fails without a kind', async () => { @@ -256,14 +260,14 @@ describe('functions/datastore', () => { }, }; const res = { - status: sinon.stub().returnsThis(), - send: sinon.stub(), + status: stub().returnsThis(), + send: stub(), }; - await program.del(req, res); + await del(req, res); - assert.ok(res.status.calledWith(500)); - assert.ok(res.send.calledWith(errorMsg('Kind'))); + ok(res.status.calledWith(500)); + ok(res.send.calledWith(errorMsg('Kind'))); }); it("del: Doesn't fail when entity does not exist", async () => { @@ -275,9 +279,9 @@ describe('functions/datastore', () => { }), headers: {'Content-Type': 'application/json'}, }); - assert.strictEqual(response.status, 200); + strictEqual(response.status, 200); const body = await response.text(); - assert.strictEqual(body, `Entity ${KIND}/nonexistent deleted.`); + strictEqual(body, `Entity ${KIND}/nonexistent deleted.`); }); it('del: Deletes an entity', async () => { @@ -289,13 +293,13 @@ describe('functions/datastore', () => { }), headers: {'Content-Type': 'application/json'}, }); - assert.strictEqual(response.status, 200); + strictEqual(response.status, 200); const body = await response.text(); - assert.strictEqual(body, `Entity ${KIND}/${NAME} deleted.`); + strictEqual(body, `Entity ${KIND}/${NAME} deleted.`); const key = datastore.key([KIND, NAME]); const [entity] = await datastore.get(key); - assert.ok(!entity); + ok(!entity); }); }); });