domainkit 0.9.1 → 0.11.0

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.
@@ -170,6 +170,10 @@ export interface MethodDescriptor {
170
170
  }
171
171
  /** Field descriptors derived from `TokenAuth.fields`: optional keys are not required, `Redacted` values are secret. */
172
172
  export declare const tokenFields: (auth: TokenAuth) => ReadonlyArray<FieldDescriptor>;
173
+ /**
174
+ * Every method a provider offers, in the order a UI should present them: the interactive ones a
175
+ * customer clicks through first, then the token they have to go and fetch themselves.
176
+ */
173
177
  export declare const describeMethods: (definition: Definition) => ReadonlyArray<MethodDescriptor>;
174
178
  export interface CallbackInput {
175
179
  readonly code: string;
@@ -210,6 +214,12 @@ export interface IntegrationAuth {
210
214
  export interface Definition<Context = unknown> {
211
215
  readonly id: string;
212
216
  readonly name: string;
217
+ /**
218
+ * Hostname suffixes of the nameservers this provider operates, e.g. `ns.cloudflare.com`.
219
+ * `Connect.discover` names the provider as a domain's host when every authoritative nameserver
220
+ * ends in one of them.
221
+ */
222
+ readonly nameservers?: ReadonlyArray<string>;
213
223
  readonly auth: {
214
224
  readonly token?: TokenAuth;
215
225
  readonly oauth?: OAuthAuth;
@@ -234,6 +244,7 @@ export declare const encodeContext: <Context>(definition: Definition<Context>, v
234
244
  export type AuthMethod = "token" | "oauth" | "integration";
235
245
  /** Validates a definition: an id and at least one auth method. Throws `DomainKit.Error` otherwise. */
236
246
  export declare const make: <Context>(definition: Definition<Context>) => Definition<Context>;
247
+ /** The kinds alone, in the same order `describeMethods` puts them: interactive first, token last. */
237
248
  export declare const methods: (definition: Definition) => ReadonlyArray<AuthMethod>;
238
249
  /**
239
250
  * Pick the most specific zone among `targets` for `domain`: exactly one match resolves, several
@@ -74,6 +74,8 @@ export declare const Snapshot: Schema.Struct<{
74
74
  readonly method: Schema.NullOr<Schema.Literals<readonly ["token", "oauth", "integration"]>>;
75
75
  readonly status: Schema.Literals<readonly ["disconnected", "connected", "reconnect"]>;
76
76
  readonly lastReceiptId: Schema.NullOr<Schema.String>;
77
+ /** How many domains the connection serves, including this one; `0` without a connection. */
78
+ readonly connectionDomains: Schema.Number;
77
79
  readonly reusable: Schema.$Array<Schema.Struct<{
78
80
  readonly connectionId: Schema.String;
79
81
  readonly provider: Schema.String;
@@ -139,6 +141,8 @@ declare const Connected_base: Schema.Class<Connected, Schema.TaggedStruct<"Conne
139
141
  readonly method: Schema.NullOr<Schema.Literals<readonly ["token", "oauth", "integration"]>>;
140
142
  readonly status: Schema.Literals<readonly ["disconnected", "connected", "reconnect"]>;
141
143
  readonly lastReceiptId: Schema.NullOr<Schema.String>;
144
+ /** How many domains the connection serves, including this one; `0` without a connection. */
145
+ readonly connectionDomains: Schema.Number;
142
146
  readonly reusable: Schema.$Array<Schema.Struct<{
143
147
  readonly connectionId: Schema.String;
144
148
  readonly provider: Schema.String;
@@ -198,7 +202,11 @@ export declare class DiscoverySelectionRequired extends DiscoverySelectionRequir
198
202
  }
199
203
  declare const DiscoveryNotFound_base: Schema.Class<DiscoveryNotFound, Schema.TaggedStruct<"NotFound", {
200
204
  readonly nameservers: Schema.$Array<Schema.String>;
205
+ readonly host: Schema.NullOr<Schema.Struct<{
206
+ readonly provider: Schema.String;
207
+ }>>;
201
208
  }>, {}>;
209
+ /** `host` names the registered provider whose nameservers serve the domain, by definition id. */
202
210
  export declare class DiscoveryNotFound extends DiscoveryNotFound_base {
203
211
  }
204
212
  export declare const Discovery: Schema.Union<readonly [typeof DiscoveryResolved, typeof DiscoverySelectionRequired, typeof DiscoveryNotFound]>;
@@ -3971,6 +3979,8 @@ export declare const group: HttpApiGroup.HttpApiGroup<"domainkit", HttpApiEndpoi
3971
3979
  readonly method: Schema.NullOr<Schema.Literals<readonly ["token", "oauth", "integration"]>>;
3972
3980
  readonly status: Schema.Literals<readonly ["disconnected", "connected", "reconnect"]>;
3973
3981
  readonly lastReceiptId: Schema.NullOr<Schema.String>;
3982
+ /** How many domains the connection serves, including this one; `0` without a connection. */
3983
+ readonly connectionDomains: Schema.Number;
3974
3984
  readonly reusable: Schema.$Array<Schema.Struct<{
3975
3985
  readonly connectionId: Schema.String;
3976
3986
  readonly provider: Schema.String;
@@ -16,6 +16,8 @@ export declare const storage: Layer.Layer<Storage.Service>;
16
16
  export declare const principal: Principal.Interface;
17
17
  export interface FakeProviderOptions {
18
18
  readonly id?: string;
19
+ /** The name a customer reads. Default `Fake <id>`; a fixture that ships screenshots sets it. */
20
+ readonly name?: string;
19
21
  /** Zones the fake credential can reach. Default: `example.com`. */
20
22
  readonly zones?: ReadonlyArray<string>;
21
23
  /** Pre-existing records, to produce `Noop` and `Conflict` operations. */
@@ -29,6 +31,8 @@ export interface FakeProviderOptions {
29
31
  readonly failWrite?: (index: number) => boolean;
30
32
  /** Nameservers per zone; default `ns1.<zone>`, `ns2.<zone>`. `resolver()` answers NS queries from them. */
31
33
  readonly nameservers?: Readonly<Record<string, ReadonlyArray<string>>>;
34
+ /** Suffixes the fake declares as `Definition.nameservers`, so `Connect.discover` can name it as a host. */
35
+ readonly nameserverSuffixes?: ReadonlyArray<string>;
32
36
  }
33
37
  export interface FakeProvider extends Provider.Definition<FakeContext> {
34
38
  readonly records: (zone: string) => ReadonlyArray<DnsRecord.Observed>;
@@ -47,18 +51,23 @@ type FakeContext = typeof Context.Type;
47
51
  export declare const provider: (options?: FakeProviderOptions) => FakeProvider;
48
52
  /** Records every fake provider currently holds for `name`, across all fake zones. */
49
53
  export declare const fakeRecords: (name: string) => ReadonlyArray<DnsRecord.Observed>;
54
+ export interface FakeResolverOptions {
55
+ /** The name every answer carries. A UI reads it as the observer. Default `fake`. */
56
+ readonly id?: string;
57
+ }
50
58
  /**
51
- * A resolver answering from the fake providers' zones, or from an explicit table. Every answer
52
- * is attributed to the resolver named `fake`.
59
+ * A resolver answering from the fake providers' zones, or from an explicit table. Every answer is
60
+ * attributed to `options.id`, which a fixture that ships screenshots names after a real resolver.
53
61
  */
54
62
  export declare const resolver: (answers?: ReadonlyArray<{
55
63
  readonly name: string;
56
64
  readonly records: ReadonlyArray<DnsRecord.Observed>;
57
- }>) => Layer.Layer<Resolver.Service>;
65
+ }>, options?: FakeResolverOptions) => Layer.Layer<Resolver.Service>;
58
66
  export interface TransportOptions {
59
67
  /** Which groups the fake server exposes, so a UI can be tested against a partial host. */
60
68
  readonly capabilities?: ReadonlyArray<Transport.Capability>;
61
69
  readonly provider?: FakeProviderOptions;
70
+ readonly resolver?: FakeResolverOptions;
62
71
  }
63
72
  export interface RecordedCall {
64
73
  /** `connection.inspect`, `provisioning.approve`, ... */
@@ -79,6 +88,6 @@ export type { Case as StorageCase } from "./internal/conformance/storage.ts";
79
88
  export declare const conformance: {
80
89
  /** Runs every Storage invariant (tenant isolation, leases, exactly-once continuations, revocation recovery). */
81
90
  storage: typeof storageCases;
82
- /** Runs create/readback/cleanup, exact-noop, conflict, stale-plan, partial-apply against a real provider definition. */
91
+ /** Runs create/readback/cleanup, exact-noop, conflict, stale-plan, partial-apply, and rejected-token against a real provider definition. */
83
92
  provider: typeof providerCases;
84
93
  };
@@ -1,6 +1,6 @@
1
1
  /** Vercel: personal tokens and marketplace integrations. */
2
2
  import { type Config, Redacted, Schema } from "effect";
3
- import type { Fetch } from "./internal/http.ts";
3
+ import { type Fetch } from "./internal/http.ts";
4
4
  import * as Provider from "./Provider.ts";
5
5
  /** `teamId` is `null` for a personal account; targets carry the team that owns the zone. */
6
6
  export declare const TeamContext: Schema.Struct<{
@@ -12,8 +12,10 @@ export interface Options {
12
12
  type Fx<A> = Effect.Effect<A, Errors.DomainKitError>;
13
13
  /** Every zone the credential can see, across accounts; internal zones cannot host records. */
14
14
  export declare const listZones: (options: Options, accountId?: string) => Fx<ReadonlyArray<Protocol.Zone>>;
15
- /** Token expiry from the verify endpoint; `null` when the token never expires or verification is unavailable. */
16
- /** Token status and expiry from a verify endpoint; an inactive token is `Unauthenticated`. */
15
+ /**
16
+ * Token status and expiry from a verify endpoint; `null` expiry means the token never expires. An
17
+ * inactive token, or a 403 from the verify endpoint, is `Unauthenticated`.
18
+ */
17
19
  export declare const verifyToken: (options: Options, path: string) => Fx<DateTime.Utc | null>;
18
20
  export declare const tokenExpiry: (options: Options, accountId: string | null) => Fx<{
19
21
  readonly expiresAt: DateTime.Utc | null;
@@ -1,12 +1,19 @@
1
1
  import { Effect } from "effect";
2
2
  import * as Errors from "../error.ts";
3
3
  import * as Provider from "../../Provider.ts";
4
- export declare const cases: readonly ["create-readback-cleanup", "exact-noop", "conflict", "stale-plan", "partial-apply-cleanup"];
4
+ export declare const cases: readonly ["create-readback-cleanup", "exact-noop", "conflict", "stale-plan", "partial-apply-cleanup", "rejected-token"];
5
5
  export type Case = (typeof cases)[number];
6
6
  /**
7
- * Runs create/readback/cleanup, exact-noop, conflict, stale-plan, and partial-apply against a
8
- * real provider definition, through the same Provision and Cleanup services hosts use.
7
+ * Runs create/readback/cleanup, exact-noop, conflict, stale-plan, partial-apply, and
8
+ * rejected-token against a real provider definition, through the same Provision and Cleanup
9
+ * services hosts use.
9
10
  */
10
11
  export declare const provider: (definition: Provider.Definition, credential: Provider.Credential, zone: string, options?: {
11
12
  readonly prefix?: string;
13
+ /**
14
+ * Token values the provider rejects, for the `rejected-token` case. Default: every required
15
+ * field set to an empty secret, which needs a token method whose required fields are all
16
+ * secrets.
17
+ */
18
+ readonly rejectedToken?: Provider.TokenValues;
12
19
  }) => Effect.Effect<void, Errors.DomainKitError>;
@@ -23,5 +23,10 @@ export declare const headersFrom: (source: HeadersInit | (() => HeadersInit | Pr
23
23
  * conflict code -> ProviderConflict, 429/5xx -> ProviderUnavailable, else ProviderRejected.
24
24
  */
25
25
  export declare const classify: (provider: string, status: number, headers: Headers, message: string, code?: string) => Reason.Model;
26
+ /**
27
+ * During token verification a `Forbidden` answer means the provider did not accept the token, so
28
+ * it reads as `Unauthenticated` with the provider's own message.
29
+ */
30
+ export declare const rejectedToken: <A, R>(verification: Effect.Effect<A, Errors.DomainKitError, R>) => Effect.Effect<A, Errors.DomainKitError, R>;
26
31
  export declare const rejected: (provider: string, message: string, code?: string) => Errors.DomainKitError;
27
32
  export declare const bearer: (token: string, init?: RequestInit) => RequestInit;
@@ -41,6 +41,8 @@ export declare const exchangeCode: (input: {
41
41
  readonly callbackUrl: string;
42
42
  readonly codeVerifier: string;
43
43
  readonly fetch?: Fetch;
44
+ /** Permit an `http:` endpoint that is not loopback. Development only; see `insecureAllowed`. */
45
+ readonly allowPlaintext?: boolean;
44
46
  }) => Effect.Effect<Tokens, Errors.DomainKitError>;
45
47
  export declare const refresh: (input: {
46
48
  readonly provider: string;
@@ -48,6 +50,7 @@ export declare const refresh: (input: {
48
50
  readonly client: Client;
49
51
  readonly refreshToken: string;
50
52
  readonly fetch?: Fetch;
53
+ readonly allowPlaintext?: boolean;
51
54
  }) => Effect.Effect<Tokens, Errors.DomainKitError>;
52
55
  export declare const revoke: (input: {
53
56
  readonly provider: string;
@@ -55,4 +58,5 @@ export declare const revoke: (input: {
55
58
  readonly client: Client;
56
59
  readonly token: string;
57
60
  readonly fetch?: Fetch;
61
+ readonly allowPlaintext?: boolean;
58
62
  }) => Effect.Effect<void, Errors.DomainKitError>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domainkit",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
4
4
  "description": "Build reviewable DNS plans for custom domains in TypeScript",
5
5
  "keywords": [
6
6
  "custom-domains",