npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@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...