Skip to content
This repository was archived by the owner on Oct 8, 2024. It is now read-only.

Commit 5a693eb

Browse files
Add http.fetch API and examples (#84)
1 parent f591ebe commit 5a693eb

File tree

18 files changed

+3869
-5
lines changed

18 files changed

+3869
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Fixed threshold logic bug in `inference.classifyText` [#76](https://github.com/gohypermode/functions-as/pull/76)
66
- Align `hypermode.json` examples to changes in manifest schema [#79](https://github.com/gohypermode/functions-as/pull/79) [#80](https://github.com/gohypermode/functions-as/pull/80) [#81](https://github.com/gohypermode/functions-as/pull/81)
7+
- Add `http.fetch` API [#84](https://github.com/gohypermode/functions-as/pull/84)
78

89
# 2024-04-25 - Version 0.6.1
910

examples/classification/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Hypermode Classification Example Plugin
22

3-
This is an example shows how to invoke a model that can perform classification.
3+
This example shows how to invoke a model that can perform classification.
44

55
See [./assembly/index.ts](./assembly/index.ts) for the implementation.

examples/embedding/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Hypermode Embedding Example Plugin
22

3-
This is an example shows how to invoke a model that can calculate vector embeddings.
3+
This example shows how to invoke a model that can calculate vector embeddings.
44

55
See [./assembly/index.ts](./assembly/index.ts) for the implementation.

examples/graphql/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Hypermode GraphQL Example Plugin
22

3-
This is an example shows how to call a GraphQL endpoint to execute queries and mutations.
3+
This example shows how to call a GraphQL endpoint to execute queries and mutations.
44

55
It uses a Dgraph, at the host configured in the `hypermode.json` manifest.
66

examples/http/.eslintrc.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"env": {
3+
"es6": true
4+
},
5+
"extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
6+
"parser": "@typescript-eslint/parser",
7+
"parserOptions": {
8+
"ecmaVersion": "latest",
9+
"sourceType": "module"
10+
},
11+
"plugins": ["@typescript-eslint"]
12+
}

examples/http/.prettierrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"plugins": ["assemblyscript-prettier"]
3+
}

examples/http/README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# Hypermode HTTP Example Plugin
2+
3+
This example shows how to call an external host via HTTP `fetch`.
4+
5+
See [./assembly/index.ts](./assembly/index.ts) for the implementation.
6+
7+
Note that any host used by the `fetch` function must have a base URL defined
8+
as a host in the [`hypermode.json`](./hypermode.json) manifest file.
9+
This is a security measure that prevents arbitrary hosts from being called
10+
based solely on function input values.

examples/http/asconfig.json

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"extends": "./node_modules/@assemblyscript/wasi-shim/asconfig.json",
3+
"options": {
4+
"transform": ["@hypermode/functions-as/transform", "json-as/transform"],
5+
"exportRuntime": true
6+
},
7+
"targets": {
8+
"debug": {
9+
"sourceMap": true,
10+
"debug": true
11+
},
12+
"release": {
13+
"optimizeLevel": 3,
14+
"shrinkLevel": 0,
15+
"converge": false,
16+
"noAssert": false
17+
}
18+
}
19+
}

examples/http/assembly/classes.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// For now, this import is required when we use @json, even if we're not calling
2+
// methods on the JSON class. It will be fixed in the future.
3+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
4+
import { JSON } from "json-as";
5+
6+
// These classes are used by the example functions in the index.ts file.
7+
8+
@json
9+
export class Quote {
10+
11+
@alias("q")
12+
quote!: string;
13+
14+
15+
@alias("a")
16+
author!: string;
17+
}
18+
19+
export class Image {
20+
contentType!: string;
21+
data!: ArrayBuffer;
22+
}
23+
24+
25+
@json
26+
export class Issue {
27+
title!: string;
28+
body!: string;
29+
30+
// The URL of the issue on GitHub, after the issue is created.
31+
@alias("html_url")
32+
url: string | null = null;
33+
}

examples/http/assembly/index.ts

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import { http } from "@hypermode/functions-as";
2+
import { Quote, Image, Issue } from "./classes";
3+
4+
// This function makes a simple HTTP GET request to example.com,
5+
// and returns the HTML text of the response.
6+
export function getExampleHtml(): string {
7+
const response = http.fetch("https://example.com/");
8+
return response.text();
9+
}
10+
11+
// This function makes a request to an API that returns data in JSON format,
12+
// and returns an object representing the data.
13+
// It also demonstrates how to check the HTTP response status.
14+
export function getRandomQuote(): Quote {
15+
const request = new http.Request("https://zenquotes.io/api/random");
16+
17+
const response = http.fetch(request);
18+
if (!response.ok) {
19+
throw new Error(
20+
`Failed to fetch quote. Received: ${response.status} ${response.statusText}`,
21+
);
22+
}
23+
24+
// The API returns an array of quotes, but we only want the first one.
25+
return response.json<Quote[]>()[0];
26+
}
27+
28+
// This function makes a request to an API that returns an image, and returns the image data.
29+
export function getRandomImage(width: i32, height: i32): Image {
30+
const url = `https://picsum.photos/${width}/${height}`;
31+
const response = http.fetch(url);
32+
const contentType = response.headers.get("Content-Type")!;
33+
34+
return {
35+
contentType,
36+
data: response.body,
37+
};
38+
}
39+
40+
// This function demonstrates a more complex HTTP call.
41+
// It makes a POST request to the GitHub API to create an issue.
42+
// See https://docs.github.com/en/rest/issues/issues?apiVersion=2022-11-28#create-an-issue
43+
// To use it, you must add a GitHub personal access token to your Hypermode secrets.
44+
// Create a fine-grained token at https://github.com/settings/tokens?type=beta with access
45+
// to write issues to the repository you want to use.
46+
//
47+
// NOTE: do not pass the Authorization header in the request.
48+
// Instead, set the authHeader in the hypermode.json manifest file to "Authorization".
49+
// The Hypermode Runtime will retrieve the token from your secrets and add it to the request.
50+
// The secret should be prefixed with "Bearer ".
51+
// In development, you can set the token as an environment variable, in an .env file if desired.
52+
// Example: HYP_HOST_KEY_GITHUB=Bearer <your-token>
53+
export function createGithubIssue(
54+
owner: string,
55+
repo: string,
56+
title: string,
57+
body: string,
58+
): Issue {
59+
// The URL for creating an issue in a GitHub repository.
60+
const url = `https://api.github.com/repos/${owner}/${repo}/issues`;
61+
62+
// Create a new request with the URL, method, and headers.
63+
const request = new http.Request(url, {
64+
method: "POST",
65+
headers: http.Headers.from([
66+
// Do not pass an Authorization header here. See note above.
67+
["Accept", "application/vnd.github+json"],
68+
["X-GitHub-Api-Version", "2022-11-28"],
69+
["Content-Type", "application/json"],
70+
]),
71+
72+
// The request body will be sent as JSON from the Issue object passed here.
73+
body: http.Content.from(<Issue>{ title, body }),
74+
} as http.RequestOptions);
75+
76+
// Send the request and check the response status.
77+
// NOTE: If you are using a private repository, and you get a 404 error, that could
78+
// be an authentication issue. Make sure you have created a token as described above.
79+
const response = http.fetch(request);
80+
if (!response.ok) {
81+
throw new Error(
82+
`Failed to create issue. Received: ${response.status} ${response.statusText}`,
83+
);
84+
}
85+
86+
// The response will contain the issue data, including the URL of the issue on GitHub.
87+
return response.json<Issue>();
88+
}

0 commit comments

Comments
 (0)