domainkit 0.16.0 → 0.17.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/package.mjs +1 -1
- 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":";;;;;;;;;;;;;;;;;;;;AAWA,MAAM,eAAe;AAErB,MAAM,UAAU,OAAO,OAAO,MAC5B,OAAO,YACJ,UAAW,aAAa,KAAK,IAAI,KAAA,IAAY,uCAC9C,EAAE,YAAY,aAAa,CAC7B,CACF,CAAC,CAAC,KAAK,OAAO,MAAM,uBAAuB,CAAC;;AAG5C,MAAa,QAAQ,OAAO,OAAO,KACjC,OAAO,SACL,SACA,qBAAqB,gBAAgB;CACnC,SAAS,OAAO,YACd,OAAO,IAAI;EACT,WAAW,UAAU,KAAK;EAC1B,QAAQ,UACN,IAAI,YAAY,aAAa,EAAE,SAAS,aAAa,KAAK,EAAE,GAAG,OAAO,OAAO;CACjF,CAAC;CACH,SAAS,WAAW,OAAO,QAAQ,MAAM;AAC3C,CAAC,CACH,CACF;;AAIA,MAAa,cAAc,UAAwC;CACjE,IAAI;EACF,OAAO,OAAO,KAAK,gBAAgB,KAAK,CAAC;CAC3C,QAAQ;EACN,OAAO,OAAO,KAAK;CACrB;AACF;;AAGA,MAAa,oBAAoB,UAAyB;CACxD,IAAI;EACF,OAAO,gBAAgB,KAAK;CAC9B,SAAS,OAAO;EACd,MAAM,IAAIA,eAAsB,EAC9B,QAAQ,IAAIC,aAAoB;GAAE,SAAS,aAAa,KAAK;GAAG,OAAO;EAAS,CAAC,EACnF,CAAC;CACH;AACF;;AAGA,MAAa,UACX,OACA,QAAQ,aAER,OAAO,cAAc;CACnB,IAAI;EACF,OAAO,OAAO,QAAQ,gBAAgB,KAAK,CAAC;CAC9C,SAAS,OAAO;EACd,OAAOC,KAAY,IAAID,aAAoB;GAAE,SAAS,aAAa,KAAK;GAAG;EAAM,CAAC,CAAC;CACrF;AACF,CAAC;AAEH,MAAa,gBAAgB,UAC3B,OAAO,UAAU,YAAY,aAAa,KAAK;;;;;;AAOjD,MAAa,cAAc,WAAwC;CACjE,MAAM,cAAc,UAAU,QAAQ,EAAE,qBAAqB,KAAK,CAAC;CACnE,IAAI,gBAAgB,MAAM,OAAO,CAAC;CAClC,MAAM,SAAS,OAAO,MAAM,GAAG;CAC/B,MAAM,oBAAoB,YAAY,MAAM,GAAG,CAAC,CAAC;CACjD,MAAM,SAAuB,CAAC;CAC9B,KAAK,IAAI,QAAQ,GAAG,SAAS,OAAO,SAAS,mBAAmB,SAAS,GACvE,OAAO,KAAK,OAAO,MAAM,KAAK,CAAC,CAAC,KAAK,GAAG,CAAU;CAEpD,OAAO;AACT;;AAGA,MAAa,YAAY,MAAc,SACrC,SAAS,QAAQ,KAAK,SAAS,IAAI,MAAM;AAE3C,SAAS,aAAa,OAAwB;CAC5C,OACE,MAAM,UAAU,OAChB,MAAM,SAAS,GAAG,KAClB,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,UAAU,aAAa,KAAK,KAAK,CAAC;AAE9D;AAEA,SAAS,gBAAgB,OAAsB;CAC7C,OAAO,UAAU,KAAK;AACxB;AAEA,SAAS,UAAU,OAAuB;CAcxC,MAAM,QAbS,MACZ,KAAK,CAAC,CACN,QAAQ,QAAQ,EAAE,CAAC,CACnB,MAAM,GAAG,CAAC,CACV,KAAK,UAAU;EACd,IAAI,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,cAAc,UAAU,WAAW,CAAC,KAAK,GAAG,GACvF,OAAO,MAAM,YAAY;EAG3B,MAAM,aADW,IAAI,IAAI,UAAU,MAAM,SAAS,CAAC,CAAC,SACxB,MAAM,GAAG,CAAC,CAAC;EACvC,IAAI,eAAe,KAAA,GAAW,MAAM,IAAI,MAAM,sCAAsC;EACpF,OAAO,WAAW,YAAY;CAChC,CACiB,CAAC,CAAC,KAAK,GAAG;CAC7B,IAAI,CAAC,aAAa,KAAK,GACrB,MAAM,IAAI,MAAM,iDAAiD,KAAK,UAAU,KAAK,GAAG;CAE1F,OAAO;AACT;AAEA,SAAS,aAAa,OAAwB;CAC5C,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC9D"}
|
package/dist/package.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "domainkit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.17.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"
|