@sanoma-ai/connector-cloudflare 0.6.1 → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -82,16 +82,38 @@ The logo is Cloudflare's cloud from [Simple Icons](https://simpleicons.org/?q=cl
82
82
 
83
83
  ## The Worker
84
84
 
85
- The package ships the Worker it uploads, `worker/`: `index.js`, which exports the Durable Object class `SanomaInstance` over `DurableObject` from `cloudflare:workers`, and `instance.js`, the object's code with no imports (typed by `instance.d.ts`), which the fake runs in Node so both kits check the code Cloudflare runs. Every request to the Worker goes to its one object, which:
85
+ The Worker script is the company's app. The package ships what it uploads, `worker/`: `index.js`, the entry, and `instance.js`, its logic with no imports (typed by `instance.d.ts`), which the fake runs in Node so both kits check the code Cloudflare runs. Beside them goes the app bundle under `app/` ([The deploy](#the-deploy)), or, until a create's first bundle, `no-app.js` in its place, which answers 503 "being set up". The entry's fetch:
86
86
 
87
- - starts the container on a request at the Worker's source revision, configuration revision and uploaded image (`ctx.container.images.runtime`: the copy, pinned by digest), as a `standard-1` instance (½ vCPU, 4 GiB: the policy refuses `basic`), with the Worker's text bindings (plain and secret) as its environment. Container labels hold the two non-secret revisions, an image hash and a hash of `SANOMA_DOMAINS` (so a change of the sites' domains alone starts it again, its environment and its sites bundle with them); a running container with different labels is destroyed and started again. Secret values never enter these labels;
88
- - waits for the container's `/healthz` (up to ten minutes, the clone and install included), sets its inactivity timeout to ten minutes, and proxies the request to its `port` with the Host it was asked for and `x-forwarded-proto` (the port's fetch reaches the container whatever the URL's host, which becomes the request's Host header: so the company serves the public site declared on a domain);
89
- - answers `GET /__sanoma/health` with the source revision, configuration revision when set, and running/readiness state without starting the container. With `?start=1`, it waits until the container answers; a create or update checks both revisions before completing;
90
- - holds the company's one wake at `/__sanoma/wake`, with `Authorization: Bearer <SANOMA_WAKEUP_TOKEN>`: `GET` shows `{ at, rang? }`, `PUT { at }` replaces it and sets the object's alarm, `DELETE` clears it. Without the token among the host's secrets it answers 404, with another one 401;
87
+ - sends `/__sanoma/health`, `/__sanoma/wake` and `/__sanoma/app-bundle` to the Worker's one Durable Object, `SanomaInstance` (`DurableObject` from `cloudflare:workers`);
88
+ - answers `GET /wake`, the Host contract's wake, by having the object start the container now (204);
89
+ - hands every other request to the app bundle's `fetch(request, env, ctx, host)`, imported on the first request, with `x-sanoma-client-ip` set from `cf-connecting-ip` over any copy the client sent, and `host.startNow()` the object's, over RPC (the app's call when it queues a run). A page, an API call, a webhook and a sign-in are all the app's, on the Worker, so a visitor never waits for a cold container (forty seconds to minutes), and the app reaches the company's database through [Hyperdrive](#the-database).
90
+
91
+ The object runs the company's worker in its container and never sees a visitor's request. It:
92
+
93
+ - starts the container at the Worker's source revision, configuration revision and uploaded image (`ctx.container.images.runtime`: the copy, pinned by digest), as a `standard-1` instance (½ vCPU, 4 GiB: the policy refuses `basic`), with the Worker's text bindings (plain and secret) as its environment, and waits for its `/healthz` (up to ten minutes, the clone and install included). Container labels hold the two non-secret revisions, an image hash and a hash of `SANOMA_DOMAINS`; secret values never enter them. A container running with other labels is drained: sent SIGTERM, so its worker stops dequeuing and exits, given thirty seconds, then destroyed if it still runs, and started again at the Worker's labels;
94
+ - answers `GET /__sanoma/health` with the source revision, configuration revision when set, and whether the container runs and answered, without starting it. With `?start=1` and `Authorization: Bearer <SANOMA_WAKEUP_TOKEN>`, it starts the container at the Worker's revisions, answering 202 until it answers, then 200;
95
+ - passes `GET /__sanoma/app-bundle?revision=` with the token on to the container's port, starting the container first (202 meanwhile): the worker there builds the bundle at that revision ([The deploy](#the-deploy));
96
+ - holds the company's one wake at `/__sanoma/wake`, with the token: `GET` shows `{ at, rang? }`, `PUT { at }` replaces it and sets the object's alarm, `DELETE` clears it. Each route that needs the token answers 401 to another one, and 404 on a host without one;
91
97
  - at the alarm, starts the container and calls its `/wake`, then notes when (`rang`); a failure throws, so Cloudflare rings the alarm again;
92
- - over RPC, `startNow()` (the sites router's call, [Public sites on the Worker](#public-sites-on-the-worker)): sets the alarm now, unless one is due sooner, and the alarm starts the container without the caller waiting and sends it `/wake` (its worker may have stopped itself while the container stayed up); a wake held for later is set again once the start is made, and one that rang never rings twice.
98
+ - over RPC, `startNow()`: sets the alarm now, unless one is due sooner, and the alarm starts the container without the caller waiting and sends it `/wake`; a wake held for later is set again once the start is made, and one that rang never rings twice.
99
+
100
+ A container that ended reports how once (`exit`, a 503), so a deploy waiting on it stops rather than starting it again. Cloudflare stops the container after ten minutes without a request to the object; the object, its storage and its alarm stay. Visitors' requests go to the app, not the object, so a run the worker keeps busy longer than that relies on the worker's own registration (a sleep's end, a queued run's `startNow`) to start it again.
101
+
102
+ The application is of the `durable_object` scheduling policy (public beta, the one Cloudflare documents for new applications; it refused `default` on the account the connector was first run on): the object starts its container, with the image and the instance type it names, so the application is only a name and the object's namespace, and has no image, versions or rollouts. The policy is fixed once an application is made: one of the `default` policy under that name is deleted by hand before the apply. A Worker of that name that is not Sanoma's (no `SANOMA_INSTANCE` binding) reads as gone, and a create or a delete refuses to touch it.
103
+
104
+ ## The deploy
105
+
106
+ A create, in Wrangler's order, copies and pins the image and waits until Cloudflare prepared it ([The image](#the-image)), makes or updates the [database's config](#the-database), and, the first time, uploads the Worker without an app (`no-app.js`) with the object's migration (`new_sqlite_classes`) and its class as a container's with that image (`containers: [{ name, class_name, images: { runtime } }]`), turns its workers.dev URL on, makes the application for the object's namespace (`{ name, scheduling_policy: "durable_object", durable_objects: { namespace_id } }`), and uploads that Worker once more: the object learns which application backs its namespace only from a deployment made after the application exists (without it every start answers "There is no container application assigned to this Durable Object namespace", found on the first real deploy, 2026-10-29). Then every create and update deploys in three steps:
93
107
 
94
- Cloudflare stops the container after ten quiet minutes; the object, its storage and its alarm stay, and the next request or alarm starts the container again. The application is of the `durable_object` scheduling policy (public beta, the one Cloudflare documents for new applications; it refused `default` on the account the connector was first run on): the object starts its container, with the image and the instance type it names, so the application is only a name and the object's namespace, and has no image, versions or rollouts. A create, in Wrangler's order, copies and pins the image and waits until Cloudflare prepared it ([The image](#the-image)), uploads the Worker with the object's migration (`new_sqlite_classes`) and its class as a container's with that image (`containers: [{ name, class_name, images: { runtime } }]`, as Wrangler sends it), turns its workers.dev URL on, makes the application for the object's namespace (`{ name, scheduling_policy: "durable_object", durable_objects: { namespace_id } }`, the `namespace_id` the Worker's settings then show), and uploads the Worker once more: the object learns which application backs its namespace only from a deployment made after the application exists, and without that upload every start answers "There is no container application assigned to this Durable Object namespace", for good (found on the first real deploy, 2026-10-29); an update does the same, except that it leaves the application as it is: a new image is a new upload naming it, and the object destroys a container started at another and starts it again at the next request. Either waits for the Worker to answer at the requested source and configuration revisions. The policy is fixed once an application is made, and the object cannot start a container under another: one of the `default` policy under that name (none can be made any more) is deleted by hand before the apply. A plan compares secret binding names, never values: the Worker's settings never show them. Advance `configurationRevision` to upload rotated values and restart a running container with them; a value change alone does not trigger an update. A delete detaches the custom domains the Worker was declared to serve (its `hostname` too), deletes the application, then the Worker with its object's storage. A Worker of that name that is not Sanoma's (no `SANOMA_INSTANCE` binding) reads as gone, and a create or a delete refuses to touch it.
108
+ 1. **The bundle.** `GET /__sanoma/app-bundle?revision=R` on the workers.dev URL with the instance token, asked every poll: the object starts the container at the Worker's current revision if it is stopped (202, unmarked), and the worker there checks out `R` and builds the app bundle for `workerd` (`@sanoma-ai/app`'s `AppBundle`: its modules, its assets, its compatibility date and flags), answering 202 until it is built, then 200 with it, each answer marked `x-sanoma-app-bundle`. The bundle has its own budget, `startTimeoutMs` (ten minutes): still none after it fails the apply retryably, "still building the app bundle at R after 600 s", saying what the last ask saw. A marked answer other than 200 or 202 (a failed build, a revision the route refuses) is a refusal. A deployment that cannot build it, a 401 (the deployed Worker or its container holds another token), an `exit` (its worker ends at startup) or an unmarked 404 (a runtime without the route), is recovered once: the Worker at R without its app (`no-app.js`) is uploaded, so the object starts the container at R, and the bundle is asked of it, the app's pages saying it is being set up until step 2; the same answer again is a refusal. Anything else (no answer, an error of Cloudflare's, a body cut off, a workers.dev URL not routed yet) is asked again; one ask may take the whole budget, as a bundle is large. Its assets (the client build and the prerendered pages) then go in through an [assets upload session](https://developers.cloudflare.com/workers/static-assets/direct-upload/) (`POST …/scripts/{name}/assets-upload-session { manifest }`, then each bucket it asks for, one after another, to `POST …/workers/assets/upload?base64=true` with the session's jwt).
109
+ 2. **One upload.** The domains no longer declared are detached, then the Worker is uploaded once with everything: `index.js`, `instance.js` and the bundle's modules under `app/`, its compatibility date and flags, the bindings (the declared ones, the namespace, `DATABASE` as Hyperdrive, `ASSETS`) and `assets: { jwt, config }` (`run_worker_first: ["/*", "!/assets/*"]`, the client build straight from the assets; `html_handling` and `not_found_handling` `none`). From here visitors get the new app; the container is still the old revision's. Then the missing domains are attached.
110
+ 3. **The restart.** `GET /__sanoma/health?start=1` with the token, asked every poll until the object answers 200 at `R` and the configuration revision: the object drains the old container (SIGTERM, thirty seconds, then destroyed) and starts one at `R`. Its own budget, the same `startTimeoutMs`: still not after it fails the apply retryably, "still starting at R after 600 s". The step is idempotent: the next apply plans none, and an explicit update whose plan is none runs it alone, uploading nothing.
111
+
112
+ No step answers a visitor 503 (but a recovered deployment's, above): the old app answers until the upload, the new one after it, and neither needs the container. A built-in workflow's runs on R-1 carry to R when its code is unchanged (`builtInCode` in `@sanoma-ai/workflows`), so the restart strands none of them. A plan compares secret binding names, never values: the Worker's settings never show them. Advance `configurationRevision` to upload rotated values and restart a running container with them; a value change alone does not trigger an update. A delete detaches the custom domains the Worker was declared to serve (its `hostname` too), deletes the application, the Worker with its object's storage, then the database's config.
113
+
114
+ ## The database
115
+
116
+ Every host needs `SANOMA_DATABASE_URL` among its secrets: a create or an update without it, or with a URL that is not `postgres://` or `postgresql://`, is refused before anything changes, and the error never shows the URL. The container keeps the direct URL in its environment. The app on the Worker reaches the database through a [Hyperdrive](https://developers.cloudflare.com/hyperdrive/) config of the Worker's name, one per host, made or updated at every deploy from the URL (`{ scheme, host, port, database, user, password }`, port 5432 unless the URL names one, user and password decoded) with query caching off, `caching: { disabled: true }`: the app's reads must see its own writes. The upload binds it as `DATABASE`, whose `connectionString` the app connects with. Hyperdrive must reach the database from Cloudflare's network: a host on `localhost` or a private address is refused by Cloudflare at the config's write. The token needs Hyperdrive Edit.
95
117
 
96
118
  ## The image
97
119
 
@@ -106,7 +128,7 @@ The Worker's `SANOMA_IMAGE` binding holds the declared image and its upload the
106
128
  3. **Go live.** `infra.ts` declares the host and, after it, `export const wakeup = cloudflare.alarm({ host })`: apply mints `SANOMA_WAKEUP_TOKEN` when none is stored and gives it to the host. One apply makes the Worker, waits for it, then the alarm, which checks the Worker holds the token.
107
129
  4. **A sleeping run.** Start a workflow that sleeps past ten quiet minutes. Before the container stops the worker registers the sleep's end; at `at` the object's alarm starts the container and calls `/wake`, and the run continues.
108
130
 
109
- To stop scaling to zero, delete the `wakeup` line (from a `cloudflare.container`, its `SANOMA_WAKEUP_TOKEN` too), and apply: the alarm is deleted, and the next request still starts the container. With the token left among the host's secrets, the runtime registers with the Worker's wake route itself (`envWakeup`), as a Sanoma Cloud company's does.
131
+ To stop scaling to zero, delete the `wakeup` line (from a `cloudflare.container`, its `SANOMA_WAKEUP_TOKEN` too), and apply: the alarm is deleted, and the next request still starts the container. The token stays among the Worker's secrets (apply mints one when none is declared: the bundle and restart routes need it), so the runtime registers with the Worker's wake route itself (`envWakeup`), as a Sanoma Cloud company's does.
110
132
 
111
133
  ## Custom domains
112
134
 
@@ -114,12 +136,6 @@ Each hostname in `domains` is attached to the Worker as a [Workers custom domain
114
136
 
115
137
  `hostname`, the app's own domain, is attached, detached and read the same way, in the same zone lookup, and the Worker's `SANOMA_HOSTNAME` binding records it (as `SANOMA_DOMAINS` records the sites'), so one no longer declared is detached and one detached by hand is drift. With it attached, the host's `url` is `https://<hostname>` (a read of one not attached gives the workers.dev URL, so a failed attach or one detached by hand never points at a name that does not route). The wake path stays on workers.dev, which stays on: the Worker's `SANOMA_HOST_URL` binding, the host's `wakeUrl` (its `worker_url`, which apply gives the alarm as its `host`) and the health checks, so a wake never waits on the hostname's DNS or certificate, and declaring or dropping a hostname leaves the alarm as it is. A `hostname` that is also one of `domains`' values is refused, `invalid`, at a plan and a create, before any request: the app answers at every hostname that is not a site's. A renamed `hostname` is detached before the upload and the new one attached after it, as a site's domain is: in between, a short window, no hostname is attached and the app answers on workers.dev alone (the host's `url` reads as it), and a failure there leaves the bindings naming the old one, detached, or the new one, not yet attached, which the next apply attaches.
116
138
 
117
- ## Public sites on the Worker
118
-
119
- A public site without a login, on a declared domain, is served by the Worker itself, so a visitor never waits for a cold container (forty seconds to minutes). With `domains` and `SANOMA_WAKEUP_TOKEN` among the host's secrets, a create or an update, once the Worker answers at the new revision, asks the container for its sites bundle (`GET /__sanoma/sites-bundle` with `Authorization: Bearer <SANOMA_WAKEUP_TOKEN>`): the runtime builds it on that first ask (`buildWorker` in `@sanoma-ai/app/build`: the sites' pages, `callFn` and `getActor`, the company's workflows and the runtime bundled for `workerd`, the pages no call is made from prerendered), answering 202 until it is built (each answer marked `x-sanoma-sites-bundle`), asked again every poll for up to the start's ten minutes, and through the object's 503 while the container starts again; a 401 or a 404 without the mark is a runtime from before the route (its staff login's sign-in page, or its app's not-found), and any other answer without it (an error of Cloudflare's, a 5xx), or a body cut off, is asked again too, until the start's time is up, which fails the apply, retryably. Then the bundle's assets (the client build and the prerendered pages) go in through an [assets upload session](https://developers.cloudflare.com/workers/static-assets/direct-upload/) (`POST …/scripts/{name}/assets-upload-session { manifest }`, then each bucket it asks for to `POST …/workers/assets/upload?base64=true` with the session's jwt), and the Worker is uploaded again as it was, plus `worker/sites.js` as its entry, the bundle's modules under `sites/`, the `ASSETS` binding and `assets: { jwt, config }`: `run_worker_first: ["/*", "!/assets/*"]` (the client build straight from the assets), `html_handling` and `not_found_handling` `none`. Its revision, image and bindings are the deploy's, so the container keeps running.
120
-
121
- The router hands a request the bundle serves (a site's page on its domain, but `/__sanoma`, `/api`, `/auth`, `/webhooks`, `/setup`, `/wake` and `/healthz`) to it: a file of the client build at its path, the page prerendered for it when the request has no query, else the page rendered on the Worker over the company's database (`SANOMA_DATABASE_URL`, the Worker's binding), a run it starts queued for the container's worker, which `startNow` starts. Everything else goes to the object, as before. A container with no such site answers 404, and the Worker is uploaded again as the deploy uploaded it; one whose build failed answers 500 with why, which fails the apply (the Worker then serves the sites from the container until the next apply). The deploy's upload carries a `SANOMA_SITES_PENDING` binding, which either upload after it leaves out: a Worker whose sites upload failed keeps it, a read sees it, and the next plan is an update, which, when the Worker otherwise runs what is declared, makes the sites' upload alone (no upload of the Worker as deployed, no domain attached, no wait for its revision). A site with a login stays on the container: Better Auth needs its database adapter on the Worker first.
122
-
123
139
  ## DNS records
124
140
 
125
141
  `cloudflare.records({ zone, name, records })` is a set of DNS records in one of the account's zones, compared as a set, in no order. A sending domain's records are the case it is made for: `records` names a declared `resend.domain`, whose `dns_records` it then takes ([a field taken from another resource's state](https://github.com/Sanoma-AI/sanoma/blob/main/packages/workflows/README.md#resources)), or is a list written out.
@@ -152,9 +168,9 @@ export const mailDns = cloudflare.records({ zone: "sanoma.work", name: "resend",
152
168
 
153
169
  `@sanoma-ai/connector-cloudflare/driver` calls Cloudflare through its official SDK, [`cloudflare`](https://www.npmjs.com/package/cloudflare) (Stainless), with its own retries off (the runtime retries what is retryable), and calls the company's Worker with `fetch`. The `cloudflare` connector the package root exports carries it and its fake (`withSetup` from `@sanoma-ai/workflows`), so a config names the connector alone and workflows never import the driver (the lint refuses that).
154
170
 
155
- `./driver` (`cloudflareDriver`; `cloudflareDriver({ timeoutMs, startTimeoutMs, pollMs })`: 30 s a request, ten minutes for the Worker to answer at a new revision, two seconds between tries; each request of the image's copy may take ten minutes) and `./fake` (`fakeCloudflare`) are internal entries, for tests.
171
+ `./driver` (`cloudflareDriver`; `cloudflareDriver({ timeoutMs, startTimeoutMs, pollMs })`: 30 s a request, ten minutes for each of the deploy's two waits, the bundle and the restart, two seconds between tries; each request of the image's copy may take ten minutes) and `./fake` (`fakeCloudflare`) are internal entries, for tests.
156
172
 
157
- A read is the Worker's settings (its bindings: what it runs is its plain-text bindings, never a secret's value), the application of its name (whether it exists, its id) and the account's subdomain (its URL); a plan compares the declared image, source, ref, revision, port, domains and hostname (each left out too) and secret names with them, and plans an update for a Worker still marked `SANOMA_SITES_PENDING`. The requests are made one after another, in the order the fixtures hold.
173
+ A read is the Worker's settings (its bindings: what it runs is its plain-text bindings, never a secret's value), the application of its name (whether it exists, its id) and the account's subdomain (its URL); a plan compares the declared image, source, ref, revision, port, domains and hostname (each left out too) and secret names with them, and plans an update for a Worker that serves no app yet (no `DATABASE` binding: a create cut off before its upload). The requests are made one after another, in the order the fixtures hold.
158
174
 
159
175
  ### Environment
160
176
 
@@ -191,7 +207,7 @@ SANOMA_LIVE=1 CLOUDFLARE_API_TOKEN=... CLOUDFLARE_ACCOUNT_ID=... \
191
207
  node connectors/cloudflare/test/live.ts
192
208
  ```
193
209
 
194
- The kits have not run on a real account yet: the connector's first real run was Sanoma's own back office (`sanoma-ops`, 2026-10-29), deployed from the app's Resources page. What it showed: the second upload above, the Host the proxy forwards, and a cold start of about six to eight minutes on `standard-1` (the clone, `pnpm install` and `sanoma serve` of a company with a public site), which is what a visitor waits for after ten quiet minutes until the container is kept running or the sites move to the Worker.
210
+ The kits have not run on a real account yet: the connector's first real run was Sanoma's own back office (`sanoma-ops`, 2026-10-29), deployed from the app's Resources page. What it showed: the second upload above, the Host the proxy forwards, and a cold start of about six to eight minutes on `standard-1` (the clone, `pnpm install` and `sanoma serve` of a company with a public site, the app built at start). The runtime image since runs `sanoma worker` alone over a pnpm store baked into it, building nothing at start ([runtime image](../../packages/sanoma/README.md#hosting-it-yourself)): measured locally at half a CPU, 2026-11-04 (Cloudflare's own pull time not included), the checkout under a second, `pnpm install --frozen-lockfile --prefer-offline` 7–10 s for a lockfile the store matches and 14–30 s for one a `pnpm update --latest` behind, and the worker's `/healthz` 6–16 s after: 16–38 s, against `standard-1`'s half a vCPU.
195
211
 
196
212
  It needs:
197
213
 
@@ -213,7 +229,7 @@ The connector carries steps for [scenarios](https://github.com/Sanoma-AI/sanoma/
213
229
 
214
230
  ## Testing
215
231
 
216
- `@sanoma-ai/connector-cloudflare/fake` is an in-memory Cloudflare account, the fake the connector carries: each sandbox run makes one of its own. Its registry is in memory too: a copy records the image under its reference there and pulls nothing. Its custom domains are in `state.domains` (hostname, Worker and zone), each zone's DNS records in `state.dns`, by the zone's name (a test adds one by hand there; a batch is all or nothing, and refuses a record identical to one the zone holds (its type, content and priority) or one beside a CNAME, as Cloudflare does), and it holds every zone asked for unless `fakeCloudflare({ zones })` names the ones it holds. A copy pins the image by a made-up digest, and a preparation answers ready for an image pinned in its registry. Its Workers answer on ports of this machine, one per Worker name, and run the package's own object code over a `ctx` in this process: storage in memory, an alarm on a timer (again after a throw), `ctx.container.images` from the upload's `containers[].images`, and a container that runs what `start` returns for the image (the one its pinned copy was copied from) and revision it was started at (by default a stub that answers `/healthz` and `/wake`); `start` refuses an image the upload did not name or an instance type that is not Cloudflare's. An upload restarts the object over its new bindings and images: a new image starts the container again at the next request, as the object finds its label changed. Its assets upload session asks, in one bucket, for the hashes `state.assets` lacks, and an upload that redeems the completion jwt keeps each path's hash on the Worker (`state.scripts[name].assets`, beside its `main_module` and `modules`); its Workers still send every request to the object, as it runs no sites bundle.
232
+ `@sanoma-ai/connector-cloudflare/fake` is an in-memory Cloudflare account, the fake the connector carries: each sandbox run makes one of its own. Its registry is in memory too: a copy records the image under its reference there and pulls nothing. Its custom domains are in `state.domains` (hostname, Worker and zone), each zone's DNS records in `state.dns`, by the zone's name (a test adds one by hand there; a batch is all or nothing, and refuses a record identical to one the zone holds (its type, content and priority) or one beside a CNAME, as Cloudflare does), and it holds every zone asked for unless `fakeCloudflare({ zones })` names the ones it holds. A copy pins the image by a made-up digest, and a preparation answers ready for an image pinned in its registry. Its Workers answer on ports of this machine, one per Worker name, and run the package's own object code over a `ctx` in this process: storage in memory, an alarm on a timer (again after a throw), `ctx.container.images` from the upload's `containers[].images`, and a container that runs what `start` returns for the image (the one its pinned copy was copied from) and revision it was started at (by default a stub that answers `/healthz` and `/wake`); `start` refuses an image the upload did not name or an instance type that is not Cloudflare's. An upload restarts the object over its new bindings and images: a new image starts the container again at the next request, as the object finds its label changed. Its assets upload session asks, in one bucket, for the hashes `state.assets` lacks, and an upload that redeems the completion jwt keeps each path's hash on the Worker (`state.scripts[name].assets`, beside its `main_module`, `modules` and `compatibility_flags`). Its Hyperdrive configs are in `state.hyperdrives`, their passwords left out, and its `DATABASE` binding's `connectionString` is the direct URL. Its Workers run the package's own `serve` over the upload's modules, written to a folder and `app/index.js` imported from there; the bundle the container's worker answers is `fakeCloudflare({ bundle })`'s, by default `stubAppBundle`, a plain ES module that answers pages and `/healthz` and serves `/assets/`, since the real bundle is built for `workerd` (`nodejs_compat`, WebAssembly) and Node cannot import it.
217
233
 
218
234
  ```ts
219
235
  import { fakeCloudflare } from "@sanoma-ai/connector-cloudflare/fake";
@@ -229,7 +245,7 @@ fake.wakes(); // each /wake the containers answered
229
245
  await fake.close();
230
246
  ```
231
247
 
232
- `test/host.test.ts` and `test/wakeup.test.ts` run the Host and Wakeup kits over the fake this way, the company's runtime in this process; `test/worker.test.ts` runs the object's code over a stubbed `ctx`. Nothing here runs the Worker in `workerd`: [Miniflare](https://developers.cloudflare.com/workers/testing/miniflare/) would, which this package does not add.
248
+ `test/host.test.ts` and `test/wakeup.test.ts` run the Host and Wakeup kits over the fake this way, the company's runtime in this process; `test/worker.test.ts` runs the object's code and `serve` over a stubbed `ctx`. Nothing here runs the Worker in `workerd`: [Miniflare](https://developers.cloudflare.com/workers/testing/miniflare/) would, which this package does not add.
233
249
 
234
250
  ## Later
235
251
 
@@ -0,0 +1,66 @@
1
+ import type { AppBundle } from "@sanoma-ai/app";
2
+ import type { CloudflareApi, ContainerOptions } from "./ops.ts";
3
+ /** The Worker's entry module, which imports `cloudflare:workers`, `instance.js` and `app/index.js`. */
4
+ export declare const MAIN_MODULE = "index.js";
5
+ /** The Durable Object class the Worker exports, which the container application runs behind. */
6
+ export declare const OBJECT_CLASS = "SanomaInstance";
7
+ /** One module of the Worker: its name in the upload, its source, and its kind (an ES module unless it says). */
8
+ export interface WorkerModule {
9
+ name: string;
10
+ content: string | Uint8Array<ArrayBuffer>;
11
+ type?: AppBundle["modules"][number]["type"];
12
+ }
13
+ /**
14
+ * The package's own modules, read once: the entry and the object's code, and the placeholder app
15
+ * (`worker/no-app.js` as `app/index.js`) of a create's uploads before its first bundle.
16
+ */
17
+ export declare function workerModules(): Promise<{
18
+ entry: WorkerModule[];
19
+ noApp: WorkerModule;
20
+ }>;
21
+ /** The bundle's modules as the upload names them, under `app/`; a refusal unless its main module is the one the entry imports. */
22
+ export declare function appModules(script: string, bundle: AppBundle): WorkerModule[];
23
+ /**
24
+ * How the Worker serves its assets: the client build under `/assets/` straight from them, every
25
+ * other path through the Worker first (the app answers a prerendered page from them itself);
26
+ * never an HTML rewrite or a fallback page of the assets' own.
27
+ */
28
+ export declare const ASSETS_CONFIG: {
29
+ readonly html_handling: "none";
30
+ readonly not_found_handling: "none";
31
+ readonly run_worker_first: readonly ["/*", "!/assets/*"];
32
+ };
33
+ type Polling = Pick<ContainerOptions, "startTimeoutMs" | "pollMs">;
34
+ /**
35
+ * A deploy's wait, with its own budget: `ask` every `pollMs` until it gives a value; a refusal it
36
+ * throws ends the wait. Still none after `startTimeoutMs` is a retryable `DriverError`,
37
+ * "`doing` after N s", with what the last ask saw.
38
+ */
39
+ export declare function waitFor<T>(doing: string, { startTimeoutMs, pollMs }: Polling, ask: () => Promise<{
40
+ value: T;
41
+ } | {
42
+ last: string;
43
+ }>): Promise<T>;
44
+ /**
45
+ * The app bundle at `revision`, asked of the Worker at `url` with the instance token until it
46
+ * gives it: the object starts its container when it is stopped, and both it and the worker answer
47
+ * 202 meanwhile. A failed build or a revision the route refuses is a refusal. A deployment that
48
+ * cannot build it is `{ stale }`, why: a token refused (the deployed Worker or its container holds
49
+ * another), a container that ended, or, from an earlier deployment (`earlier`), a 404 the route
50
+ * did not mark (a runtime without it). Any other answer (no answer, an error of Cloudflare's, a
51
+ * body cut off, a workers.dev URL not routed yet) is asked again. Still none
52
+ * after `startTimeoutMs` is a retryable `DriverError` that says what the last ask saw. One ask
53
+ * may take the whole budget: a bundle is large.
54
+ */
55
+ export declare function appBundle(cf: CloudflareApi, { script, url, token, revision, earlier, }: {
56
+ script: string;
57
+ url: string;
58
+ token: string;
59
+ revision: string;
60
+ earlier: boolean;
61
+ }, polling: Polling): Promise<AppBundle | {
62
+ stale: string;
63
+ }>;
64
+ /** Puts the bundle's assets in through an upload session for `script`'s next upload: the completion jwt that upload redeems. */
65
+ export declare function uploadAssets(cf: CloudflareApi, script: string, assets: AppBundle["assets"]): Promise<string>;
66
+ export {};
package/dist/deploy.js ADDED
@@ -0,0 +1,143 @@
1
+ import { readFile } from "node:fs/promises";
2
+ import { setTimeout as delay } from "node:timers/promises";
3
+ import { DriverError, errorMessage } from "@sanoma-ai/workflows";
4
+ import { APP_BUNDLE_HEADER, APP_BUNDLE_PATH } from "@sanoma-ai/workflows/shared";
5
+ import mime from "mime";
6
+ import { refused } from "./errors.js";
7
+ // What a deploy uploads as the company's Worker script: the package's `worker/` (the entry and the
8
+ // object's code) and the app bundle under `app/`, which the worker at the new revision's checkout
9
+ // builds and the object passes on (`appBundle`), its assets through an upload session.
10
+ const WORKER = new URL("../worker/", import.meta.url);
11
+ /** The Worker's entry module, which imports `cloudflare:workers`, `instance.js` and `app/index.js`. */
12
+ export const MAIN_MODULE = "index.js";
13
+ /** The Durable Object class the Worker exports, which the container application runs behind. */
14
+ export const OBJECT_CLASS = "SanomaInstance";
15
+ /** Where the app bundle's modules go in the upload: the entry imports `app/index.js`. */
16
+ const APP = "app/";
17
+ let modules;
18
+ const read = (file, name = file) => readFile(new URL(file, WORKER), "utf8").then((content) => ({ name, content }));
19
+ /**
20
+ * The package's own modules, read once: the entry and the object's code, and the placeholder app
21
+ * (`worker/no-app.js` as `app/index.js`) of a create's uploads before its first bundle.
22
+ */
23
+ export function workerModules() {
24
+ modules ??= Promise.all([read(MAIN_MODULE), read("instance.js"), read("no-app.js", `${APP}index.js`)])
25
+ .then(([entry, instance, noApp]) => ({ entry: [entry, instance], noApp }))
26
+ .catch((err) => {
27
+ modules = undefined;
28
+ throw err;
29
+ });
30
+ return modules;
31
+ }
32
+ /** The bundle's modules as the upload names them, under `app/`; a refusal unless its main module is the one the entry imports. */
33
+ export function appModules(script, bundle) {
34
+ if (bundle.mainModule !== "index.js") {
35
+ throw refused(`${script}: the app bundle's main module is ${bundle.mainModule}; the Worker imports ${APP}index.js`);
36
+ }
37
+ return bundle.modules.map(({ name, type, content }) => ({
38
+ name: `${APP}${name}`,
39
+ type,
40
+ content: Buffer.from(content, "base64"),
41
+ }));
42
+ }
43
+ /**
44
+ * How the Worker serves its assets: the client build under `/assets/` straight from them, every
45
+ * other path through the Worker first (the app answers a prerendered page from them itself);
46
+ * never an HTML rewrite or a fallback page of the assets' own.
47
+ */
48
+ export const ASSETS_CONFIG = {
49
+ html_handling: "none",
50
+ not_found_handling: "none",
51
+ run_worker_first: ["/*", "!/assets/*"],
52
+ };
53
+ /**
54
+ * A deploy's wait, with its own budget: `ask` every `pollMs` until it gives a value; a refusal it
55
+ * throws ends the wait. Still none after `startTimeoutMs` is a retryable `DriverError`,
56
+ * "`doing` after N s", with what the last ask saw.
57
+ */
58
+ export async function waitFor(doing, { startTimeoutMs, pollMs }, ask) {
59
+ const until = Date.now() + startTimeoutMs;
60
+ for (;;) {
61
+ const seen = await ask();
62
+ if ("value" in seen)
63
+ return seen.value;
64
+ if (Date.now() >= until) {
65
+ throw new DriverError(`cloudflare: ${doing} after ${Math.round(startTimeoutMs / 1000)} s: ${seen.last}`, {
66
+ retryable: true,
67
+ });
68
+ }
69
+ await delay(pollMs);
70
+ }
71
+ }
72
+ /**
73
+ * The app bundle at `revision`, asked of the Worker at `url` with the instance token until it
74
+ * gives it: the object starts its container when it is stopped, and both it and the worker answer
75
+ * 202 meanwhile. A failed build or a revision the route refuses is a refusal. A deployment that
76
+ * cannot build it is `{ stale }`, why: a token refused (the deployed Worker or its container holds
77
+ * another), a container that ended, or, from an earlier deployment (`earlier`), a 404 the route
78
+ * did not mark (a runtime without it). Any other answer (no answer, an error of Cloudflare's, a
79
+ * body cut off, a workers.dev URL not routed yet) is asked again. Still none
80
+ * after `startTimeoutMs` is a retryable `DriverError` that says what the last ask saw. One ask
81
+ * may take the whole budget: a bundle is large.
82
+ */
83
+ export async function appBundle(cf, { script, url, token, revision, earlier, }, polling) {
84
+ return waitFor(`${script}: still building the app bundle at ${revision}`, polling, async () => {
85
+ try {
86
+ const res = await cf.send(`${url}${APP_BUNDLE_PATH}?revision=${encodeURIComponent(revision)}`, {
87
+ method: "GET",
88
+ headers: { authorization: `Bearer ${token}` },
89
+ signal: AbortSignal.timeout(polling.startTimeoutMs),
90
+ });
91
+ const route = res.headers.has(APP_BUNDLE_HEADER);
92
+ // Undefined when it is none (a body cut off where the JSON is).
93
+ const body = (await res.json().catch(() => undefined));
94
+ if (route && res.status === 200 && body !== undefined)
95
+ return { value: body };
96
+ const said = typeof body?.error === "string" ? body.error : `${APP_BUNDLE_PATH} answered ${res.status}`;
97
+ if (res.status === 401 || typeof body?.exit === "string" || (earlier && !route && res.status === 404)) {
98
+ return { value: { stale: said } };
99
+ }
100
+ // The worker's own refusal: the build's failure, a revision it refuses.
101
+ if (route && res.status !== 200 && res.status !== 202)
102
+ throw refused(`${script}: no app bundle at ${revision}: ${said}`);
103
+ return {
104
+ last: res.status === 202 ? (route ? "the worker is building it" : "its container is starting") : said,
105
+ };
106
+ }
107
+ catch (error) {
108
+ if (error instanceof DriverError)
109
+ throw error;
110
+ // No answer this time (a timeout, a body cut off): asked again.
111
+ return { last: errorMessage(error) };
112
+ }
113
+ });
114
+ }
115
+ /** Puts the bundle's assets in through an upload session for `script`'s next upload: the completion jwt that upload redeems. */
116
+ export async function uploadAssets(cf, script, assets) {
117
+ const byHash = new Map();
118
+ const manifest = {};
119
+ for (const { path, content, hash, size } of assets) {
120
+ manifest[path] = { hash, size };
121
+ byHash.set(hash, { hash, base64: content, contentType: mime.getType(path) ?? "application/octet-stream" });
122
+ }
123
+ const { jwt, buckets } = await cf.assetsSession(script, manifest);
124
+ // Every asset already in: the session's jwt is the completion one.
125
+ if (!buckets.length)
126
+ return jwt;
127
+ // Every bucket's files first, so a hash no asset has is refused before any request starts.
128
+ const files = buckets.map((bucket) => bucket.map((hash) => {
129
+ const file = byHash.get(hash);
130
+ if (!file)
131
+ throw refused(`${script}: the assets upload session asks for ${hash}, which no asset hashes to`);
132
+ return file;
133
+ }));
134
+ // One bucket after another, as Cloudflare limits how many it takes at once: the one that
135
+ // completes the set answers the completion jwt.
136
+ let completion;
137
+ for (const bucket of files)
138
+ completion = (await cf.uploadAssets(jwt, bucket)) ?? completion;
139
+ if (!completion)
140
+ throw refused(`${script}: every bucket of assets was uploaded, and Cloudflare gave no completion jwt`);
141
+ return completion;
142
+ }
143
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../src/deploy.ts"],"names":[],"mappings":"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"}
package/dist/driver.d.ts CHANGED
@@ -1,14 +1,19 @@
1
1
  export interface CloudflareDriverOptions {
2
2
  /** How long one request may take, in milliseconds. Default 30 000. */
3
3
  timeoutMs?: number;
4
- /** How long a create or update waits for the Worker to answer at its new revision. Default 10 minutes: a cold start clones and installs. */
4
+ /**
5
+ * How long a deploy waits for the app bundle at its revision, and then again for the container
6
+ * restarted at it. Default 10 minutes each: a cold start clones and installs, and a bundle is a
7
+ * build of the app.
8
+ */
5
9
  startTimeoutMs?: number;
6
10
  /** How long between two tries of the Worker while it starts. Default 2 000. */
7
11
  pollMs?: number;
8
12
  }
9
13
  /**
10
14
  * The real Cloudflare account at `CLOUDFLARE_ACCOUNT_ID`, with `CLOUDFLARE_API_TOKEN`: the
11
- * company's Worker and its container application (`cloudflare.container`), its object's alarm
15
+ * company's Worker, its container application and its database's Hyperdrive config
16
+ * (`cloudflare.host`, and `cloudflare.container`, its alias), its object's alarm
12
17
  * over the Worker's wake route with the company's `SANOMA_WAKEUP_TOKEN` (`cloudflare.alarm`), and
13
18
  * sets of DNS records in the account's zones (`cloudflare.records`). See the README.
14
19
  */
package/dist/driver.js CHANGED
@@ -9,7 +9,7 @@ import { CLOUDFLARE_REGISTRY, copyImage } from "./registry.js";
9
9
  const env = z.object({
10
10
  CLOUDFLARE_API_TOKEN: z
11
11
  .string()
12
- .describe("an API token with Workers Scripts Edit and Workers Containers Edit, and Zone Read and Zone → DNS → Edit on the zones of custom domains and DNS records"),
12
+ .describe("an API token with Workers Scripts Edit, Workers Containers Edit and Hyperdrive Edit, and Zone Read and Zone → DNS → Edit on the zones of custom domains and DNS records"),
13
13
  CLOUDFLARE_ACCOUNT_ID: z
14
14
  .string()
15
15
  .regex(/^[0-9a-f]{32}$/, "an account id is 32 hexadecimal digits")
@@ -50,7 +50,8 @@ const MODULE_TYPES = {
50
50
  };
51
51
  const isStatus = (error, status) => error instanceof DriverError && error.status === status;
52
52
  /** A request to a Worker, with a timeout: a redirect is no answer of the Worker's, and would carry the token elsewhere. */
53
- const sender = (timeoutMs) => (url, init) => fetch(url, { ...init, redirect: "manual", signal: AbortSignal.timeout(timeoutMs) });
53
+ /** `fetch` within `timeoutMs`, unless the caller gives its own signal (a large body's). */
54
+ const sender = (timeoutMs) => (url, init) => fetch(url, { ...init, redirect: "manual", signal: init.signal ?? AbortSignal.timeout(timeoutMs) });
54
55
  /**
55
56
  * The account at `CLOUDFLARE_ACCOUNT_ID` with `CLOUDFLARE_API_TOKEN`, read when an operation is
56
57
  * called. `subdomains` keeps each account's workers.dev subdomain once read, for the driver's life.
@@ -142,6 +143,23 @@ function accountApi(timeoutMs, subdomains) {
142
143
  async enableSubdomain(script) {
143
144
  await calling(`POST workers/scripts/${script}/subdomain`, (cf) => cf.workers.scripts.subdomain.create(script, { account_id, enabled: true }));
144
145
  },
146
+ hyperdrive: (name) => calling("GET hyperdrive/configs", async (cf) => {
147
+ // One page: an account holds 25 configs at most.
148
+ const page = await cf.hyperdrive.configs.list({ account_id, per_page: 50 });
149
+ const config = page.result.find((c) => c.name === name);
150
+ return config && { id: config.id };
151
+ }),
152
+ createHyperdrive: (name, origin) => calling("POST hyperdrive/configs", async (cf) => {
153
+ // Query caching off: the app reads what it just wrote.
154
+ const { id } = await cf.hyperdrive.configs.create({ account_id, name, origin, caching: { disabled: true } });
155
+ return { id };
156
+ }),
157
+ async updateHyperdrive(id, name, origin) {
158
+ await calling(`PUT hyperdrive/configs/${id}`, (cf) => cf.hyperdrive.configs.update(id, { account_id, name, origin, caching: { disabled: true } }));
159
+ },
160
+ async deleteHyperdrive(id) {
161
+ await found(`DELETE hyperdrive/configs/${id}`, (cf) => cf.hyperdrive.configs.delete(id, { account_id }));
162
+ },
145
163
  async deleteScript(script) {
146
164
  await found(`DELETE workers/scripts/${script}`, (cf) => cf.workers.scripts.delete(script, { account_id, force: true }));
147
165
  },
@@ -233,7 +251,8 @@ const zoneRecord = (record) => ({
233
251
  });
234
252
  /**
235
253
  * The real Cloudflare account at `CLOUDFLARE_ACCOUNT_ID`, with `CLOUDFLARE_API_TOKEN`: the
236
- * company's Worker and its container application (`cloudflare.container`), its object's alarm
254
+ * company's Worker, its container application and its database's Hyperdrive config
255
+ * (`cloudflare.host`, and `cloudflare.container`, its alias), its object's alarm
237
256
  * over the Worker's wake route with the company's `SANOMA_WAKEUP_TOKEN` (`cloudflare.alarm`), and
238
257
  * sets of DNS records in the account's zones (`cloudflare.records`). See the README.
239
258
  */
@@ -1 +1 @@
1
- {"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"driver.js","sourceRoot":"","sources":["../src/driver.ts"],"names":[],"mappings":"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"}