Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): add helper function to fetch a TD #1169

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions packages/binding-http/test/http-client-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,20 @@ import chai, { expect, should } from "chai";

import * as http from "http";

import { Content, DefaultContent, ContentSerdes, createLoggers, ProtocolServer } from "@node-wot/core";
import {
Content,
DefaultContent,
ContentSerdes,
createLoggers,
ProtocolServer,
Servient,
Helpers,
} from "@node-wot/core";

import { Readable } from "stream";

import HttpClient from "../src/http-client";
import { HttpForm } from "../src/http";
import { HttpForm, HttpClientFactory } from "../src/http";

import express from "express";
import serveStatic from "serve-static";
Expand Down Expand Up @@ -518,4 +526,24 @@ class HttpClientTest2 {
);
});
}

@test async "should fetchTD successfully"() {
const servient = new Servient();
servient.addClientFactory(new HttpClientFactory());
const helpers = new Helpers(servient);
const td = await helpers.fetchTD("http://plugfest.thingweb.io:8083/counter");
expect(td).to.contains.keys("@context", "title");
}

@test async "should fail fetching a non TD resource"() {
const servient = new Servient();
servient.addClientFactory(new HttpClientFactory());
const helpers = new Helpers(servient);
try {
await helpers.fetchTD("http://plugfest.thingweb.io:8083/"); // reports array
expect(1).to.equal(0, "Does not report that we do not deal with a proper TD");
} catch (err) {
// correct since it is not a proper TD
}
}
}
26 changes: 23 additions & 3 deletions packages/core/src/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ import * as TDT from "wot-thing-description-types";
import { ContentSerdes } from "./content-serdes";
import Ajv, { ValidateFunction, ErrorObject } from "ajv";
import TDSchema from "wot-thing-description-types/schema/td-json-schema-validation.json";
import { DataSchemaValue, ExposedThingInit } from "wot-typescript-definitions";
import { DataSchemaValue, ExposedThingInit, ThingDescription } from "wot-typescript-definitions";
import { SomeJSONSchema } from "ajv/dist/types/json-schema";
import { ThingInteraction, ThingModelHelpers } from "@node-wot/td-tools";
import { Resolver } from "@node-wot/td-tools/src/resolver-interface";
Expand Down Expand Up @@ -152,8 +152,28 @@ export default class Helpers implements Resolver {
}
}

// TODO: specialize fetch to retrieve just thing descriptions
// see https://github.com/eclipse-thingweb/node-wot/issues/1055
/**
* Fetches a resource with additionally checking TD conformance
*
* @param uri The URI of a TD resource
* @returns A ThingDescription
*/
public async fetchTD(uri: string): Promise<ThingDescription> {
const data = await this.fetch(uri);
const isValid = Helpers.tsSchemaValidator(data);
if (!isValid) {
const errors = Helpers.tsSchemaValidator.errors?.map((o: ErrorObject) => o.message).join("\n");
throw new Error(errors);
}
return data as ThingDescription;
}

/**
* Fetches a resource
*
* @param uri The URI of a resource
* @returns An object
*/
public fetch(uri: string): Promise<unknown> {
return new Promise<unknown>((resolve, reject) => {
const client = this.srv.getClientFor(Helpers.extractScheme(uri));
Expand Down
8 changes: 3 additions & 5 deletions packages/examples/src/bindings/coap/example-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@

import { Servient, Helpers } from "@node-wot/core";
import { CoapClientFactory } from "@node-wot/binding-coap";
import { ThingDescription } from "wot-typescript-definitions";

// create Servient and add CoAP binding
const servient = new Servient();
servient.addClientFactory(new CoapClientFactory());

const wotHelper = new Helpers(servient);
wotHelper
.fetch("coap://plugfest.thingweb.io:5683/testthing")
.then(async (fetched) => {
const td: ThingDescription = fetched as ThingDescription;
// using await for serial execution (note 'async' in then() of fetch())
.fetchTD("coap://plugfest.thingweb.io:5683/testthing")
.then(async (td) => {
// using await for serial execution (note 'async' in then() of fetchTD())
try {
const WoT = await servient.start();
const thing = await WoT.consume(td);
Expand Down
8 changes: 3 additions & 5 deletions packages/examples/src/bindings/http/example-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,16 @@

import { Servient, Helpers } from "@node-wot/core";
import { HttpClientFactory } from "@node-wot/binding-http";
import { ThingDescription } from "wot-typescript-definitions";

// create Servient and add HTTP binding
const servient = new Servient();
servient.addClientFactory(new HttpClientFactory());

const wotHelper = new Helpers(servient);
wotHelper
.fetch("http://plugfest.thingweb.io:8083/testthing")
.then(async (fetched) => {
const td: ThingDescription = fetched as ThingDescription;
// using await for serial execution (note 'async' in then() of fetch())
.fetchTD("http://plugfest.thingweb.io:8083/testthing")
.then(async (td) => {
// using await for serial execution (note 'async' in then() of fetchTD())
try {
const WoT = await servient.start();
const thing = await WoT.consume(td);
Expand Down
7 changes: 3 additions & 4 deletions packages/examples/src/scripts/counter-client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
********************************************************************************/

import { Helpers } from "@node-wot/core";
import { ThingDescription } from "wot-typescript-definitions";

let WoTHelpers!: Helpers;

Expand All @@ -31,11 +30,11 @@ function getFormIndexForDecrementWithCoAP(thing: WoT.ConsumedThing): number {
return 0;
}

WoTHelpers.fetch("coap://localhost:5683/counter")
WoTHelpers.fetchTD("coap://localhost:5683/counter")
.then(async (td) => {
// using await for serial execution (note 'async' in then() of fetch())
// using await for serial execution (note 'async' in then() of fetchTD())
try {
const thing = await WoT.consume(td as ThingDescription);
const thing = await WoT.consume(td);
console.info("=== TD ===");
console.info(td);
console.info("==========");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
// It considers a fictional smart coffee machine in order to demonstrate the capabilities of Web of Things.
// An accompanying tutorial is available at http://www.thingweb.io/smart-coffee-machine.html.

import { ThingDescription } from "wot-typescript-definitions";
import { Helpers } from "@node-wot/core";
let WoTHelpers!: Helpers;

Expand All @@ -29,9 +28,9 @@ function log(msg: string, data: unknown) {
console.info("======================");
}

WoTHelpers.fetch("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) => {
WoTHelpers.fetchTD("http://127.0.0.1:8080/smart-coffee-machine").then(async (td) => {
try {
const thing = await WoT.consume(td as ThingDescription);
const thing = await WoT.consume(td);
log("Thing Description:", td);

// Read property allAvailableResources
Expand Down
5 changes: 2 additions & 3 deletions packages/examples/src/security/oauth/consumer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,11 @@
* SPDX-License-Identifier: EPL-2.0 OR W3C-20150513
********************************************************************************/
import { Helpers } from "@node-wot/core";
import { ThingDescription } from "wot-typescript-definitions";

let WoTHelpers!: Helpers;

WoTHelpers.fetch("https://localhost:8080/oauth").then((td) => {
WoT.consume(td as ThingDescription).then(async (thing) => {
WoTHelpers.fetchTD("https://localhost:8080/oauth").then((td) => {
WoT.consume(td).then(async (thing) => {
try {
const resp = await thing.invokeAction("sayOk");
const result = await resp?.value();
Expand Down
7 changes: 3 additions & 4 deletions packages/examples/src/testthing/testclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
********************************************************************************/

import { Helpers } from "@node-wot/core";
import { ThingDescription } from "wot-typescript-definitions";
let WoTHelpers!: Helpers;

console.log = () => {
Expand Down Expand Up @@ -51,11 +50,11 @@ async function testPropertyWrite(
}
}

WoTHelpers.fetch("http://localhost:8080/testthing")
WoTHelpers.fetchTD("http://localhost:8080/testthing")
.then(async (td) => {
// using await for serial execution (note 'async' in then() of fetch())
// using await for serial execution (note 'async' in then() of fetchTD())
try {
const thing = await WoT.consume(td as ThingDescription);
const thing = await WoT.consume(td);
console.info("=== TD ===");
console.info(td);
console.info("==========");
Expand Down
Loading