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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@webdyne/webdyne-cloudflare

v1.7.1

Published

Cloudflare service extensions for WebDyne running under WebAssembly

Readme

WebDyne::Cloudflare

Use Cloudflare services from WebDyne PSP pages or native PAGI applications under ZeroPerl. The npm package @webdyne/webdyne-cloudflare includes both the Perl modules and JavaScript adapters. No separate CPAN installation is required in the Worker.

| Service | Perl API | WebDyne example | | --- | --- | --- | | D1 queries and atomic batches | D1 | Storage | | D1 sessions and bookmarks | Sessions | Bookmark continuation | | Workers KV | KV | Storage | | R2 buffered objects | R2 | Storage | | PostgreSQL through Hyperdrive | Hyperdrive | Inventory | | MySQL through Hyperdrive | MySQL | Inventory | | Secrets Store retrieval | Secrets Store | Safe retrieval | | Durable Object RPC and Perl SQLite handlers | Durable Objects | Counter |

Quick start

Start with the examples guide. Each service directory is a standalone application with WebDyne as its default entry and, where useful, a native PAGI alternative.

For a new application:

npm init -y
npm install @webdyne/webdyne-zeroperl@^1.0.14 @webdyne/webdyne-cloudflare@^1.7.1
npx webdyne-cloudflare init

Install the released packages from npm. See the examples guide for complete local development instructions. Create app/app.psp, enable the extension and configure the required bindings in package.json using the configuration guide, then run npm run check and npm run dev. Initialization creates scaffolding; it does not create your application page or provision Cloudflare resources.

Request lifetime and Futures

Construct facades inside the request. In WebDyne, the scope is $self->r()->{'scope'}; native PAGI receives $scope_hr directly. Cloudflare bindings and database credentials remain in JavaScript. Perl receives an opaque capability that expires when the request or invocation finishes. Do not retain facades, statements, or unfinished operations in package globals.

Service I/O returns Futures. The WebDyne examples retrieve results with ->get() through ZeroPerl's host bridge. Native async handlers use Future::AsyncAwait and await. Complete all work within the request; dropping a Future does not schedule background work. Hyperdrive uses familiar DBI-style method names and argument positions, but is asynchronous and is not DBI-compatible.

use WebDyne::Cloudflare::D1;

sub customer {
    my ($self, $match_hr)=@_;
    my $db_or=WebDyne::Cloudflare::D1->new(
        scope => $self->r()->{'scope'}, binding => 'DB',
    );
    return $db_or->prepare('SELECT name FROM customers WHERE id=?1')
        ->bind($match_hr->{'id'})->first()->get();
}

Use bound SQL parameters and the service's explicit byte/blob wrapper for binary data. Escape values inserted into HTML. See the individual API references for result types, errors, limits, and transaction behavior. A timeout or failed commit does not prove a database write was cancelled; ambiguous writes are never retried automatically. Runtime teardown awaits resource cleanup.

Text, binary data and errors

Perl character strings cross as text. Unflagged non-ASCII strings are decoded strictly as UTF-8, including SQL, keys, column names and nested metadata/JSON keys and values. Invalid UTF-8 fails before the host call. Normalization copies containers without changing caller data; cycles and keys which become identical after UTF-8 decoding are rejected.

Use the service's blob($bytes) wrapper for binary values. Returned binary data becomes ordinary Perl byte strings. D1 preserves numbers, zero, empty strings, JSON booleans and SQL NULL (undef). KV/R2 put treats a plain numeric body as text; use KV put_json to retain JSON numeric/boolean types.

Missing capabilities or invalid constructor arguments throw immediately. Service operations fail their Future on errors. Host errors use WebDyne::Cloudflare::D1::Error, KV::Error or R2::Error, with name(), message(), code() and cause() accessors and stringification. Local input validation errors can be plain exceptions. Catch failures around await or ->get(); don't assume every exception is a service Error object.

KV values and R2 bodies are buffered, with a default bridge limit of 16 MiB. KV provider reads are buffered before the limit check; it is not a streaming memory guarantee. R2 rejects oversized reads and cancels unread bodies. Increasing the limits increases interpreter/Worker memory pressure and does not lift Cloudflare's own service limits.

R2 streaming, multipart uploads, conditional requests, signed URL generation and automatic retries are not implemented for the storage APIs. Use the documented methods rather than assuming the complete JavaScript binding API is available in Perl.

Development and documentation

Perl 5.20+ with Future and Future::AsyncAwait is declared; current native tests use Perl 5.44. Use Node.js 24+ for the full suite, including SQLite tests.

npm ci --ignore-scripts
perl Makefile.PL
make test
make distcheck
npm run pack:check
  • API overview: maintained sidecars beside Perl source.
  • Configuration: binding allowlists and generated Wrangler resources.
  • Examples: runnable applications, separate from regression fixtures.
  • Testing: contract, package and Worker integration commands.
  • Qualification record: dated evidence and explicit limits.
  • Release and staging: Gitea source, GitHub qualification and npm MFA handoff.
  • t/: Perl tests, fixtures and maintained integration harnesses.
  • t.js/: JavaScript tests, smoke runners and package checks.

Generated consumers, npm archives and local Wrangler state are ignored build outputs. Keep them out of source distributions. Historical implementation reports and superseded prototypes are available in Git history before the 1.7.1 cleanup.