@sanoma-ai/connector-cloudflare 0.2.0 → 0.3.1
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 +43 -14
- package/dist/connector.d.ts +64 -3
- package/dist/connector.js +101 -2
- package/dist/connector.js.map +1 -1
- package/dist/driver.d.ts +3 -3
- package/dist/driver.js +41 -5
- package/dist/driver.js.map +1 -1
- package/dist/fake.d.ts +7 -2
- package/dist/fake.js +76 -5
- package/dist/fake.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/ops.d.ts +67 -1
- package/dist/ops.js +20 -10
- package/dist/ops.js.map +1 -1
- package/dist/records.d.ts +70 -0
- package/dist/records.js +325 -0
- package/dist/records.js.map +1 -0
- package/dist/resources.d.ts +25 -1
- package/dist/resources.js +4 -3
- package/dist/resources.js.map +1 -1
- package/features/records.feature +114 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @sanoma-ai/connector-cloudflare
|
|
2
2
|
|
|
3
|
-
[Cloudflare Containers](https://developers.cloudflare.com/containers/) as a host that stops when quiet, and its [Durable Object](https://developers.cloudflare.com/durable-objects/)'s [alarm](https://developers.cloudflare.com/durable-objects/api/alarms/) as the wakeup that starts it again, for [`@sanoma-ai/workflows`](https://www.npmjs.com/package/@sanoma-ai/workflows). Both are one Worker per company, `sanoma-<name>`, on the account's workers.dev subdomain.
|
|
3
|
+
[Cloudflare Containers](https://developers.cloudflare.com/containers/) as a host that stops when quiet, and its [Durable Object](https://developers.cloudflare.com/durable-objects/)'s [alarm](https://developers.cloudflare.com/durable-objects/api/alarms/) as the wakeup that starts it again, for [`@sanoma-ai/workflows`](https://www.npmjs.com/package/@sanoma-ai/workflows). Both are one Worker per company, `sanoma-<name>`, on the account's workers.dev subdomain. And a set of [DNS records](#dns-records) in one of the account's zones, such as the ones a sending domain asks for.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
npm install @sanoma-ai/connector-cloudflare
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
The three types are writable: `read` and `import` (effect `read`), and the change operations only the apply workflow may call, `plan` (effect `read`), `create`, `update` and `delete` (effect `write`). The container is a host ([Hosts](https://github.com/Sanoma-AI/sanoma/blob/main/packages/workflows/README.md#hosts)) and the alarm a wakeup, with one more operation, `register`, which the worker calls:
|
|
12
12
|
|
|
13
|
-
| Type | Operations | Import id
|
|
14
|
-
| ----------- | ----------------------------------------------------------------------------------------- |
|
|
15
|
-
| `container` | `cloudflare.container.read`, `.import`, `.plan`, `.create`, `.update`, `.delete` | its name
|
|
16
|
-
| `alarm` | `cloudflare.alarm.read`, `.import`, `.plan`, `.create`, `.update`, `.delete`, `.register` | its host's URL
|
|
13
|
+
| Type | Operations | Import id |
|
|
14
|
+
| ----------- | ----------------------------------------------------------------------------------------- | --------------- |
|
|
15
|
+
| `container` | `cloudflare.container.read`, `.import`, `.plan`, `.create`, `.update`, `.delete` | its name |
|
|
16
|
+
| `alarm` | `cloudflare.alarm.read`, `.import`, `.plan`, `.create`, `.update`, `.delete`, `.register` | its host's URL |
|
|
17
|
+
| `records` | `cloudflare.records.read`, `.import`, `.plan`, `.create`, `.update`, `.delete` | `<zone>/<name>` |
|
|
17
18
|
|
|
18
19
|
A data file declares them with the constructors in `@sanoma-ai/connector-cloudflare/resources`. Declaring the alarm is the whole switch for scaling to zero: without it, nothing starts a stopped container at a deadline, and a sleeping run waits for the next request.
|
|
19
20
|
|
|
@@ -85,6 +86,34 @@ To stop scaling to zero, delete the `wakeup` line and `SANOMA_WAKEUP_TOKEN` from
|
|
|
85
86
|
|
|
86
87
|
Each hostname in `domains` is attached to the Worker as a [Workers custom domain](https://developers.cloudflare.com/workers/configuration/routing/custom-domains/) by a create or an update: Cloudflare then makes its DNS record and certificate and routes it to the Worker. The zone is the hostname's last two labels (`www.acme.example` is in `acme.example`), looked up in the account once per apex when a domain is to be attached (`GET /zones?name=&account.id=`); a hostname whose zone the account does not hold, or the token cannot read, is refused, naming the hostname and the zone, before anything changes. An update lists the Worker's attached domains first (`GET …/workers/domains?service=`), and only a missing one's zone is looked up; after the upload, each missing one is attached (`PUT …/workers/domains { zone_id, hostname, service }`), then the ones declared before and no longer are detached (`DELETE …/workers/domains/{id}`). A domain attached by hand and never declared is left alone. A read lists the Worker's attached domains too and shows only the declared ones attached, so a domain whose attach failed, or one detached by hand, is drift that the next apply attaches again. A delete detaches every declared one before the Worker goes. A container without `domains` makes none of these requests, unless it served some before, which are then detached. A zone such as `acme.co.uk`, whose apex is three labels, is not found yet.
|
|
87
88
|
|
|
89
|
+
## DNS records
|
|
90
|
+
|
|
91
|
+
`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.
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
// resources/infra.ts
|
|
95
|
+
import { cloudflare } from "@sanoma-ai/connector-cloudflare/resources";
|
|
96
|
+
import { resend } from "@sanoma-ai/connector-resend/resources";
|
|
97
|
+
|
|
98
|
+
export const mail = resend.domain({ name: "sanoma.work" });
|
|
99
|
+
export const mailDns = cloudflare.records({ zone: "sanoma.work", name: "resend", records: mail });
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
| Field | What it is |
|
|
103
|
+
| ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
104
|
+
| `zone` | The zone's name, as the account holds it (`sanoma.work`); changing it replaces the set |
|
|
105
|
+
| `name` | The set's label (`resend`): lower case letters, digits, `-` and `_`. Its identity is `<zone>/<name>`; changing it replaces the set |
|
|
106
|
+
| `records` | The records, at least one: `{ type, name, content, priority?, ttl? }` each (`dnsRecord` from `@sanoma-ai/workflows`): TXT, MX, CNAME or CAA, the full name in lower case (the zone's name or one ending in it), a TXT record's text unquoted, a priority for MX, a ttl in seconds (1, automatic, when left out). One type, name and content declared twice with another ttl or priority, a name outside the zone, or a CNAME declared beside another record of its name, or two SPF policies (`v=spf1` TXT records) declared at one name, is refused, `invalid` |
|
|
107
|
+
| `zone_id`, `record_ids` | Cloudflare's: the zone's id, and each record's, in the order of `records` as a read gives them |
|
|
108
|
+
|
|
109
|
+
**Ownership.** Every record the set writes carries the comment `sanoma:<zone>/<name>` (`sanoma:sanoma.work/resend`), in that case exactly, which is how a read finds its records (`GET /zones/{id}/dns_records?comment.exact=`): the set is the records that carry it, and none is gone. A record's comment holds 100 characters on a Free zone, so a set whose mark is longer is refused, `invalid`. A record without that comment is never changed or deleted, whoever added it, with one exception: a record identical to a declared one in type, name and content, and an MX record's priority (one added by hand before the set was declared), is adopted, patched to carry the comment and the declared ttl; so is one a changed record would be patched to, whose marked one is then deleted. An adopted record is the set's from then on: it carries the mark, so it changes with the set and is **deleted with it**, and the comment it had is replaced by the mark (the set finds its records by the exact comment, so it keeps no other). A record in the way of a declared one is refused, `conflict`, naming it, before anything is written, whether the declared one is to be posted or a marked one patched to it: a CNAME at the name (or a declared CNAME beside any record), another SPF policy (a `v=spf1` TXT) at the name, an MX record to the same server at another priority, a record identical to a declared one that another set's comment marks, or one identical to it that is proxied (a set's records are DNS only, and adopting it would turn its proxy off). Every page of a lookup is read, so a busy name hides nothing.
|
|
110
|
+
|
|
111
|
+
**Writes.** A create or an update is one batch (`POST /zones/{id}/dns_records/batch`), which Cloudflare runs as one transaction, all or nothing: a post for each declared record no record holds, a patch for each marked record of a declared one's type and name whose content, priority or ttl changed, or whose proxy was turned on by hand (one of the same content first, so a ttl's change patches that record), and each one adopted, and a delete for each marked record no longer declared. Each record is written unproxied (`proxied: false`), with a ttl of 1 (automatic) unless declared; a CAA record's content, `0 issue "letsencrypt.org"` (its value quoted or not), is sent as its fields and compared with its value quoted, as Cloudflare shows it. A set already as declared writes nothing, an update retried after its batch was written too. A delete is one batch deleting the marked records, and only those. A read gives each marked record as `records` holds it: its name in lower case with no trailing dot, a TXT record's text with the quotes Cloudflare may show around it taken off (and a long one's quoted parts joined), the priority of an MX record, the ttl (1 when automatic); a plan and drift compare a declared ttl left out as 1.
|
|
112
|
+
|
|
113
|
+
**Records not known yet.** Where `records` is taken from a domain apply creates in the same run, `plan` is given `records: null`: a set not bound yet plans a create, one the zone holds an update, with `records` among `unknown`, and apply plans it again at its step with the domain's records. An `update` whose `desired` leaves `records` out (the domain is absent or unreadable, so drift and apply leave the field out) keeps what the zone holds and writes nothing. `records: null` at a create or an update is refused, `not_known`: apply fails such a step before it gets there.
|
|
114
|
+
|
|
115
|
+
**The token.** The API token needs **Zone → DNS → Edit** on the zone, beside Zone Read (the zone's lookup) and the Workers permissions the container needs. A token without it is refused, not retryable, `no_dns_permission` (status 403), naming the permission and the zone, whether Cloudflare refuses the read of the records or the batch. A zone the account does not hold, or the token cannot read, is refused at a create, an update or a delete, `no_zone` (Cloudflare lists neither, so a delete is not taken as done with the records perhaps left behind); a read there finds the set gone.
|
|
116
|
+
|
|
88
117
|
## Driver
|
|
89
118
|
|
|
90
119
|
`@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).
|
|
@@ -97,16 +126,16 @@ A read is the Worker's settings (its bindings: what it runs is its plain-text bi
|
|
|
97
126
|
|
|
98
127
|
It reads these on every call, never when the config loads:
|
|
99
128
|
|
|
100
|
-
| Variable | What it is
|
|
101
|
-
| ----------------------- |
|
|
102
|
-
| `CLOUDFLARE_API_TOKEN` | An API token with Workers Scripts Edit and Workers Containers Edit (Write, in the API's terms),
|
|
103
|
-
| `CLOUDFLARE_ACCOUNT_ID` | The account's id, 32 hexadecimal digits, on its dashboard's overview
|
|
129
|
+
| Variable | What it is |
|
|
130
|
+
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
131
|
+
| `CLOUDFLARE_API_TOKEN` | An API token with Workers Scripts Edit and Workers Containers Edit (Write, in the API's terms), Zone Read for `domains` (custom domains are attached and detached with Workers Scripts Edit) and DNS records, and Zone → DNS → Edit on the zones of [DNS records](#dns-records) |
|
|
132
|
+
| `CLOUDFLARE_ACCOUNT_ID` | The account's id, 32 hexadecimal digits, on its dashboard's overview |
|
|
104
133
|
|
|
105
134
|
When either is unset, a call fails, not retryable, naming it. The driver declares both in its `env` ([Credentials](https://www.npmjs.com/package/@sanoma-ai/workflows#credentials)): the worker starts without them, and the app's connector page shows their status and lets you set them. The alarm's operations need neither: they call the Worker with `SANOMA_WAKEUP_TOKEN` (`alarm.create` mints it when none is stored), and `alarm.create` stores `SANOMA_HOST_URL` once the host answered, for a register made off the host; it keeps the first one stored, which the Worker's own binding overrides on the host. A read without the token reads the alarm as unhealthy, so a plan to delete it still goes on.
|
|
106
135
|
|
|
107
136
|
### Errors and retries
|
|
108
137
|
|
|
109
|
-
A 429, a 5xx, a timeout or no reply is retryable, the image's copy's requests too; any other 4xx is not. `status` and `vendorCode` (Cloudflare's first error `code`) are kept. The driver's own refusals are not retryable: `exists` (a Worker of that name that is not Sanoma's, which is neither overwritten nor deleted), `plan_changed` (an update whose plan changed since it was approved, or is not an update: a new name is a delete and a create), `no_token` and `token` (a host without the company's `SANOMA_WAKEUP_TOKEN`, or with another one), `no_zone` (a domain whose zone the account does not hold), and a Worker that did not answer at its revision in time, which says what it answered.
|
|
138
|
+
A 429, a 5xx, a timeout or no reply is retryable, the image's copy's requests too; any other 4xx is not. `status` and `vendorCode` (Cloudflare's first error `code`) are kept. The driver's own refusals are not retryable: `exists` (a Worker of that name that is not Sanoma's, which is neither overwritten nor deleted), `plan_changed` (an update whose plan changed since it was approved, or is not an update: a new name is a delete and a create), `no_token` and `token` (a host without the company's `SANOMA_WAKEUP_TOKEN`, or with another one), `no_zone` (a domain or a record set whose zone the account does not hold), `conflict` (a record in the way of a declared one), `no_dns_permission` (a token without Zone → DNS → Edit), `not_known` (records given as `null`), `invalid` (a record the shared shape refuses, an MX one without a priority, one outside the zone, a CNAME or a second SPF policy beside another declared record, or a set's mark longer than 100 characters), and a Worker that did not answer at its revision in time, which says what it answered.
|
|
110
139
|
|
|
111
140
|
### Plan
|
|
112
141
|
|
|
@@ -114,7 +143,7 @@ Containers need the Workers Paid plan. An instance is billed while it runs, by i
|
|
|
114
143
|
|
|
115
144
|
### Testing the driver
|
|
116
145
|
|
|
117
|
-
`test/driver.test.ts` and the features replay Cloudflare's replies (`test/fixtures`) with [`@sanoma-ai/testing/replay`](https://github.com/Sanoma-AI/sanoma/blob/main/packages/testing/README.md#replaying-a-vendors-api): `pnpm vitest run connectors/cloudflare` needs no account. The fixtures are **written from Cloudflare's API reference, not recorded**: no account was at hand when the connector was written. A recording replaces them (`SANOMA_LIVE=1 SANOMA_RECORD=1` on the features test), losing the account's id and subdomain, ids and tokens; until then, a reply the reference gets wrong is wrong here too. The upload's `containers` field (its `name`, `class_name` and `images`) is Wrangler's and not in the reference or the SDK's types, and the object's `ctx.container.images` and `start({ image, instance })` are the policy's: the live run is what checks them. The image's copy is tested against two small registries in this process (`test/registry.test.ts`), and the driver's call for its credentials over replies written from the SDK's types and the OCI distribution spec; that Cloudflare's registry takes the copy as written is what the live run checks. The driver tests only replay.
|
|
146
|
+
`test/driver.test.ts`, `test/records.test.ts` and the features replay Cloudflare's replies (`test/fixtures`) with [`@sanoma-ai/testing/replay`](https://github.com/Sanoma-AI/sanoma/blob/main/packages/testing/README.md#replaying-a-vendors-api): `pnpm vitest run connectors/cloudflare` needs no account. The fixtures are **written from Cloudflare's API reference, not recorded**: no account was at hand when the connector was written. A recording replaces them (`SANOMA_LIVE=1 SANOMA_RECORD=1` on the features test), losing the account's id and subdomain, ids and tokens; until then, a reply the reference gets wrong is wrong here too. The upload's `containers` field (its `name`, `class_name` and `images`) is Wrangler's and not in the reference or the SDK's types, and the object's `ctx.container.images` and `start({ image, instance })` are the policy's: the live run is what checks them. The DNS records' fixtures (`records-*`) are written from the [DNS records reference](https://developers.cloudflare.com/api/resources/dns/subresources/records/) the same way, on `sanoma.work` with a set named `check` (`check-*.sanoma.work`), to be recorded on their first live run: Cloudflare's TXT content is quoted in them, which a read takes off. That Cloudflare shows a TXT record written unquoted with quotes is the reference's examples', not checked; a read compares it either way. The image's copy is tested against two small registries in this process (`test/registry.test.ts`), and the driver's call for its credentials over replies written from the SDK's types and the OCI distribution spec; that Cloudflare's registry takes the copy as written is what the live run checks. The driver tests only replay.
|
|
118
147
|
|
|
119
148
|
### Running it live
|
|
120
149
|
|
|
@@ -146,11 +175,11 @@ The connector carries steps for [scenarios](https://github.com/Sanoma-AI/sanoma/
|
|
|
146
175
|
| ------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
|
147
176
|
| Given | `a Cloudflare container for {string} at revision {string}` | Creates the company's container through `cloudflare.container.create`, its token generated, named `host` (`$host.state.url`) |
|
|
148
177
|
|
|
149
|
-
`features/cloudflare.feature` creates, reads, plans and deletes a container, and creates an alarm and registers with it, on the fake and on the replies in `test/fixtures` (named after each scenario): `test/features.test.ts` runs them with [`describeFeatures`](https://github.com/Sanoma-AI/sanoma/blob/main/packages/testing/README.md#a-connectors-own-features). The package ships `features/`.
|
|
178
|
+
`features/cloudflare.feature` creates, reads, plans and deletes a container, and creates an alarm and registers with it, and `features/records.feature` creates a record set, reads it, plans it unchanged, updates it with a changed record and one dropped, and deletes it, on the fake and on the replies in `test/fixtures` (named after each scenario): `test/features.test.ts` runs them with [`describeFeatures`](https://github.com/Sanoma-AI/sanoma/blob/main/packages/testing/README.md#a-connectors-own-features). The package ships `features/`.
|
|
150
179
|
|
|
151
180
|
## Testing
|
|
152
181
|
|
|
153
|
-
`@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), 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.
|
|
182
|
+
`@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.
|
|
154
183
|
|
|
155
184
|
```ts
|
|
156
185
|
import { fakeCloudflare } from "@sanoma-ai/connector-cloudflare/fake";
|
package/dist/connector.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Connector } from "@sanoma-ai/workflows";
|
|
1
|
+
import { type Connector, type DnsRecord } from "@sanoma-ai/workflows";
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
/**
|
|
4
4
|
* `cloudflare.container`: the company's Worker, `sanoma-<name>`, on the account's workers.dev
|
|
@@ -48,6 +48,66 @@ export declare const alarm: import("@sanoma-ai/workflows").Resource<z.ZodObject<
|
|
|
48
48
|
readonly by: readonly ["url"];
|
|
49
49
|
};
|
|
50
50
|
}, true>;
|
|
51
|
+
/** A CAA record's content, `0 issue "letsencrypt.org"`, as the fields Cloudflare takes; undefined when it is not one. */
|
|
52
|
+
export declare function caaData(content: string): {
|
|
53
|
+
flags: number;
|
|
54
|
+
tag: string;
|
|
55
|
+
value: string;
|
|
56
|
+
} | undefined;
|
|
57
|
+
/** A CAA record's fields as its content, as Cloudflare shows them: `caaData`'s reverse. */
|
|
58
|
+
export declare const caaContent: ({ flags, tag, value }: {
|
|
59
|
+
flags: number;
|
|
60
|
+
tag: string;
|
|
61
|
+
value: string;
|
|
62
|
+
}) => string;
|
|
63
|
+
/** A record as a zone or a declaration gives it, as far as a set compares it. */
|
|
64
|
+
interface AnyRecord {
|
|
65
|
+
type: string;
|
|
66
|
+
name: string;
|
|
67
|
+
content: string;
|
|
68
|
+
priority?: number | null | undefined;
|
|
69
|
+
ttl?: number | null | undefined;
|
|
70
|
+
}
|
|
71
|
+
/** A canonical record's key: two records of one key are the same record. */
|
|
72
|
+
export declare const keyOf: ({ type, name, content, priority, ttl }: DnsRecord) => string;
|
|
73
|
+
/**
|
|
74
|
+
* One record in the one form a set compares: its name in lower case with no trailing dot, a TXT
|
|
75
|
+
* record's text unquoted, a CAA record's value quoted, a priority for an MX record only, and a
|
|
76
|
+
* ttl, 1 (automatic) unless given.
|
|
77
|
+
*/
|
|
78
|
+
export declare const canonicalRecord: ({ type, name, content, priority, ttl }: AnyRecord) => DnsRecord;
|
|
79
|
+
/**
|
|
80
|
+
* `cloudflare.records({ zone, name, records })`: a set of DNS records in one of the account's
|
|
81
|
+
* zones, `<zone>/<name>`, compared as a set. Each record it writes carries the comment
|
|
82
|
+
* `sanoma:<zone>/<name>`, which is how a read finds them; a record without it is never changed or
|
|
83
|
+
* deleted, except one identical to a declared record in type, name, content (and an MX record's
|
|
84
|
+
* priority), which is adopted (its comment replaced by the mark), and is deleted with the set from then on.
|
|
85
|
+
* `records` may name a `resend.domain`, whose `dns_records` it then takes (`from`): a sending
|
|
86
|
+
* domain's records go to the zone that holds them.
|
|
87
|
+
*/
|
|
88
|
+
export declare const records: import("@sanoma-ai/workflows").Resource<z.ZodObject<{
|
|
89
|
+
zone: z.ZodString;
|
|
90
|
+
name: z.ZodString;
|
|
91
|
+
records: z.ZodArray<z.ZodObject<{
|
|
92
|
+
type: z.ZodEnum<{
|
|
93
|
+
CAA: "CAA";
|
|
94
|
+
CNAME: "CNAME";
|
|
95
|
+
MX: "MX";
|
|
96
|
+
TXT: "TXT";
|
|
97
|
+
}>;
|
|
98
|
+
name: z.ZodString;
|
|
99
|
+
content: z.ZodString;
|
|
100
|
+
priority: z.ZodOptional<z.ZodNumber>;
|
|
101
|
+
ttl: z.ZodOptional<z.ZodNumber>;
|
|
102
|
+
}, z.core.$strip>>;
|
|
103
|
+
zone_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
104
|
+
record_ids: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
105
|
+
}, z.core.$strip>, "cloudflare.records", {
|
|
106
|
+
readonly records: {
|
|
107
|
+
readonly type: readonly ["resend.domain"];
|
|
108
|
+
readonly from: "dns_records";
|
|
109
|
+
};
|
|
110
|
+
}, true>;
|
|
51
111
|
/** `alarm.register`, in the alarm type's own group, beside its resource operations. */
|
|
52
112
|
declare const registerSpec: {
|
|
53
113
|
register: {
|
|
@@ -60,9 +120,10 @@ declare const registerSpec: {
|
|
|
60
120
|
output: z.ZodObject<{}, z.core.$strip>;
|
|
61
121
|
};
|
|
62
122
|
};
|
|
63
|
-
/** The connector's specs:
|
|
123
|
+
/** The connector's specs: each type's operations, and `register` in the alarm's group. */
|
|
64
124
|
type CloudflareSpecs = {
|
|
65
125
|
container: (typeof container)["ops"];
|
|
126
|
+
records: (typeof records)["ops"];
|
|
66
127
|
alarm: (typeof alarm)["ops"] & typeof registerSpec;
|
|
67
128
|
};
|
|
68
129
|
/**
|
|
@@ -70,6 +131,6 @@ type CloudflareSpecs = {
|
|
|
70
131
|
* `delete`) and `alarm.register` in the alarm's group (Supabase's pattern).
|
|
71
132
|
*/
|
|
72
133
|
export declare const cloudflareOps: Connector<"cloudflare", CloudflareSpecs>;
|
|
73
|
-
/** The connector's type:
|
|
134
|
+
/** The connector's type: the three types, with `alarm.register`. */
|
|
74
135
|
export type CloudflareOps = typeof cloudflareOps;
|
|
75
136
|
export {};
|
package/dist/connector.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineConnector, defineResource, vendorInfo } from "@sanoma-ai/workflows";
|
|
1
|
+
import { compareDeclared, defineConnector, defineResource, dnsRecord, vendorInfo, } from "@sanoma-ai/workflows";
|
|
2
2
|
import { DOMAIN_NAME, SITE_KEY } from "@sanoma-ai/workflows/shared";
|
|
3
3
|
import { z } from "zod";
|
|
4
4
|
/*
|
|
@@ -120,7 +120,106 @@ export const alarm = defineResource({
|
|
|
120
120
|
outputs: (state) => ({ healthy: state.healthy === true }),
|
|
121
121
|
},
|
|
122
122
|
});
|
|
123
|
-
|
|
123
|
+
/** A set's label: lower case letters, digits, `-` and `_`. */
|
|
124
|
+
const LABEL = /^[a-z0-9](?:[a-z0-9_-]{0,61}[a-z0-9])?$/;
|
|
125
|
+
const recordsSchema = z.object({
|
|
126
|
+
zone: z
|
|
127
|
+
.string()
|
|
128
|
+
.regex(DOMAIN_NAME, "a zone's name, lower case, such as `example.com`")
|
|
129
|
+
.describe("The zone's name, as the account holds it: `example.com`"),
|
|
130
|
+
name: z
|
|
131
|
+
.string()
|
|
132
|
+
.regex(LABEL, "lower case letters, digits, `-` and `_`")
|
|
133
|
+
.describe("The set's label, such as `resend`: its identity is `<zone>/<name>`, and each record it writes carries the comment `sanoma:<zone>/<name>`"),
|
|
134
|
+
records: z
|
|
135
|
+
.array(dnsRecord)
|
|
136
|
+
// Empty, it would read back as gone, a create on every apply.
|
|
137
|
+
.min(1, "a set holds at least one record: leave it out rather than empty")
|
|
138
|
+
.describe("The records, compared as a set: a list, or a declared `resend.domain`, whose `dns_records` they are then"),
|
|
139
|
+
zone_id: z.string().nullish().describe("The zone's id, which Cloudflare sets"),
|
|
140
|
+
record_ids: z
|
|
141
|
+
.array(z.string())
|
|
142
|
+
.nullish()
|
|
143
|
+
.describe("Each record's id, which Cloudflare sets, in the order of `records` as a read gives them"),
|
|
144
|
+
});
|
|
145
|
+
/** A TXT record's text as a zone may show it, quoted (`"v=spf1 …"`) or split in quoted strings (`"…" "…"`), unquoted. */
|
|
146
|
+
function unquoted(content) {
|
|
147
|
+
const text = content.trim();
|
|
148
|
+
if (!/^"(?:[^"\\]|\\.)*"(?:\s+"(?:[^"\\]|\\.)*")*$/s.test(text))
|
|
149
|
+
return content;
|
|
150
|
+
return [...text.matchAll(/"((?:[^"\\]|\\.)*)"/gs)].map(([, part = ""]) => part.replace(/\\(.)/gs, "$1")).join("");
|
|
151
|
+
}
|
|
152
|
+
/** A CAA record's content, `0 issue "letsencrypt.org"`, as the fields Cloudflare takes; undefined when it is not one. */
|
|
153
|
+
export function caaData(content) {
|
|
154
|
+
const parts = /^(\d+)\s+(\S+)\s+(.+)$/s.exec(content.trim());
|
|
155
|
+
if (!parts)
|
|
156
|
+
return undefined;
|
|
157
|
+
const [, flags, tag, value] = parts;
|
|
158
|
+
// A tag in any case is the same tag (RFC 8659); Cloudflare shows it in lower case.
|
|
159
|
+
return { flags: Number(flags), tag: tag.toLowerCase(), value: value.replace(/^"(.*)"$/s, "$1") };
|
|
160
|
+
}
|
|
161
|
+
/** A CAA record's fields as its content, as Cloudflare shows them: `caaData`'s reverse. */
|
|
162
|
+
export const caaContent = ({ flags, tag, value }) => `${flags} ${tag} "${value}"`;
|
|
163
|
+
/** A record's content in its compared form: a TXT record's text unquoted, a CAA record's value quoted. */
|
|
164
|
+
function contentOf(type, content) {
|
|
165
|
+
if (type === "TXT")
|
|
166
|
+
return unquoted(content);
|
|
167
|
+
const caa = type === "CAA" ? caaData(content) : undefined;
|
|
168
|
+
return caa ? caaContent(caa) : content;
|
|
169
|
+
}
|
|
170
|
+
/** A canonical record's key: two records of one key are the same record. */
|
|
171
|
+
export const keyOf = ({ type, name, content, priority, ttl }) => JSON.stringify([type, name, content, priority, ttl]);
|
|
172
|
+
/**
|
|
173
|
+
* One record in the one form a set compares: its name in lower case with no trailing dot, a TXT
|
|
174
|
+
* record's text unquoted, a CAA record's value quoted, a priority for an MX record only, and a
|
|
175
|
+
* ttl, 1 (automatic) unless given.
|
|
176
|
+
*/
|
|
177
|
+
export const canonicalRecord = ({ type, name, content, priority, ttl }) => ({
|
|
178
|
+
type: type,
|
|
179
|
+
name: name.toLowerCase().replace(/\.$/, ""),
|
|
180
|
+
content: contentOf(type, content),
|
|
181
|
+
...(type === "MX" && typeof priority === "number" && { priority }),
|
|
182
|
+
ttl: ttl ?? 1,
|
|
183
|
+
});
|
|
184
|
+
const recordsFields = {
|
|
185
|
+
immutable: ["zone", "name"],
|
|
186
|
+
vendorOwned: ["zone_id", "record_ids"],
|
|
187
|
+
writeOnly: [],
|
|
188
|
+
unordered: ["records"],
|
|
189
|
+
references: { records: { type: ["resend.domain"], from: "dns_records" } },
|
|
190
|
+
};
|
|
191
|
+
/** A state or a declaration with its records in their compared form (`canonicalRecord`), each once, as a plan has them. */
|
|
192
|
+
const canonicalSet = (state) => {
|
|
193
|
+
if (!Array.isArray(state.records))
|
|
194
|
+
return state;
|
|
195
|
+
const records = state.records.map((record) => canonicalRecord(record));
|
|
196
|
+
return { ...state, records: [...new Map(records.map((r) => [keyOf(r), r])).values()] };
|
|
197
|
+
};
|
|
198
|
+
/**
|
|
199
|
+
* `cloudflare.records({ zone, name, records })`: a set of DNS records in one of the account's
|
|
200
|
+
* zones, `<zone>/<name>`, compared as a set. Each record it writes carries the comment
|
|
201
|
+
* `sanoma:<zone>/<name>`, which is how a read finds them; a record without it is never changed or
|
|
202
|
+
* deleted, except one identical to a declared record in type, name, content (and an MX record's
|
|
203
|
+
* priority), which is adopted (its comment replaced by the mark), and is deleted with the set from then on.
|
|
204
|
+
* `records` may name a `resend.domain`, whose `dns_records` it then takes (`from`): a sending
|
|
205
|
+
* domain's records go to the zone that holds them.
|
|
206
|
+
*/
|
|
207
|
+
export const records = defineResource({
|
|
208
|
+
vendor: "cloudflare",
|
|
209
|
+
type: "records",
|
|
210
|
+
title: "DNS records",
|
|
211
|
+
identity: "zone/name",
|
|
212
|
+
schema: recordsSchema,
|
|
213
|
+
fields: recordsFields,
|
|
214
|
+
find: ({ zone, name }) => `${zone}/${name}`,
|
|
215
|
+
bindingId: (state) => `${String(state.zone)}/${String(state.name)}`,
|
|
216
|
+
// Drift compares each record as `canonicalRecord` has it: a ttl left out is automatic, as read.
|
|
217
|
+
normalize: (state, desired) => compareDeclared(recordsFields, canonicalSet(state), canonicalSet(desired)),
|
|
218
|
+
writable: true,
|
|
219
|
+
// Records hold no data: a set deleted by hand is written again without asking.
|
|
220
|
+
stateless: true,
|
|
221
|
+
});
|
|
222
|
+
const types = defineConnector("cloudflare", { container, alarm, records }, vendorInfo(import.meta.url));
|
|
124
223
|
/** `alarm.register`, in the alarm type's own group, beside its resource operations. */
|
|
125
224
|
const registerSpec = {
|
|
126
225
|
register: {
|
package/dist/connector.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"connector.js","sourceRoot":"","sources":["../src/connector.ts"],"names":[],"mappings":"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"}
|
package/dist/driver.d.ts
CHANGED
|
@@ -8,8 +8,8 @@ export interface CloudflareDriverOptions {
|
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* The real Cloudflare account at `CLOUDFLARE_ACCOUNT_ID`, with `CLOUDFLARE_API_TOKEN`: the
|
|
11
|
-
* company's Worker and its container application (`cloudflare.container`),
|
|
12
|
-
* over the Worker's wake route with the company's `SANOMA_WAKEUP_TOKEN` (`cloudflare.alarm`)
|
|
13
|
-
* the README.
|
|
11
|
+
* company's Worker and its container application (`cloudflare.container`), its object's alarm
|
|
12
|
+
* over the Worker's wake route with the company's `SANOMA_WAKEUP_TOKEN` (`cloudflare.alarm`), and
|
|
13
|
+
* sets of DNS records in the account's zones (`cloudflare.records`). See the README.
|
|
14
14
|
*/
|
|
15
15
|
export declare function cloudflareDriver(options?: CloudflareDriverOptions): import("@sanoma-ai/workflows").Driver;
|
package/dist/driver.js
CHANGED
|
@@ -2,12 +2,13 @@ import { defineDriver, DriverError, retryableStatus } from "@sanoma-ai/workflows
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { cloudflareOps } from "./connector.js";
|
|
4
4
|
import { alarmOps, containerOps, refused } from "./ops.js";
|
|
5
|
+
import { recordsOps } from "./records.js";
|
|
5
6
|
import { CLOUDFLARE_REGISTRY, copyImage } from "./registry.js";
|
|
6
7
|
/** The environment variables the driver reads, on every call. */
|
|
7
8
|
const env = z.object({
|
|
8
9
|
CLOUDFLARE_API_TOKEN: z
|
|
9
10
|
.string()
|
|
10
|
-
.describe("an API token with Workers Scripts Edit and Workers Containers Edit, and Zone Read
|
|
11
|
+
.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"),
|
|
11
12
|
CLOUDFLARE_ACCOUNT_ID: z
|
|
12
13
|
.string()
|
|
13
14
|
.regex(/^[0-9a-f]{32}$/, "an account id is 32 hexadecimal digits")
|
|
@@ -167,14 +168,45 @@ function accountApi(timeoutMs, subdomains) {
|
|
|
167
168
|
async detachDomain(id) {
|
|
168
169
|
await found(`DELETE workers/domains/${id}`, (cf) => cf.workers.domains.delete(id, { account_id }));
|
|
169
170
|
},
|
|
171
|
+
dnsRecords: (zone_id, comment) => calling(`GET zones/${zone_id}/dns_records?comment.exact=${comment}`, (cf) => everyRecord(cf, { zone_id, comment: { exact: comment } })),
|
|
172
|
+
dnsRecordsAt: (zone_id, name) => calling(`GET zones/${zone_id}/dns_records?name.exact=${name}`, (cf) => everyRecord(cf, { zone_id, name: { exact: name } })),
|
|
173
|
+
writeDns: (zone_id, { posts, patches, deletes }) => calling(`POST zones/${zone_id}/dns_records/batch`, async (cf) => {
|
|
174
|
+
// The SDK's params are a union per record type; `RecordWrite` is the fields each shares.
|
|
175
|
+
const result = await cf.dns.records.batch({ zone_id, posts, patches, deletes });
|
|
176
|
+
return { patches: (result.patches ?? []).map(zoneRecord), posts: (result.posts ?? []).map(zoneRecord) };
|
|
177
|
+
}),
|
|
170
178
|
send: sender(timeoutMs),
|
|
171
179
|
};
|
|
172
180
|
}
|
|
181
|
+
/**
|
|
182
|
+
* Every record a list finds, page after page as its first page counts them (the SDK's own
|
|
183
|
+
* iteration asks for one page more, which answers empty).
|
|
184
|
+
*/
|
|
185
|
+
async function everyRecord(cf, query) {
|
|
186
|
+
const first = await cf.dns.records.list(query);
|
|
187
|
+
const found = [...first.result];
|
|
188
|
+
const pages = first.result_info.total_pages ?? 1;
|
|
189
|
+
for (let page = 2; page <= pages; page++) {
|
|
190
|
+
found.push(...(await cf.dns.records.list({ ...query, page })).result);
|
|
191
|
+
}
|
|
192
|
+
return found.map(zoneRecord);
|
|
193
|
+
}
|
|
194
|
+
/** A record of Cloudflare's reply, as the fields read here. */
|
|
195
|
+
const zoneRecord = (record) => ({
|
|
196
|
+
id: record.id,
|
|
197
|
+
type: record.type,
|
|
198
|
+
name: record.name,
|
|
199
|
+
content: record.content ?? "",
|
|
200
|
+
ttl: record.ttl,
|
|
201
|
+
...(record.priority !== undefined && { priority: record.priority }),
|
|
202
|
+
...(typeof record.comment === "string" && { comment: record.comment }),
|
|
203
|
+
...(record.proxied && { proxied: true }),
|
|
204
|
+
});
|
|
173
205
|
/**
|
|
174
206
|
* The real Cloudflare account at `CLOUDFLARE_ACCOUNT_ID`, with `CLOUDFLARE_API_TOKEN`: the
|
|
175
|
-
* company's Worker and its container application (`cloudflare.container`),
|
|
176
|
-
* over the Worker's wake route with the company's `SANOMA_WAKEUP_TOKEN` (`cloudflare.alarm`)
|
|
177
|
-
* the README.
|
|
207
|
+
* company's Worker and its container application (`cloudflare.container`), its object's alarm
|
|
208
|
+
* over the Worker's wake route with the company's `SANOMA_WAKEUP_TOKEN` (`cloudflare.alarm`), and
|
|
209
|
+
* sets of DNS records in the account's zones (`cloudflare.records`). See the README.
|
|
178
210
|
*/
|
|
179
211
|
export function cloudflareDriver(options = {}) {
|
|
180
212
|
const { timeoutMs = 30_000, startTimeoutMs = 10 * 60_000, pollMs = 2_000 } = options;
|
|
@@ -182,6 +214,10 @@ export function cloudflareDriver(options = {}) {
|
|
|
182
214
|
const api = () => accountApi(timeoutMs, subdomains);
|
|
183
215
|
// The alarm only calls the Worker, so it needs no account.
|
|
184
216
|
const worker = { send: sender(timeoutMs) };
|
|
185
|
-
return defineDriver(cloudflareOps, {
|
|
217
|
+
return defineDriver(cloudflareOps, {
|
|
218
|
+
container: containerOps(api, { startTimeoutMs, pollMs }),
|
|
219
|
+
alarm: alarmOps(() => worker),
|
|
220
|
+
records: recordsOps(api),
|
|
221
|
+
}, { env });
|
|
186
222
|
}
|
|
187
223
|
//# sourceMappingURL=driver.js.map
|
package/dist/driver.js.map
CHANGED
|
@@ -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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"}
|
package/dist/fake.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type FakeOptions } from "@sanoma-ai/workflows/fake";
|
|
2
|
-
import { type Application, type ReadBinding } from "./ops.ts";
|
|
2
|
+
import { type Application, type ReadBinding, type ZoneRecord } from "./ops.ts";
|
|
3
3
|
/** A `GET /wake` a container answered: when. */
|
|
4
4
|
export interface FakeWake {
|
|
5
5
|
at: Date;
|
|
@@ -45,12 +45,16 @@ export interface FakeCloudflareState extends Record<string, unknown> {
|
|
|
45
45
|
service: string;
|
|
46
46
|
zone_id: string;
|
|
47
47
|
}>;
|
|
48
|
+
/** Each zone's DNS records, by the zone's name: any set's, and any added by hand (a test's). */
|
|
49
|
+
dns: Record<string, ZoneRecord[]>;
|
|
48
50
|
}
|
|
49
51
|
/**
|
|
50
52
|
* An in-memory Cloudflare account for tests, as the API answers: Workers in `state.scripts`,
|
|
51
53
|
* container applications in `state.applications`, the images copied into its registry in
|
|
52
54
|
* `state.images` (nothing is pulled), their custom domains in `state.domains` (every zone held
|
|
53
|
-
* unless `zones` names them),
|
|
55
|
+
* unless `zones` names them), each zone's DNS records in `state.dns`, by the zone's name (a batch
|
|
56
|
+
* is all or nothing: an identical record or one beside a CNAME fails it whole), and the account's
|
|
57
|
+
* workers.dev URLs served in
|
|
54
58
|
* this process, one server on a port of this machine per Worker name (a name with no Worker
|
|
55
59
|
* answers workers.dev's 404). Each Worker runs the package's own object code
|
|
56
60
|
* (`worker/instance.js`) over a `ctx` in this process: its container runs `start`'s runtime
|
|
@@ -65,6 +69,7 @@ export interface FakeCloudflareState extends Record<string, unknown> {
|
|
|
65
69
|
*/
|
|
66
70
|
export declare function fakeCloudflare(options?: FakeCloudflareOptions): import("@sanoma-ai/workflows/fake").Fake<FakeCloudflareState, import("@sanoma-ai/workflows").OpIdOf<"cloudflare", {
|
|
67
71
|
container: (typeof import("./connector.ts").container)["ops"];
|
|
72
|
+
records: (typeof import("./connector.ts").records)["ops"];
|
|
68
73
|
alarm: (typeof import("./connector.ts").alarm)["ops"] & {
|
|
69
74
|
register: {
|
|
70
75
|
effect: "write";
|