@htfn/cli
v0.0.11
Published
Hypertext Functions (HTFN) CLI (Alpha). To view our terms of service, please run: htfn terms
Downloads
710
Readme
Hypertext Functions (Alpha)
JavaScript Functions that Speak HTTP
Create JavaScript (or TypeScript) functions that run in the cloud. Start building APIs, websites and single page applications in just a few key presses.
Build hypertext functions like this in seconds:
// myfunc.ts
export default function (req: Request) {
return Response.json({ message: "Hellorld!", url: req.url });
}
Deploy the function immediately, no build step required: 🚀
htfn deploy myfunc ./myfunc.ts
🥁 Drumroll please... https://myfunc-a40a5cc495e7b04e.fn.htfn.io
Platform
Hypertext functions do not run inside NodeJS, they use Google V8 directly, so functions cannot call any of the NodeJS APIs. This here is WinterCG country 🦇
Not all WinterCG runtime APIs are implemented (yet), but this is work in progress. At the moment, you can use the following:
fetch()
console.*
localStorage.*
self.crypto.randomUUID()
self.crypto.getRandomValues()
setTimeout()
setInterval()
btoa()
atob()
TextDecoder
TextEncoder
Please note that all assets (css, images, JavaScript bundles, etc.) are aggressively HTTP cached. It's best to implement
cache busting techniques. We use private
caching, so
if you're iteratively building a function you can just temporarily turn your browser cache off.
This is alpha software and may be prone to bugs. Please be advised that your data is at risk and may be lost without warning. By using Hypertext Functions you agree with our terms of service.
Limitations
Hypertext Functions is currently a completely free service. The following limitations apply:
- Maximum of 3 hypertext functions per account
- Maximum of 1,000,000 versions per function
- Maximum of 100Mb of stored assets per account (including function code)
- Maximum of 100Mb of local storage per account
- Maximum of 20 calls to
fetch()
per function call - Maximum of 10 custom domains
- Maximum of 80 environment variables
- 128Mb of memory per function call
- Timeout of 6 seconds per function call
Installation
Install Hypertext Functions CLI globally:
npm install -g @htfn/cli
htfn login
Or run directly via npx:
npx @htfn/cli login
If your browser doesn't automatically open when logging in, use the following flag to get the login URL and copy/paste that into your browser instead:
htfn login --url
# or
npx @htfn/cli login --url
IMPORTANT: Hypertext Functions CLI tool requires NodeJS version >= 18.0.0
Getting Started
Create a simple JavaScript hypertext function file with the following contents:
// hellorld.js
export default function (request) {
const name = new URL(request.url).searchParams.get('name') ?? 'World';
return Response.json({
message: `Hello ${name}`,
});
}
Login to the Hypertext Functions service (authorization is currently only via GitHub - so you'll need a GitHub account to proceed).
htfn login
# or use this flag to get the login URL instead
htfn login --url
Deploy the function that we defined above.
htfn deploy hellorld ./hellorld.js
If the deployment was a success, you'll be presented with a set of URLs to access your new function. The URL will look something like this:
https://hellorld-68efe810aa4648b8.fn.htfn.io/?name=Joe
Monitor the logs for a hypertext function. Logs contain messages from console.log()
as well as system events:
htfn log tail hellorld
Functions
List Functions
List all of your deployed functions:
htfn list
Filter functions by name:
htfn list --filter=hellorld
Display more information about each function in the list:
htfn list --extended
Get the list of functions as JSON:
htfn list --json
List Function Versions
List versions of a particular hypertext function:
htfn versions hellorld
Filter function versions by contents of the push message:
htfn versions hellorld --filter="critical update"
Display more information about each function version in the list:
htfn versions hellorld --extended
Get the list of function versions as JSON:
htfn versions hellorld --json
Build a Function
Build and bundle a given function, sending the built JavaScript to stdout:
htfn build ./hellorld.js
Hypertext Functions CLI tool is also bundled with ESBuild, so you can build TypeScript functions too :)
htfn build ./hellorld.ts
Pushing Function Versions
When you want to build and upload a new function version without making the new version "production":
htfn push hellorld ./hellorld.ts
Push the new version with an associated message:
htfn push hellorld ./hellorld.ts --message="did some stuff and things"
Push a new function version without building first, just upload the function as-is:
htfn push hellorld ./hellorld.ts --no-build
Build & push a new function version, then promote the new version to "production":
htfn push hellorld ./hellorld.ts --promote
Sometimes you may have a frontend bundle that your function may access when running in the client. E.g. let's say you build a server-side rendered ReactJS SPA that has some client-side code, you can build, bundle and push this as an asset too:
Note that the "client" file, in this case
App.tsx
, must be in the root of your function directory
htfn push hellorld ./hellorld.ts --client=./App.tsx
Promote
Promote any version of a hypertext function to be the "production" version.
Promote the "latest" function version to production:
htfn promote hellorld --latest
Promote a particular function version to production, by passing the version ID:
htfn promote hellorld --version=TuetYWNHhmuSQ3xPoVLv9M
Prune
You can prune a given hypertext function, whereby all non-production versions will be permanently deleted:
htfn prune hellorld
Upload Assets
You may also upload a directory of assets (e.g. images, fonts, etc.) that will be served from the root of your function URL:
Note that in the following example there's a directory named
assets
containing the assets you wish to upload
htfn push hellorld ./hellorld.ts --assets=./assets
Deploying
Putting it altogether - instead of building, pushing and promoting as separate commands, you can simply run the deploy
command to perform all of these things at once; build, push & promote at the same time:
htfn deploy hellorld ./hellorld.ts --assets=./assets --client=./App.tsx
Removing
You can permanently delete functions by removing them like so:
htfn remove hellorld
Where hellorld
is the name of your function.
If you like to live dangerously, you can forcefully remove functions immediately:
htfn remove hellorld --force
Domains
You can add arbitrary domains to your hypertext functions, making your function production versions easier and more
memorable to access. At the moment, you can only add subdomains of htfn.io
.
Add a Domain
Add a domain to the existing hypertext function, hellorld
:
htfn domains add hellorld myfunction.htfn.io
List Domains
List domains for the hypertext function, hellorld
:
htfn domains list hellorld
Remove a Domain
Remove a domain from the hypertext function, hellorld
:
htfn domains remove hellorld myfunction.htfn.io
Environment Variables
You can add the following types of environment variables:
- Organisation - env vars available to all of your hypertext functions
- Function - env vars available to a particular hypertext function
Function env vars trump organisation env vars. All env vars are strings.
Environment vars may be accessed via the process.env
object in your hypertext function, like so:
export default function () {
return Response.json({ my_var_one: process.env.MY_VAR_ONE });
}
Set Environment Variables
In order to set a value for MY_VAR_ONE
:
# Set function env var
htfn env set func hellorld -e MY_VAR_ONE='val1'
# Set the same env var at organisation level
htfn env set org -e MY_VAR_ONE='val1'
List Environment Variables
List env vars for a particular function:
htfn env list func hellorld
List env vars for a your organisation:
htfn env list org
Remove Environment Variables
Remove a function env var
htfn env remove func hellorld -e MY_VAR_ONE
Remove an organisation env var
htfn env remove org -e MY_VAR_ONE
Logs
You can watch the tail of a particular hypertext function's log:
Tailing Logs
htfn log tail hellorld
Filter by log level:
htfn log tail hellorld --level=error
Output JSON:
htfn log tail hellorld --json
Only show log entries from a given date/time:
htfn log tail hellorld --from="2024-02-26 15:08:18"
Search Logs
You can search the log by request ID (found in the response header of a called function):
htfn log find FRAMwPMUKfX8kmwDyW8Evc
Output JSON:
htfn log find FRAMwPMUKfX8kmwDyW8Evc --json
Filter by log level:
htfn log find FRAMwPMUKfX8kmwDyW8Evc --level=error
Miscellaneous
Some other hypertext function CLI commands that don't quite fit the categories above.
My Profile
Get details about your Hypertext Functions account and profile
htfn whoami
Logout
Log out of all of your active sessions, deleting all sessions in the process:
htfn logout
Terms of Service
View the Hyptertext Functions terms of service (opens in your browser):
htfn terms
Contact Us
Opens the Hypertext Functions contact form in your browser:
htfn contact
Function Examples
Some hypertext function ideas to get you started :)
Simple JSON Response
// simplejson.ts
export default function (req: Request): Response {
return Response.json({ message: "Hellorld!" });
}
htfn deploy simplejson ./simplejson.ts
Simple HTML Response
// simplehtml.ts
export default function (req: Request): Response {
return new Response(`<strong>Hellorld!</strong>`, { headers: {
"content-type": "text/html",
}});
}
htfn deploy simplehtml ./simplehtml.ts
Simple Fetch
// simplefetch.ts
export default async function (req: Request): Response {
const res = await fetch("https://example.com");
return new Response(await res.text(), { headers: {
"content-type": "text/html",
}});
}
htfn deploy simplefetch ./simplefetch.ts
What's My IP?
// myip.ts
export default function (req: Request) {
return Response.json({
your_ip: req.headers.get('x-real-ip'),
});
}
htfn deploy myip ./myip.ts
Storage
// storage.ts
export default function (req: Request) {
const message = new URL(req.url).searchParams.get('message') ?? 'default message';
// Make use of the full localStorage API, not just setItem() :)
// The local storage item "my_message" will be available in all of your hypertext functions
localStorage.setItem("my_message", message);
return Response.json({ message: localStorage.getItem("my_message") });
}
htfn deploy storage ./storage.ts
Random v4 UUID
// randomuuid.ts
export default function (req: Request) {
return Response.json({
random_uuid: self.crypto.randomUUID(),
});
}
htfn deploy randomuuid ./randomuuid.ts
Hono Framework
Use the Hono framework to build a REST API:
npm init
npm install hono
// hono.ts
import { Hono } from 'hono';
const app = new Hono();
app.get('/users', (c) => c.json([{ name: 'Joe Bloggs' }]));
export default app.fetch;
htfn deploy hono ./hono.ts
More examples to follow...