domainkit 0.16.0 → 0.18.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.
- package/README.md +2 -2
- package/dist/Custody.mjs +1 -1
- package/dist/Custody.mjs.map +1 -1
- package/dist/DomainName.mjs +1 -1
- package/dist/DomainName.mjs.map +1 -1
- package/dist/Vercel.mjs +2 -1
- package/dist/Vercel.mjs.map +1 -1
- package/dist/package.mjs +1 -1
- package/dist/types/Vercel.d.ts +7 -0
- package/package.json +6 -5
package/README.md
CHANGED
|
@@ -88,8 +88,8 @@ export const DomainKitLive = DomainKit.layer({
|
|
|
88
88
|
providers: [
|
|
89
89
|
Cloudflare.provider({
|
|
90
90
|
oauth: {
|
|
91
|
-
clientId: Config.
|
|
92
|
-
clientSecret: Config.
|
|
91
|
+
clientId: Config.String("CF_CLIENT_ID"),
|
|
92
|
+
clientSecret: Config.Redacted("CF_CLIENT_SECRET"),
|
|
93
93
|
},
|
|
94
94
|
}),
|
|
95
95
|
Vercel.provider(), // tokens only
|
package/dist/Custody.mjs
CHANGED
|
@@ -37,7 +37,7 @@ const make = (options) => Effect.gen(function* () {
|
|
|
37
37
|
const layer = (options) => Layer.effect(Service)(make(options));
|
|
38
38
|
/** Same options, each field a `Config`. Defaults to `DOMAINKIT_CUSTODY_KEY`. */
|
|
39
39
|
const layerConfig = (options = {}) => Layer.effect(Service)(Effect.gen(function* () {
|
|
40
|
-
const key = yield* (options.key ?? Config.
|
|
40
|
+
const key = yield* (options.key ?? Config.Redacted("DOMAINKIT_CUSTODY_KEY")).pipe(Effect.mapError((cause) => new DomainKitError({ reason: new InvalidInput({
|
|
41
41
|
message: cause.message,
|
|
42
42
|
field: "key"
|
|
43
43
|
}) })));
|
package/dist/Custody.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Custody.mjs","names":["Aes.decodeKey","Errors.fail","Reason.InvalidInput","Aes.importKey","Aes.seal","Aes.open","Errors.DomainKitError","Aes.generateKey","Errors.isDomainKitError","Reason.CryptoFailed"],"sources":["../src/Custody.ts"],"sourcesContent":["/**\n * Seals provider credentials before Storage writes them. The default is AES-256-GCM through\n * WebCrypto from one configured key; hosts with a KMS provide their own. There is no plaintext\n * mode.\n *\n * Envelope format: `v1.<iv>.<ciphertext>` with base64url segments and a 12-byte IV. Rotating\n * the key requires re-sealing stored credentials; `open` fails with `CryptoFailed` on a mismatch.\n */\nimport { Config, Context, Effect, Layer, Redacted } from \"effect\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\nimport * as Aes from \"./internal/aes.ts\";\n\nexport interface Interface {\n readonly seal: (\n plaintext: Redacted.Redacted<string>,\n ) => Effect.Effect<string, Errors.DomainKitError>;\n readonly open: (\n ciphertext: string,\n ) => Effect.Effect<Redacted.Redacted<string>, Errors.DomainKitError>;\n}\n\nexport class Service extends Context.Service<Service, Interface>()(\"@domainkit/Custody\") {}\n\nexport interface Options {\n /** 32 bytes, base64 or hex. Rotating it requires re-sealing stored credentials. */\n readonly key: Redacted.Redacted<string>;\n}\n\nexport const make = (options: Options): Effect.Effect<Interface, Errors.DomainKitError> =>\n Effect.gen(function* () {\n const raw = Aes.decodeKey(Redacted.value(options.key));\n if (raw === null) {\n return yield* Errors.fail(\n new Reason.InvalidInput({\n message: \"Custody key must be 32 bytes encoded as base64 or hex\",\n field: \"key\",\n }),\n );\n }\n const key = yield* Aes.importKey(raw);\n return {\n seal: (plaintext) => Aes.seal(key, plaintext),\n open: (ciphertext) => Aes.open(key, ciphertext),\n };\n });\n\nexport const layer = (options: Options): Layer.Layer<Service, Errors.DomainKitError> =>\n Layer.effect(Service)(make(options));\n\n/** Same options, each field a `Config`. Defaults to `DOMAINKIT_CUSTODY_KEY`. */\nexport const layerConfig = (\n options: { readonly key?: Config.Config<Redacted.Redacted<string>> } = {},\n): Layer.Layer<Service, Errors.DomainKitError> =>\n Layer.effect(Service)(\n Effect.gen(function* () {\n const key = yield* (options.key ?? Config.
|
|
1
|
+
{"version":3,"file":"Custody.mjs","names":["Aes.decodeKey","Errors.fail","Reason.InvalidInput","Aes.importKey","Aes.seal","Aes.open","Errors.DomainKitError","Aes.generateKey","Errors.isDomainKitError","Reason.CryptoFailed"],"sources":["../src/Custody.ts"],"sourcesContent":["/**\n * Seals provider credentials before Storage writes them. The default is AES-256-GCM through\n * WebCrypto from one configured key; hosts with a KMS provide their own. There is no plaintext\n * mode.\n *\n * Envelope format: `v1.<iv>.<ciphertext>` with base64url segments and a 12-byte IV. Rotating\n * the key requires re-sealing stored credentials; `open` fails with `CryptoFailed` on a mismatch.\n */\nimport { Config, Context, Effect, Layer, Redacted } from \"effect\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\nimport * as Aes from \"./internal/aes.ts\";\n\nexport interface Interface {\n readonly seal: (\n plaintext: Redacted.Redacted<string>,\n ) => Effect.Effect<string, Errors.DomainKitError>;\n readonly open: (\n ciphertext: string,\n ) => Effect.Effect<Redacted.Redacted<string>, Errors.DomainKitError>;\n}\n\nexport class Service extends Context.Service<Service, Interface>()(\"@domainkit/Custody\") {}\n\nexport interface Options {\n /** 32 bytes, base64 or hex. Rotating it requires re-sealing stored credentials. */\n readonly key: Redacted.Redacted<string>;\n}\n\nexport const make = (options: Options): Effect.Effect<Interface, Errors.DomainKitError> =>\n Effect.gen(function* () {\n const raw = Aes.decodeKey(Redacted.value(options.key));\n if (raw === null) {\n return yield* Errors.fail(\n new Reason.InvalidInput({\n message: \"Custody key must be 32 bytes encoded as base64 or hex\",\n field: \"key\",\n }),\n );\n }\n const key = yield* Aes.importKey(raw);\n return {\n seal: (plaintext) => Aes.seal(key, plaintext),\n open: (ciphertext) => Aes.open(key, ciphertext),\n };\n });\n\nexport const layer = (options: Options): Layer.Layer<Service, Errors.DomainKitError> =>\n Layer.effect(Service)(make(options));\n\n/** Same options, each field a `Config`. Defaults to `DOMAINKIT_CUSTODY_KEY`. */\nexport const layerConfig = (\n options: { readonly key?: Config.Config<Redacted.Redacted<string>> } = {},\n): Layer.Layer<Service, Errors.DomainKitError> =>\n Layer.effect(Service)(\n Effect.gen(function* () {\n const key = yield* (options.key ?? Config.Redacted(\"DOMAINKIT_CUSTODY_KEY\")).pipe(\n Effect.mapError(\n (cause) =>\n new Errors.DomainKitError({\n reason: new Reason.InvalidInput({ message: cause.message, field: \"key\" }),\n }),\n ),\n );\n return yield* make({ key });\n }),\n );\n\n/** A fresh random key in the accepted encoding; for tests, playgrounds, and first-time setup. */\nexport const generateKey = Aes.generateKey;\n\nexport interface AsyncInterface {\n readonly seal: (plaintext: string) => Promise<string>;\n readonly open: (ciphertext: string) => Promise<string>;\n}\n\nconst cryptoFailed = (operation: \"seal\" | \"open\") => (cause: unknown) =>\n Errors.isDomainKitError(cause)\n ? cause\n : new Errors.DomainKitError({ reason: new Reason.CryptoFailed({ operation }) });\n\n/** Wrap a Promise-shaped KMS client; rejections become `CryptoFailed`. */\nexport const fromAsync = (service: AsyncInterface): Interface => ({\n seal: (plaintext) =>\n Effect.tryPromise({\n try: () => service.seal(Redacted.value(plaintext)),\n catch: cryptoFailed(\"seal\"),\n }),\n open: (ciphertext) =>\n Effect.tryPromise({ try: () => service.open(ciphertext), catch: cryptoFailed(\"open\") }).pipe(\n Effect.map((value) => Redacted.make(value)),\n ),\n});\n\nexport const layerFromAsync = (service: AsyncInterface): Layer.Layer<Service> =>\n Layer.succeed(Service)(fromAsync(service));\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAuBA,IAAa,UAAb,cAA6B,QAAQ,QAA4B,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC;AAO1F,MAAa,QAAQ,YACnB,OAAO,IAAI,aAAa;CACtB,MAAM,MAAMA,UAAc,SAAS,MAAM,QAAQ,GAAG,CAAC;CACrD,IAAI,QAAQ,MACV,OAAO,OAAOC,KACZ,IAAIC,aAAoB;EACtB,SAAS;EACT,OAAO;CACT,CAAC,CACH;CAEF,MAAM,MAAM,OAAOC,UAAc,GAAG;CACpC,OAAO;EACL,OAAO,cAAcC,KAAS,KAAK,SAAS;EAC5C,OAAO,eAAeC,KAAS,KAAK,UAAU;CAChD;AACF,CAAC;AAEH,MAAa,SAAS,YACpB,MAAM,OAAO,OAAO,CAAC,CAAC,KAAK,OAAO,CAAC;;AAGrC,MAAa,eACX,UAAuE,CAAC,MAExE,MAAM,OAAO,OAAO,CAAC,CACnB,OAAO,IAAI,aAAa;CACtB,MAAM,MAAM,QAAQ,QAAQ,OAAO,OAAO,SAAS,uBAAuB,EAAA,CAAG,KAC3E,OAAO,UACJ,UACC,IAAIC,eAAsB,EACxB,QAAQ,IAAIJ,aAAoB;EAAE,SAAS,MAAM;EAAS,OAAO;CAAM,CAAC,EAC1E,CAAC,CACL,CACF;CACA,OAAO,OAAO,KAAK,EAAE,IAAI,CAAC;AAC5B,CAAC,CACH;;AAGF,MAAa,cAAcK;AAO3B,MAAM,gBAAgB,eAAgC,UACpDC,iBAAwB,KAAK,IACzB,QACA,IAAIF,eAAsB,EAAE,QAAQ,IAAIG,aAAoB,EAAE,UAAU,CAAC,EAAE,CAAC;;AAGlF,MAAa,aAAa,aAAwC;CAChE,OAAO,cACL,OAAO,WAAW;EAChB,WAAW,QAAQ,KAAK,SAAS,MAAM,SAAS,CAAC;EACjD,OAAO,aAAa,MAAM;CAC5B,CAAC;CACH,OAAO,eACL,OAAO,WAAW;EAAE,WAAW,QAAQ,KAAK,UAAU;EAAG,OAAO,aAAa,MAAM;CAAE,CAAC,CAAC,CAAC,KACtF,OAAO,KAAK,UAAU,SAAS,KAAK,KAAK,CAAC,CAC5C;AACJ;AAEA,MAAa,kBAAkB,YAC7B,MAAM,QAAQ,OAAO,CAAC,CAAC,UAAU,OAAO,CAAC"}
|
package/dist/DomainName.mjs
CHANGED
|
@@ -21,7 +21,7 @@ var DomainName_exports = /* @__PURE__ */ __exportAll({
|
|
|
21
21
|
const labelPattern = /^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/;
|
|
22
22
|
const Branded = Schema.String.check(Schema.makeFilter((value) => isNormalized(value) ? void 0 : "Expected a fully qualified DNS name", { identifier: "DomainName" })).pipe(Schema.brand("@domainkit/DomainName"));
|
|
23
23
|
/** Decodes any hostname spelling into its normalized, branded form; encodes back to a string. */
|
|
24
|
-
const Model = Schema.String.pipe(Schema.decodeTo(Branded, SchemaTransformation.
|
|
24
|
+
const Model = Schema.String.pipe(Schema.decodeTo(Branded, SchemaTransformation.transformEffect({
|
|
25
25
|
decode: (input, options) => Effect.try({
|
|
26
26
|
try: () => normalize(input),
|
|
27
27
|
catch: (cause) => new SchemaIssue.InvalidValue({ message: errorMessage(cause) }, input, options)
|
package/dist/DomainName.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DomainName.mjs","names":["Errors.DomainKitError","Reason.InvalidInput","Errors.fail"],"sources":["../src/DomainName.ts"],"sourcesContent":["/**\n * A normalized, IDN-aware hostname. Lifecycle inputs accept plain strings and validate them, so\n * most hosts never construct this directly; it exists for hosts that want the brand in their own\n * types.\n */\nimport { Effect, Option, Schema, SchemaIssue, SchemaTransformation } from \"effect\";\nimport { getDomain } from \"tldts\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\n\nconst labelPattern = /^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/;\n\nconst Branded = Schema.String.check(\n Schema.makeFilter<string>(\n (value) => (isNormalized(value) ? undefined : \"Expected a fully qualified DNS name\"),\n { identifier: \"DomainName\" },\n ),\n).pipe(Schema.brand(\"@domainkit/DomainName\"));\n\n/** Decodes any hostname spelling into its normalized, branded form; encodes back to a string. */\nexport const Model = Schema.String.pipe(\n Schema.decodeTo(\n Branded,\n SchemaTransformation.
|
|
1
|
+
{"version":3,"file":"DomainName.mjs","names":["Errors.DomainKitError","Reason.InvalidInput","Errors.fail"],"sources":["../src/DomainName.ts"],"sourcesContent":["/**\n * A normalized, IDN-aware hostname. Lifecycle inputs accept plain strings and validate them, so\n * most hosts never construct this directly; it exists for hosts that want the brand in their own\n * types.\n */\nimport { Effect, Option, Schema, SchemaIssue, SchemaTransformation } from \"effect\";\nimport { getDomain } from \"tldts\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\n\nconst labelPattern = /^[a-z0-9_](?:[a-z0-9_-]{0,61}[a-z0-9_])?$/;\n\nconst Branded = Schema.String.check(\n Schema.makeFilter<string>(\n (value) => (isNormalized(value) ? undefined : \"Expected a fully qualified DNS name\"),\n { identifier: \"DomainName\" },\n ),\n).pipe(Schema.brand(\"@domainkit/DomainName\"));\n\n/** Decodes any hostname spelling into its normalized, branded form; encodes back to a string. */\nexport const Model = Schema.String.pipe(\n Schema.decodeTo(\n Branded,\n SchemaTransformation.transformEffect({\n decode: (input, options) =>\n Effect.try({\n try: () => normalize(input),\n catch: (cause) =>\n new SchemaIssue.InvalidValue({ message: errorMessage(cause) }, input, options),\n }),\n encode: (domain) => Effect.succeed(domain),\n }),\n ),\n);\nexport type Model = typeof Branded.Type;\n\n/** Validates and normalizes; `None` when the input is not a hostname. */\nexport const fromString = (input: string): Option.Option<Model> => {\n try {\n return Option.some(normalizeUnsafe(input));\n } catch {\n return Option.none();\n }\n};\n\n/** Validates and normalizes; throws `DomainKit.Error` (reason `InvalidInput`) when invalid. */\nexport const fromStringUnsafe = (input: string): Model => {\n try {\n return normalizeUnsafe(input);\n } catch (cause) {\n throw new Errors.DomainKitError({\n reason: new Reason.InvalidInput({ message: errorMessage(cause), field: \"domain\" }),\n });\n }\n};\n\n/** Validates and normalizes inside Effect; fails with reason `InvalidInput`. */\nexport const decode = (\n input: string,\n field = \"domain\",\n): Effect.Effect<Model, Errors.DomainKitError> =>\n Effect.suspend(() => {\n try {\n return Effect.succeed(normalizeUnsafe(input));\n } catch (cause) {\n return Errors.fail(new Reason.InvalidInput({ message: errorMessage(cause), field }));\n }\n });\n\nexport const isDomainName = (input: unknown): input is Model =>\n typeof input === \"string\" && isNormalized(input);\n\n/**\n * Zone candidates from the name itself down to the registrable domain, most specific first:\n * `a.b.example.com` -> `a.b.example.com`, `b.example.com`, `example.com`. Empty when the name has\n * no registrable suffix.\n */\nexport const candidates = (domain: Model): ReadonlyArray<Model> => {\n const registrable = getDomain(domain, { allowPrivateDomains: true });\n if (registrable === null) return [];\n const labels = domain.split(\".\");\n const registrableLabels = registrable.split(\".\").length;\n const values: Array<Model> = [];\n for (let index = 0; index <= labels.length - registrableLabels; index += 1) {\n values.push(labels.slice(index).join(\".\") as Model);\n }\n return values;\n};\n\n/** `true` when `name` is `zone` or a subdomain of it. */\nexport const isWithin = (name: string, zone: string): boolean =>\n name === zone || name.endsWith(`.${zone}`);\n\nfunction isNormalized(value: string): boolean {\n return (\n value.length <= 253 &&\n value.includes(\".\") &&\n value.split(\".\").every((label) => labelPattern.test(label))\n );\n}\n\nfunction normalizeUnsafe(input: string): Model {\n return normalize(input) as Model;\n}\n\nfunction normalize(input: string): string {\n const labels = input\n .trim()\n .replace(/\\.+$/, \"\")\n .split(\".\")\n .map((label) => {\n if (label.includes(\"_\") || [...label].every((character) => character.charCodeAt(0) <= 127)) {\n return label.toLowerCase();\n }\n const hostname = new URL(`http://${label}.example`).hostname;\n const normalized = hostname.split(\".\")[0];\n if (normalized === undefined) throw new Error(\"Domain label could not be normalized\");\n return normalized.toLowerCase();\n });\n const value = labels.join(\".\");\n if (!isNormalized(value)) {\n throw new Error(`Expected a fully qualified DNS name, received ${JSON.stringify(input)}`);\n }\n return value;\n}\n\nfunction errorMessage(cause: unknown): string {\n return cause instanceof Error ? cause.message : String(cause);\n}\n"],"mappings":"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"}
|
package/dist/Vercel.mjs
CHANGED
|
@@ -38,10 +38,11 @@ const provider = (options = {}) => {
|
|
|
38
38
|
});
|
|
39
39
|
const integration = options.integration === void 0 ? void 0 : integrationAuth(options.integration);
|
|
40
40
|
function integrationAuth(settings) {
|
|
41
|
+
const installOrigin = (settings.installOrigin ?? "https://vercel.com").replace(/\/$/, "");
|
|
41
42
|
return {
|
|
42
43
|
label: "Install the Vercel integration",
|
|
43
44
|
start: (input) => {
|
|
44
|
-
const authorizationUrl = new URL(
|
|
45
|
+
const authorizationUrl = new URL(`${installOrigin}/integrations/${encodeURIComponent(settings.slug)}/new`);
|
|
45
46
|
authorizationUrl.searchParams.set("source", "external");
|
|
46
47
|
authorizationUrl.searchParams.set("state", input.state);
|
|
47
48
|
return Effect.succeed({ authorizationUrl: authorizationUrl.toString() });
|
package/dist/Vercel.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Vercel.mjs","names":["Client.exchangeCode","Errors.fail","Reason.Unauthenticated","Provider.make","Provider.tokenAuth","Client.user","Client.zones","teams","Client.teams","DomainName.decode","Provider.resolveAmong","Client.dns"],"sources":["../src/Vercel.ts"],"sourcesContent":["/** Vercel: personal tokens and marketplace integrations. */\nimport { type Config, Effect, Redacted, Schema } from \"effect\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\nimport * as DomainName from \"./DomainName.ts\";\nimport { resolve } from \"./internal/config.ts\";\nimport { type Fetch, rejectedToken } from \"./internal/http.ts\";\nimport * as Client from \"./internal/vercel/client.ts\";\nimport type * as Protocol from \"./internal/vercel/protocol.ts\";\nimport * as Provider from \"./Provider.ts\";\n\n/** `teamId` is `null` for a personal account; targets carry the team that owns the zone. */\nexport const TeamContext = Schema.Struct({ teamId: Schema.NullOr(Schema.String) });\nexport type TeamContext = typeof TeamContext.Type;\n\n/** Token-method input: the access token, and a team id to scope the connection to one team. */\nexport const TokenFields = Schema.Struct({\n token: Schema.RedactedFromValue(Schema.String),\n teamId: Schema.optionalKey(Schema.String),\n});\n\nexport interface Options {\n /** Omit to offer tokens only. */\n readonly integration?: {\n readonly clientId: string | Config.Config<string>;\n readonly clientSecret: Redacted.Redacted<string> | Config.Config<Redacted.Redacted<string>>;\n readonly slug: string;\n };\n readonly fetch?: Fetch;\n readonly baseUrl?: string;\n}\n\nconst capabilities = [\"dns:read\", \"dns:write\"] as const;\n\nexport const provider = (options: Options = {}): Provider.Definition<TeamContext> => {\n const fetch = options.fetch ?? globalThis.fetch;\n const baseUrl = (options.baseUrl ?? \"https://api.vercel.com\").replace(/\\/$/, \"\");\n const client = (token: string): Client.Options => ({ token, fetch, baseUrl });\n\n const targetOf = (domain: Protocol.Domain, label: string): Provider.Target => ({\n zone: domain.name,\n context: { teamId: domain.teamId } satisfies TeamContext,\n label: `${domain.name} (${label})`,\n nameservers: domain.nameservers.length > 0 ? domain.nameservers : domain.intendedNameservers,\n });\n\n const integration =\n options.integration === undefined ? undefined : integrationAuth(options.integration);\n\n function integrationAuth(\n settings: NonNullable<Options[\"integration\"]>,\n ): Provider.IntegrationAuth {\n return {\n label: \"Install the Vercel integration\",\n start: (input) => {\n const authorizationUrl = new URL(\n `https://vercel.com/integrations/${encodeURIComponent(settings.slug)}/new`,\n );\n authorizationUrl.searchParams.set(\"source\", \"external\");\n authorizationUrl.searchParams.set(\"state\", input.state);\n return Effect.succeed({ authorizationUrl: authorizationUrl.toString() });\n },\n complete: (input) =>\n Effect.gen(function* () {\n const clientId = yield* resolve(settings.clientId, \"integration.clientId\");\n const clientSecret = yield* resolve(settings.clientSecret, \"integration.clientSecret\");\n const token = yield* Client.exchangeCode({\n options: client(\"\"),\n clientId,\n clientSecret: Redacted.value(clientSecret),\n code: input.code,\n callbackUrl: input.callbackUrl,\n });\n const callbackTeam = input.params.teamId;\n if (callbackTeam !== undefined && callbackTeam !== token.team_id) {\n return yield* Errors.fail(\n new Reason.Unauthenticated({\n message: \"Vercel integration callback team does not match the installed team\",\n }),\n );\n }\n return {\n secret: Redacted.make(token.access_token),\n context: { teamId: token.team_id } satisfies TeamContext,\n expiresAt: null,\n };\n }),\n };\n }\n\n return Provider.make<TeamContext>({\n id: \"vercel\",\n name: \"Vercel\",\n nameservers: [\"vercel-dns.com\"],\n context: TeamContext,\n contextVersion: \"vercel.v1\",\n auth: {\n token: Provider.tokenAuth({\n label: \"Access token\",\n docsUrl: \"https://vercel.com/account/settings/tokens\",\n requiredCapabilities: capabilities,\n fields: TokenFields,\n authenticate: ({ token, teamId }) =>\n Client.user(client(Redacted.value(token))).pipe(\n Effect.map(() => ({\n secret: token,\n context: { teamId: teamId ?? null } satisfies TeamContext,\n expiresAt: null,\n })),\n rejectedToken,\n ),\n }),\n ...(integration === undefined ? {} : { integration }),\n },\n session: (credential) => {\n const clientOptions = client(Redacted.value(credential.secret));\n const context = Schema.decodeUnknownOption(TeamContext)(credential.context);\n const teamId = context._tag === \"Some\" ? context.value.teamId : null;\n const listTargets = (): Effect.Effect<\n ReadonlyArray<Provider.Target>,\n Errors.DomainKitError\n > =>\n teamId !== null\n ? Client.zones(clientOptions, teamId).pipe(\n Effect.map((domains) => domains.map((domain) => targetOf(domain, teamId))),\n )\n : Effect.gen(function* () {\n const personal = yield* Client.zones(clientOptions, null);\n const teams = yield* Client.teams(clientOptions).pipe(\n Effect.catchIf(\n (error) => error.reason._tag !== \"ProviderUnavailable\",\n () => Effect.succeed([]),\n ),\n );\n const perTeam = yield* Effect.forEach(teams, (team) =>\n Client.zones(clientOptions, team.id).pipe(\n Effect.map((domains) =>\n domains.map((domain) => targetOf(domain, team.name ?? team.slug)),\n ),\n ),\n );\n return [...personal.map((domain) => targetOf(domain, \"personal\")), ...perTeam.flat()];\n });\n return {\n capabilities: () => Effect.succeed(capabilities),\n listTargets,\n resolveTarget: (domain) =>\n Effect.gen(function* () {\n const name = yield* DomainName.decode(domain);\n const targets = yield* listTargets();\n return Provider.resolveAmong(name, targets);\n }),\n dns: (target) => {\n const scope = Schema.decodeUnknownOption(TeamContext)(target.context);\n return Client.dns(clientOptions, scope._tag === \"Some\" ? scope.value.teamId : teamId);\n },\n };\n },\n });\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Vercel.mjs","names":["Client.exchangeCode","Errors.fail","Reason.Unauthenticated","Provider.make","Provider.tokenAuth","Client.user","Client.zones","teams","Client.teams","DomainName.decode","Provider.resolveAmong","Client.dns"],"sources":["../src/Vercel.ts"],"sourcesContent":["/** Vercel: personal tokens and marketplace integrations. */\nimport { type Config, Effect, Redacted, Schema } from \"effect\";\n\nimport * as Errors from \"./internal/error.ts\";\nimport * as Reason from \"./Reason.ts\";\nimport * as DomainName from \"./DomainName.ts\";\nimport { resolve } from \"./internal/config.ts\";\nimport { type Fetch, rejectedToken } from \"./internal/http.ts\";\nimport * as Client from \"./internal/vercel/client.ts\";\nimport type * as Protocol from \"./internal/vercel/protocol.ts\";\nimport * as Provider from \"./Provider.ts\";\n\n/** `teamId` is `null` for a personal account; targets carry the team that owns the zone. */\nexport const TeamContext = Schema.Struct({ teamId: Schema.NullOr(Schema.String) });\nexport type TeamContext = typeof TeamContext.Type;\n\n/** Token-method input: the access token, and a team id to scope the connection to one team. */\nexport const TokenFields = Schema.Struct({\n token: Schema.RedactedFromValue(Schema.String),\n teamId: Schema.optionalKey(Schema.String),\n});\n\nexport interface Options {\n /** Omit to offer tokens only. */\n readonly integration?: {\n readonly clientId: string | Config.Config<string>;\n readonly clientSecret: Redacted.Redacted<string> | Config.Config<Redacted.Redacted<string>>;\n readonly slug: string;\n /**\n * Origin of the install page, which Vercel serves at `/integrations/{slug}/new` beneath it.\n * Default `https://vercel.com`; a stage points it at an emulator that mounts the same path.\n * It stays separate from `baseUrl` because in production these are different hosts:\n * `vercel.com` for the browser install, `api.vercel.com` for the code exchange and the REST API.\n */\n readonly installOrigin?: string;\n };\n readonly fetch?: Fetch;\n readonly baseUrl?: string;\n}\n\nconst capabilities = [\"dns:read\", \"dns:write\"] as const;\n\nexport const provider = (options: Options = {}): Provider.Definition<TeamContext> => {\n const fetch = options.fetch ?? globalThis.fetch;\n const baseUrl = (options.baseUrl ?? \"https://api.vercel.com\").replace(/\\/$/, \"\");\n const client = (token: string): Client.Options => ({ token, fetch, baseUrl });\n\n const targetOf = (domain: Protocol.Domain, label: string): Provider.Target => ({\n zone: domain.name,\n context: { teamId: domain.teamId } satisfies TeamContext,\n label: `${domain.name} (${label})`,\n nameservers: domain.nameservers.length > 0 ? domain.nameservers : domain.intendedNameservers,\n });\n\n const integration =\n options.integration === undefined ? undefined : integrationAuth(options.integration);\n\n function integrationAuth(\n settings: NonNullable<Options[\"integration\"]>,\n ): Provider.IntegrationAuth {\n const installOrigin = (settings.installOrigin ?? \"https://vercel.com\").replace(/\\/$/, \"\");\n return {\n label: \"Install the Vercel integration\",\n start: (input) => {\n const authorizationUrl = new URL(\n `${installOrigin}/integrations/${encodeURIComponent(settings.slug)}/new`,\n );\n authorizationUrl.searchParams.set(\"source\", \"external\");\n authorizationUrl.searchParams.set(\"state\", input.state);\n return Effect.succeed({ authorizationUrl: authorizationUrl.toString() });\n },\n complete: (input) =>\n Effect.gen(function* () {\n const clientId = yield* resolve(settings.clientId, \"integration.clientId\");\n const clientSecret = yield* resolve(settings.clientSecret, \"integration.clientSecret\");\n const token = yield* Client.exchangeCode({\n options: client(\"\"),\n clientId,\n clientSecret: Redacted.value(clientSecret),\n code: input.code,\n callbackUrl: input.callbackUrl,\n });\n const callbackTeam = input.params.teamId;\n if (callbackTeam !== undefined && callbackTeam !== token.team_id) {\n return yield* Errors.fail(\n new Reason.Unauthenticated({\n message: \"Vercel integration callback team does not match the installed team\",\n }),\n );\n }\n return {\n secret: Redacted.make(token.access_token),\n context: { teamId: token.team_id } satisfies TeamContext,\n expiresAt: null,\n };\n }),\n };\n }\n\n return Provider.make<TeamContext>({\n id: \"vercel\",\n name: \"Vercel\",\n nameservers: [\"vercel-dns.com\"],\n context: TeamContext,\n contextVersion: \"vercel.v1\",\n auth: {\n token: Provider.tokenAuth({\n label: \"Access token\",\n docsUrl: \"https://vercel.com/account/settings/tokens\",\n requiredCapabilities: capabilities,\n fields: TokenFields,\n authenticate: ({ token, teamId }) =>\n Client.user(client(Redacted.value(token))).pipe(\n Effect.map(() => ({\n secret: token,\n context: { teamId: teamId ?? null } satisfies TeamContext,\n expiresAt: null,\n })),\n rejectedToken,\n ),\n }),\n ...(integration === undefined ? {} : { integration }),\n },\n session: (credential) => {\n const clientOptions = client(Redacted.value(credential.secret));\n const context = Schema.decodeUnknownOption(TeamContext)(credential.context);\n const teamId = context._tag === \"Some\" ? context.value.teamId : null;\n const listTargets = (): Effect.Effect<\n ReadonlyArray<Provider.Target>,\n Errors.DomainKitError\n > =>\n teamId !== null\n ? Client.zones(clientOptions, teamId).pipe(\n Effect.map((domains) => domains.map((domain) => targetOf(domain, teamId))),\n )\n : Effect.gen(function* () {\n const personal = yield* Client.zones(clientOptions, null);\n const teams = yield* Client.teams(clientOptions).pipe(\n Effect.catchIf(\n (error) => error.reason._tag !== \"ProviderUnavailable\",\n () => Effect.succeed([]),\n ),\n );\n const perTeam = yield* Effect.forEach(teams, (team) =>\n Client.zones(clientOptions, team.id).pipe(\n Effect.map((domains) =>\n domains.map((domain) => targetOf(domain, team.name ?? team.slug)),\n ),\n ),\n );\n return [...personal.map((domain) => targetOf(domain, \"personal\")), ...perTeam.flat()];\n });\n return {\n capabilities: () => Effect.succeed(capabilities),\n listTargets,\n resolveTarget: (domain) =>\n Effect.gen(function* () {\n const name = yield* DomainName.decode(domain);\n const targets = yield* listTargets();\n return Provider.resolveAmong(name, targets);\n }),\n dns: (target) => {\n const scope = Schema.decodeUnknownOption(TeamContext)(target.context);\n return Client.dns(clientOptions, scope._tag === \"Some\" ? scope.value.teamId : teamId);\n },\n };\n },\n });\n};\n"],"mappings":"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"}
|
package/dist/package.mjs
CHANGED
package/dist/types/Vercel.d.ts
CHANGED
|
@@ -18,6 +18,13 @@ export interface Options {
|
|
|
18
18
|
readonly clientId: string | Config.Config<string>;
|
|
19
19
|
readonly clientSecret: Redacted.Redacted<string> | Config.Config<Redacted.Redacted<string>>;
|
|
20
20
|
readonly slug: string;
|
|
21
|
+
/**
|
|
22
|
+
* Origin of the install page, which Vercel serves at `/integrations/{slug}/new` beneath it.
|
|
23
|
+
* Default `https://vercel.com`; a stage points it at an emulator that mounts the same path.
|
|
24
|
+
* It stays separate from `baseUrl` because in production these are different hosts:
|
|
25
|
+
* `vercel.com` for the browser install, `api.vercel.com` for the code exchange and the REST API.
|
|
26
|
+
*/
|
|
27
|
+
readonly installOrigin?: string;
|
|
21
28
|
};
|
|
22
29
|
readonly fetch?: Fetch;
|
|
23
30
|
readonly baseUrl?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domainkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.18.0",
|
|
4
4
|
"description": "Build reviewable DNS plans for custom domains in TypeScript",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"custom-domains",
|
|
@@ -143,16 +143,17 @@
|
|
|
143
143
|
"tldts": "^7.4.11"
|
|
144
144
|
},
|
|
145
145
|
"devDependencies": {
|
|
146
|
-
"@effect/vitest": "4.0.0-rc.
|
|
146
|
+
"@effect/vitest": "4.0.0-rc.117",
|
|
147
147
|
"@types/bun": "1.4.0",
|
|
148
|
-
"effect": "4.0.0-rc.
|
|
148
|
+
"effect": "4.0.0-rc.117",
|
|
149
149
|
"miniflare": "3.20250718.3",
|
|
150
150
|
"tsdown": "0.22.14",
|
|
151
151
|
"typescript": "7.0.2",
|
|
152
|
-
"
|
|
152
|
+
"vite": "7.1.12",
|
|
153
|
+
"vitest": "5.0.1"
|
|
153
154
|
},
|
|
154
155
|
"peerDependencies": {
|
|
155
|
-
"effect": ">=4.0.0-rc.
|
|
156
|
+
"effect": ">=4.0.0-rc.117 <5.0.0"
|
|
156
157
|
},
|
|
157
158
|
"engines": {
|
|
158
159
|
"node": ">=24.10.0"
|