@effect-auth/core 0.1.0-alpha.1 → 0.1.0-alpha.13
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 +790 -73
- package/dist/ApiKey.d.ts +207 -0
- package/dist/ApiKey.d.ts.map +1 -0
- package/dist/ApiKey.js +275 -0
- package/dist/ApiKey.js.map +1 -0
- package/dist/AuditLog.d.ts +335 -1
- package/dist/AuditLog.d.ts.map +1 -1
- package/dist/AuditLog.js +318 -1
- package/dist/AuditLog.js.map +1 -1
- package/dist/AuthConfig.d.ts +42 -0
- package/dist/AuthConfig.d.ts.map +1 -0
- package/dist/AuthConfig.js +43 -0
- package/dist/AuthConfig.js.map +1 -0
- package/dist/AuthFlow.d.ts +462 -36
- package/dist/AuthFlow.d.ts.map +1 -1
- package/dist/AuthFlow.js +657 -5
- package/dist/AuthFlow.js.map +1 -1
- package/dist/AuthKernel.d.ts +3 -0
- package/dist/AuthKernel.d.ts.map +1 -0
- package/dist/AuthKernel.js +9 -0
- package/dist/AuthKernel.js.map +1 -0
- package/dist/Challenge.d.ts +24 -4
- package/dist/Challenge.d.ts.map +1 -1
- package/dist/Challenge.js +167 -1
- package/dist/Challenge.js.map +1 -1
- package/dist/Client.d.ts +449 -0
- package/dist/Client.d.ts.map +1 -0
- package/dist/Client.js +985 -0
- package/dist/Client.js.map +1 -0
- package/dist/Crypto.d.ts +6 -1
- package/dist/Crypto.d.ts.map +1 -1
- package/dist/Crypto.js +62 -1
- package/dist/Crypto.js.map +1 -1
- package/dist/DomainVerification.d.ts +200 -0
- package/dist/DomainVerification.d.ts.map +1 -0
- package/dist/DomainVerification.js +304 -0
- package/dist/DomainVerification.js.map +1 -0
- package/dist/EffectQbSqliteStorage.d.ts +985 -0
- package/dist/EffectQbSqliteStorage.d.ts.map +1 -0
- package/dist/EffectQbSqliteStorage.js +2824 -0
- package/dist/EffectQbSqliteStorage.js.map +1 -0
- package/dist/EmailOtp.d.ts +120 -0
- package/dist/EmailOtp.d.ts.map +1 -0
- package/dist/EmailOtp.js +286 -0
- package/dist/EmailOtp.js.map +1 -0
- package/dist/EmailVerification.d.ts +121 -0
- package/dist/EmailVerification.d.ts.map +1 -0
- package/dist/EmailVerification.js +200 -0
- package/dist/EmailVerification.js.map +1 -0
- package/dist/HttpApi/Api.d.ts +2410 -0
- package/dist/HttpApi/Api.d.ts.map +1 -0
- package/dist/HttpApi/Api.js +3026 -0
- package/dist/HttpApi/Api.js.map +1 -0
- package/dist/HttpApi/Endpoints.d.ts +1073 -0
- package/dist/HttpApi/Endpoints.d.ts.map +1 -0
- package/dist/HttpApi/Endpoints.js +428 -0
- package/dist/HttpApi/Endpoints.js.map +1 -0
- package/dist/HttpApi/Errors.d.ts +114 -0
- package/dist/HttpApi/Errors.d.ts.map +1 -0
- package/dist/HttpApi/Errors.js +230 -0
- package/dist/HttpApi/Errors.js.map +1 -0
- package/dist/HttpApi/Schemas.d.ts +1254 -0
- package/dist/HttpApi/Schemas.d.ts.map +1 -0
- package/dist/HttpApi/Schemas.js +862 -0
- package/dist/HttpApi/Schemas.js.map +1 -0
- package/dist/HttpApi/Security.d.ts +159 -0
- package/dist/HttpApi/Security.d.ts.map +1 -0
- package/dist/HttpApi/Security.js +530 -0
- package/dist/HttpApi/Security.js.map +1 -0
- package/dist/HttpApi/Transport.d.ts +65 -0
- package/dist/HttpApi/Transport.d.ts.map +1 -0
- package/dist/HttpApi/Transport.js +311 -0
- package/dist/HttpApi/Transport.js.map +1 -0
- package/dist/HttpApi/index.d.ts +8 -0
- package/dist/HttpApi/index.d.ts.map +1 -0
- package/dist/HttpApi/index.js +7 -0
- package/dist/HttpApi/index.js.map +1 -0
- package/dist/HttpApi.d.ts +2 -0
- package/dist/HttpApi.d.ts.map +1 -0
- package/dist/HttpApi.js +2 -0
- package/dist/HttpApi.js.map +1 -0
- package/dist/Identifiers.d.ts +3 -0
- package/dist/Identifiers.d.ts.map +1 -1
- package/dist/Identifiers.js +2 -0
- package/dist/Identifiers.js.map +1 -1
- package/dist/IncidentAction.d.ts +80 -0
- package/dist/IncidentAction.d.ts.map +1 -0
- package/dist/IncidentAction.js +158 -0
- package/dist/IncidentAction.js.map +1 -0
- package/dist/Internal.d.ts +7 -0
- package/dist/Internal.d.ts.map +1 -0
- package/dist/Internal.js +12 -0
- package/dist/Internal.js.map +1 -0
- package/dist/Jwt.d.ts +281 -0
- package/dist/Jwt.d.ts.map +1 -0
- package/dist/Jwt.js +721 -0
- package/dist/Jwt.js.map +1 -0
- package/dist/LoginApproval.d.ts +314 -0
- package/dist/LoginApproval.d.ts.map +1 -0
- package/dist/LoginApproval.js +551 -0
- package/dist/LoginApproval.js.map +1 -0
- package/dist/LoginNotification.d.ts +183 -0
- package/dist/LoginNotification.d.ts.map +1 -0
- package/dist/LoginNotification.js +329 -0
- package/dist/LoginNotification.js.map +1 -0
- package/dist/LoginRisk.d.ts +344 -0
- package/dist/LoginRisk.d.ts.map +1 -0
- package/dist/LoginRisk.js +484 -0
- package/dist/LoginRisk.js.map +1 -0
- package/dist/MachineAuth.d.ts +73 -0
- package/dist/MachineAuth.d.ts.map +1 -0
- package/dist/MachineAuth.js +147 -0
- package/dist/MachineAuth.js.map +1 -0
- package/dist/MagicLink.d.ts +85 -0
- package/dist/MagicLink.d.ts.map +1 -0
- package/dist/MagicLink.js +206 -0
- package/dist/MagicLink.js.map +1 -0
- package/dist/Mailer.d.ts +147 -0
- package/dist/Mailer.d.ts.map +1 -0
- package/dist/Mailer.js +208 -0
- package/dist/Mailer.js.map +1 -0
- package/dist/OAuth.d.ts +1890 -0
- package/dist/OAuth.d.ts.map +1 -0
- package/dist/OAuth.js +3063 -0
- package/dist/OAuth.js.map +1 -0
- package/dist/Passkey.d.ts +334 -0
- package/dist/Passkey.d.ts.map +1 -0
- package/dist/Passkey.js +422 -0
- package/dist/Passkey.js.map +1 -0
- package/dist/PasskeySimpleWebAuthn.d.ts +11 -0
- package/dist/PasskeySimpleWebAuthn.d.ts.map +1 -0
- package/dist/PasskeySimpleWebAuthn.js +181 -0
- package/dist/PasskeySimpleWebAuthn.js.map +1 -0
- package/dist/Password.d.ts +237 -0
- package/dist/Password.d.ts.map +1 -0
- package/dist/Password.js +641 -0
- package/dist/Password.js.map +1 -0
- package/dist/Policy.d.ts +7 -4
- package/dist/Policy.d.ts.map +1 -1
- package/dist/Policy.js +28 -5
- package/dist/Policy.js.map +1 -1
- package/dist/Privacy.d.ts +15 -0
- package/dist/Privacy.d.ts.map +1 -1
- package/dist/Privacy.js +58 -1
- package/dist/Privacy.js.map +1 -1
- package/dist/RateLimiter.d.ts +104 -0
- package/dist/RateLimiter.d.ts.map +1 -0
- package/dist/RateLimiter.js +118 -0
- package/dist/RateLimiter.js.map +1 -0
- package/dist/RecoveryCode.d.ts +169 -0
- package/dist/RecoveryCode.d.ts.map +1 -0
- package/dist/RecoveryCode.js +299 -0
- package/dist/RecoveryCode.js.map +1 -0
- package/dist/RefreshToken.d.ts +222 -0
- package/dist/RefreshToken.d.ts.map +1 -0
- package/dist/RefreshToken.js +342 -0
- package/dist/RefreshToken.js.map +1 -0
- package/dist/Retention.d.ts +98 -0
- package/dist/Retention.d.ts.map +1 -0
- package/dist/Retention.js +204 -0
- package/dist/Retention.js.map +1 -0
- package/dist/SecurityTimeline.d.ts +78 -0
- package/dist/SecurityTimeline.d.ts.map +1 -0
- package/dist/SecurityTimeline.js +461 -0
- package/dist/SecurityTimeline.js.map +1 -0
- package/dist/Sessions.d.ts +123 -11
- package/dist/Sessions.d.ts.map +1 -1
- package/dist/Sessions.js +534 -1
- package/dist/Sessions.js.map +1 -1
- package/dist/StepUp.d.ts +44 -0
- package/dist/StepUp.d.ts.map +1 -0
- package/dist/StepUp.js +82 -0
- package/dist/StepUp.js.map +1 -0
- package/dist/Storage.d.ts +73 -5
- package/dist/Storage.d.ts.map +1 -1
- package/dist/Storage.js +11 -1
- package/dist/Storage.js.map +1 -1
- package/dist/StorageMigrations.d.ts +23 -1
- package/dist/StorageMigrations.d.ts.map +1 -1
- package/dist/StorageMigrations.js +462 -2
- package/dist/StorageMigrations.js.map +1 -1
- package/dist/Testing.d.ts +9 -1
- package/dist/Testing.d.ts.map +1 -1
- package/dist/Testing.js +30 -2
- package/dist/Testing.js.map +1 -1
- package/dist/Totp.d.ts +220 -0
- package/dist/Totp.d.ts.map +1 -0
- package/dist/Totp.js +477 -0
- package/dist/Totp.js.map +1 -0
- package/dist/TrustedDevice.d.ts +127 -0
- package/dist/TrustedDevice.d.ts.map +1 -0
- package/dist/TrustedDevice.js +252 -0
- package/dist/TrustedDevice.js.map +1 -0
- package/dist/WaitUntil.d.ts.map +1 -1
- package/dist/WaitUntil.js +1 -1
- package/dist/WaitUntil.js.map +1 -1
- package/dist/Webhook.d.ts +380 -0
- package/dist/Webhook.d.ts.map +1 -0
- package/dist/Webhook.js +592 -0
- package/dist/Webhook.js.map +1 -0
- package/dist/alchemy/cloudflare/Email.d.ts +25 -0
- package/dist/alchemy/cloudflare/Email.d.ts.map +1 -0
- package/dist/alchemy/cloudflare/Email.js +117 -0
- package/dist/alchemy/cloudflare/Email.js.map +1 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts +34 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js +30 -0
- package/dist/alchemy/cloudflare/RateLimitDurableObject.js.map +1 -0
- package/dist/cloudflare/Email.d.ts +25 -0
- package/dist/cloudflare/Email.d.ts.map +1 -0
- package/dist/cloudflare/Email.js +153 -0
- package/dist/cloudflare/Email.js.map +1 -0
- package/dist/cloudflare/RateLimitDurableObject.d.ts +50 -0
- package/dist/cloudflare/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/cloudflare/RateLimitDurableObject.js +51 -0
- package/dist/cloudflare/RateLimitDurableObject.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/RateLimitDurableObject.d.ts +32 -0
- package/dist/internal/RateLimitDurableObject.d.ts.map +1 -0
- package/dist/internal/RateLimitDurableObject.js +80 -0
- package/dist/internal/RateLimitDurableObject.js.map +1 -0
- package/migrations/0002_auth_password.sql +25 -0
- package/migrations/0003_auth_login_approval_review.sql +22 -0
- package/migrations/0004_auth_trusted_device.sql +12 -0
- package/migrations/0005_auth_passkey.sql +17 -0
- package/migrations/0006_auth_totp_factor.sql +17 -0
- package/migrations/0007_auth_recovery_code.sql +13 -0
- package/migrations/0008_auth_api_key.sql +17 -0
- package/migrations/0009_auth_refresh_token.sql +21 -0
- package/migrations/0010_auth_jwt_revocation.sql +8 -0
- package/migrations/0011_auth_oauth_account.sql +16 -0
- package/migrations/0012_auth_oauth_provider_token_vault.sql +20 -0
- package/migrations/0013_auth_security_timeline.sql +16 -0
- package/migrations/0014_auth_webhook_outbox.sql +16 -0
- package/migrations/0015_auth_webhook_replay.sql +7 -0
- package/migrations/0016_auth_login_risk_history.sql +23 -0
- package/migrations/0017_auth_audit_log.sql +17 -0
- package/migrations/0018_auth_domain_verification.sql +18 -0
- package/migrations/0019_auth_oauth_authorization_code.sql +17 -0
- package/migrations/0020_auth_oauth_provider_mode_token.sql +24 -0
- package/migrations/0021_auth_oauth_client_secret.sql +14 -0
- package/migrations/0022_auth_oauth_client.sql +15 -0
- package/migrations/0023_auth_oauth_consent.sql +15 -0
- package/package.json +162 -26
- package/dist/D1Kysely.d.ts +0 -40
- package/dist/D1Kysely.d.ts.map +0 -1
- package/dist/D1Kysely.js +0 -75
- package/dist/D1Kysely.js.map +0 -1
- package/dist/KyselyStorage.d.ts +0 -41
- package/dist/KyselyStorage.d.ts.map +0 -1
- package/dist/KyselyStorage.js +0 -176
- package/dist/KyselyStorage.js.map +0 -1
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Data, Effect, Redacted } from "effect";
|
|
2
|
+
export class MachineAuthError extends Data.TaggedError("MachineAuthError") {
|
|
3
|
+
}
|
|
4
|
+
export const bearerToken = (headers) => {
|
|
5
|
+
const authorization = headers.get("authorization");
|
|
6
|
+
if (authorization === null) {
|
|
7
|
+
return undefined;
|
|
8
|
+
}
|
|
9
|
+
const [scheme, token] = authorization.trim().split(/\s+/, 2);
|
|
10
|
+
return scheme?.toLowerCase() === "bearer" && token !== undefined && token !== ""
|
|
11
|
+
? token
|
|
12
|
+
: undefined;
|
|
13
|
+
};
|
|
14
|
+
export const apiKeyPrefixFromSecret = (secret) => {
|
|
15
|
+
const separator = secret.indexOf(".");
|
|
16
|
+
return separator > 0 ? secret.slice(0, separator) : "malformed";
|
|
17
|
+
};
|
|
18
|
+
export const jwtClaimScopes = (claims) => {
|
|
19
|
+
const { scope, scopes } = claims;
|
|
20
|
+
if (typeof scope === "string") {
|
|
21
|
+
return scope.split(/\s+/).filter((value) => value.length > 0);
|
|
22
|
+
}
|
|
23
|
+
return Array.isArray(scopes) &&
|
|
24
|
+
scopes.every((value) => typeof value === "string")
|
|
25
|
+
? scopes
|
|
26
|
+
: [];
|
|
27
|
+
};
|
|
28
|
+
const nonEmptyStringField = (record, key) => {
|
|
29
|
+
if (key === undefined) {
|
|
30
|
+
return undefined;
|
|
31
|
+
}
|
|
32
|
+
const value = record?.[key];
|
|
33
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
34
|
+
};
|
|
35
|
+
const machineActorMetadataFields = (record, options, defaults) => {
|
|
36
|
+
const tenantId = nonEmptyStringField(record, options.tenantIdField ?? defaults.tenantIdField);
|
|
37
|
+
const serviceAccountId = nonEmptyStringField(record, options.serviceAccountIdField ?? defaults.serviceAccountIdField);
|
|
38
|
+
return {
|
|
39
|
+
...(tenantId === undefined ? {} : { tenantId }),
|
|
40
|
+
...(serviceAccountId === undefined ? {} : { serviceAccountId }),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export const apiKeyMachineActor = (key, options = {}) => ({
|
|
44
|
+
kind: "api_key",
|
|
45
|
+
userId: key.userId,
|
|
46
|
+
keyId: key.id,
|
|
47
|
+
scopes: key.scopes,
|
|
48
|
+
key,
|
|
49
|
+
...machineActorMetadataFields(key.metadata, options, {
|
|
50
|
+
tenantIdField: "tenantId",
|
|
51
|
+
serviceAccountIdField: "serviceAccountId",
|
|
52
|
+
}),
|
|
53
|
+
});
|
|
54
|
+
export const jwtMachineActor = (input, options = {}) => {
|
|
55
|
+
const jwtId = typeof input.claims.jti === "string" && input.claims.jti.length > 0
|
|
56
|
+
? input.claims.jti
|
|
57
|
+
: undefined;
|
|
58
|
+
return {
|
|
59
|
+
kind: "jwt",
|
|
60
|
+
subject: input.claims.sub,
|
|
61
|
+
scopes: input.scopes ?? jwtClaimScopes(input.claims),
|
|
62
|
+
claims: input.claims,
|
|
63
|
+
key: input.key,
|
|
64
|
+
...(jwtId === undefined ? {} : { jwtId }),
|
|
65
|
+
...machineActorMetadataFields(input.claims, options, {
|
|
66
|
+
tenantIdField: "tenant_id",
|
|
67
|
+
serviceAccountIdField: "service_account_id",
|
|
68
|
+
}),
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
const missingScopes = (actorScopes, requiredScopes) => (requiredScopes ?? []).filter((scope) => !actorScopes.includes(scope));
|
|
72
|
+
export const requireMachineScopes = (input) => {
|
|
73
|
+
const missing = missingScopes(input.actor.scopes, input.scopes);
|
|
74
|
+
return missing.length === 0
|
|
75
|
+
? Effect.succeed(input.actor)
|
|
76
|
+
: Effect.fail(new MachineAuthError({
|
|
77
|
+
reason: "missing_scope",
|
|
78
|
+
message: "Machine credential is missing a required scope",
|
|
79
|
+
}));
|
|
80
|
+
};
|
|
81
|
+
export const verifyMachineApiKey = (options) => Effect.gen(function* () {
|
|
82
|
+
const secret = bearerToken(options.headers);
|
|
83
|
+
if (secret === undefined) {
|
|
84
|
+
return yield* new MachineAuthError({
|
|
85
|
+
reason: "missing_bearer",
|
|
86
|
+
message: "Missing bearer token",
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
const result = yield* options.apiKeyVerification
|
|
90
|
+
.verify({
|
|
91
|
+
secret: Redacted.make(secret),
|
|
92
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
93
|
+
...(options.verificationMetadata === undefined
|
|
94
|
+
? {}
|
|
95
|
+
: { metadata: options.verificationMetadata }),
|
|
96
|
+
})
|
|
97
|
+
.pipe(Effect.mapError((cause) => new MachineAuthError({
|
|
98
|
+
reason: "verification_failed",
|
|
99
|
+
message: "Failed to verify machine API key",
|
|
100
|
+
cause,
|
|
101
|
+
})));
|
|
102
|
+
if (!result.valid || result.key === undefined) {
|
|
103
|
+
return yield* new MachineAuthError({
|
|
104
|
+
reason: "invalid_api_key",
|
|
105
|
+
message: "Invalid API key bearer token",
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return yield* requireMachineScopes({
|
|
109
|
+
actor: apiKeyMachineActor(result.key, options),
|
|
110
|
+
scopes: options.requiredScopes ?? [],
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
export const verifyMachineJwt = (options) => Effect.gen(function* () {
|
|
114
|
+
const token = bearerToken(options.headers);
|
|
115
|
+
if (token === undefined) {
|
|
116
|
+
return yield* new MachineAuthError({
|
|
117
|
+
reason: "missing_bearer",
|
|
118
|
+
message: "Missing bearer token",
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
const result = yield* options.jwtVerifier
|
|
122
|
+
.verify({
|
|
123
|
+
token: Redacted.make(token),
|
|
124
|
+
...(options.issuer === undefined ? {} : { issuer: options.issuer }),
|
|
125
|
+
...(options.audience === undefined ? {} : { audience: options.audience }),
|
|
126
|
+
...(options.now === undefined ? {} : { now: options.now }),
|
|
127
|
+
...(options.clockTolerance === undefined
|
|
128
|
+
? {}
|
|
129
|
+
: { clockTolerance: options.clockTolerance }),
|
|
130
|
+
})
|
|
131
|
+
.pipe(Effect.mapError((cause) => new MachineAuthError({
|
|
132
|
+
reason: "verification_failed",
|
|
133
|
+
message: "Failed to verify machine JWT",
|
|
134
|
+
cause,
|
|
135
|
+
})));
|
|
136
|
+
if (!result.valid) {
|
|
137
|
+
return yield* new MachineAuthError({
|
|
138
|
+
reason: "invalid_jwt",
|
|
139
|
+
message: "Invalid JWT bearer token",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
return yield* requireMachineScopes({
|
|
143
|
+
actor: jwtMachineActor(result, options),
|
|
144
|
+
scopes: options.requiredScopes ?? [],
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
//# sourceMappingURL=MachineAuth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MachineAuth.js","sourceRoot":"","sources":["../src/MachineAuth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { Context, Duration, Effect, Layer, Redacted } from "effect";
|
|
2
|
+
import { AuthFlow } from "./AuthFlow.js";
|
|
3
|
+
import type { AuthFlowPrimaryFactorResult, AuthFlowService, AuthResultOf } from "./AuthFlow.js";
|
|
4
|
+
import { Challenge } from "./Challenge.js";
|
|
5
|
+
import type { ChallengeService } from "./Challenge.js";
|
|
6
|
+
import { Crypto } from "./Crypto.js";
|
|
7
|
+
import type { CryptoService } from "./Crypto.js";
|
|
8
|
+
import type { ChallengeId, UnixMillis } from "./Identifiers.js";
|
|
9
|
+
import { Email } from "./Identifiers.js";
|
|
10
|
+
import type { LoginRequestContext } from "./LoginRisk.js";
|
|
11
|
+
import { AuthMailer } from "./Mailer.js";
|
|
12
|
+
import type { AuthMailerService } from "./Mailer.js";
|
|
13
|
+
import { UserStore } from "./Storage.js";
|
|
14
|
+
import type { UserStoreService } from "./Storage.js";
|
|
15
|
+
export interface MagicLinkStartInput {
|
|
16
|
+
readonly email: Email;
|
|
17
|
+
readonly secret?: Redacted.Redacted<string>;
|
|
18
|
+
readonly ttl?: Duration.Duration;
|
|
19
|
+
readonly locale?: string;
|
|
20
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
21
|
+
}
|
|
22
|
+
export interface MagicLinkStarted {
|
|
23
|
+
readonly challengeId: ChallengeId;
|
|
24
|
+
readonly email: Email;
|
|
25
|
+
readonly expiresAt: UnixMillis;
|
|
26
|
+
}
|
|
27
|
+
export interface MagicLinkVerifyInput {
|
|
28
|
+
readonly challengeId: ChallengeId;
|
|
29
|
+
readonly secret: Redacted.Redacted<string>;
|
|
30
|
+
readonly trustedDeviceToken?: Redacted.Redacted<string>;
|
|
31
|
+
readonly request?: LoginRequestContext;
|
|
32
|
+
}
|
|
33
|
+
export interface MagicLinkUrlInput extends MagicLinkStarted {
|
|
34
|
+
readonly secret: Redacted.Redacted<string>;
|
|
35
|
+
readonly locale?: string;
|
|
36
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
37
|
+
}
|
|
38
|
+
declare const MagicLinkStartError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
39
|
+
readonly _tag: "MagicLinkStartError";
|
|
40
|
+
} & Readonly<A>;
|
|
41
|
+
export declare class MagicLinkStartError extends MagicLinkStartError_base<{
|
|
42
|
+
readonly message: string;
|
|
43
|
+
readonly cause?: unknown;
|
|
44
|
+
}> {
|
|
45
|
+
}
|
|
46
|
+
declare const MagicLinkVerifyError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
47
|
+
readonly _tag: "MagicLinkVerifyError";
|
|
48
|
+
} & Readonly<A>;
|
|
49
|
+
export declare class MagicLinkVerifyError extends MagicLinkVerifyError_base<{
|
|
50
|
+
readonly message: string;
|
|
51
|
+
readonly cause?: unknown;
|
|
52
|
+
}> {
|
|
53
|
+
}
|
|
54
|
+
export type MagicLinkError = MagicLinkStartError | MagicLinkVerifyError;
|
|
55
|
+
export type MagicLinkVerifyResult = AuthFlowPrimaryFactorResult<"magic-link"> | AuthResultOf<"InvalidCredentials" | "AccountDisabled">;
|
|
56
|
+
export interface MagicLinkLoginService {
|
|
57
|
+
readonly start: (input: MagicLinkStartInput) => Effect.Effect<MagicLinkStarted, MagicLinkStartError>;
|
|
58
|
+
readonly verify: (input: MagicLinkVerifyInput) => Effect.Effect<MagicLinkVerifyResult, MagicLinkVerifyError>;
|
|
59
|
+
}
|
|
60
|
+
declare const MagicLinkLogin_base: Context.ServiceClass<MagicLinkLogin, "auth/login/MagicLink", MagicLinkLoginService>;
|
|
61
|
+
export declare class MagicLinkLogin extends MagicLinkLogin_base {
|
|
62
|
+
}
|
|
63
|
+
export declare namespace MagicLinkLogin {
|
|
64
|
+
const make: (service: MagicLinkLoginService) => MagicLinkLoginService;
|
|
65
|
+
}
|
|
66
|
+
export interface MagicLinkOptions {
|
|
67
|
+
readonly ttl?: Duration.Duration;
|
|
68
|
+
readonly secretBytes?: number;
|
|
69
|
+
readonly userIdBytes?: number;
|
|
70
|
+
readonly makeUrl: (input: MagicLinkUrlInput) => string;
|
|
71
|
+
}
|
|
72
|
+
export interface MagicLinkDependencies extends MagicLinkOptions {
|
|
73
|
+
readonly challenge: ChallengeService;
|
|
74
|
+
readonly users: UserStoreService;
|
|
75
|
+
readonly crypto: CryptoService;
|
|
76
|
+
readonly authFlow: AuthFlowService;
|
|
77
|
+
readonly authMailer: AuthMailerService;
|
|
78
|
+
}
|
|
79
|
+
export declare const defaultMagicLinkTtl: Duration.Duration;
|
|
80
|
+
export declare const defaultMagicLinkSecretBytes = 32;
|
|
81
|
+
export declare const makeMagicLinkLogin: (dependencies: MagicLinkDependencies) => MagicLinkLoginService;
|
|
82
|
+
export declare const MagicLinkLoginLive: (options: MagicLinkOptions) => Layer.Layer<MagicLinkLogin, never, Crypto | UserStore | Challenge | AuthMailer | AuthFlow>;
|
|
83
|
+
export declare const MagicLinkFeatureLive: (options: MagicLinkOptions) => Layer.Layer<MagicLinkLogin, never, Crypto | UserStore | Challenge | AuthMailer | AuthFlow>;
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=MagicLink.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MagicLink.d.ts","sourceRoot":"","sources":["../src/MagicLink.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { Context, Data, Duration, Effect, Layer, Option, Redacted } from "effect";
|
|
2
|
+
import { AuthFlow, AuthResult } from "./AuthFlow.js";
|
|
3
|
+
import { Challenge } from "./Challenge.js";
|
|
4
|
+
import { Crypto } from "./Crypto.js";
|
|
5
|
+
import { Email, UserId } from "./Identifiers.js";
|
|
6
|
+
import { currentUnixMillis } from "./Internal.js";
|
|
7
|
+
import { AuthMailer } from "./Mailer.js";
|
|
8
|
+
import { UserStore } from "./Storage.js";
|
|
9
|
+
export class MagicLinkStartError extends Data.TaggedError("MagicLinkStartError") {
|
|
10
|
+
}
|
|
11
|
+
export class MagicLinkVerifyError extends Data.TaggedError("MagicLinkVerifyError") {
|
|
12
|
+
}
|
|
13
|
+
export class MagicLinkLogin extends Context.Service()("auth/login/MagicLink") {
|
|
14
|
+
}
|
|
15
|
+
(function (MagicLinkLogin) {
|
|
16
|
+
MagicLinkLogin.make = (service) => MagicLinkLogin.of(service);
|
|
17
|
+
})(MagicLinkLogin || (MagicLinkLogin = {}));
|
|
18
|
+
export const defaultMagicLinkTtl = Duration.minutes(15);
|
|
19
|
+
export const defaultMagicLinkSecretBytes = 32;
|
|
20
|
+
const verifiedExistingUser = (users, user) => Effect.gen(function* () {
|
|
21
|
+
if (user.disabledAt !== undefined) {
|
|
22
|
+
return AuthResult.AccountDisabled();
|
|
23
|
+
}
|
|
24
|
+
if (user.emailVerified) {
|
|
25
|
+
return { _tag: "User", user };
|
|
26
|
+
}
|
|
27
|
+
const updatedAt = yield* currentUnixMillis;
|
|
28
|
+
const updated = yield* users
|
|
29
|
+
.markEmailVerified({ userId: user.id, updatedAt })
|
|
30
|
+
.pipe(Effect.mapError((cause) => new MagicLinkVerifyError({
|
|
31
|
+
message: "Failed to mark email verified",
|
|
32
|
+
cause,
|
|
33
|
+
})));
|
|
34
|
+
if (Option.isNone(updated)) {
|
|
35
|
+
return yield* new MagicLinkVerifyError({ message: "User not found" });
|
|
36
|
+
}
|
|
37
|
+
return { _tag: "User", user: updated.value };
|
|
38
|
+
});
|
|
39
|
+
const findByEmail = (users, email) => users.findByEmail(email).pipe(Effect.mapError((cause) => new MagicLinkVerifyError({
|
|
40
|
+
message: "Failed to load user by email",
|
|
41
|
+
cause,
|
|
42
|
+
})));
|
|
43
|
+
const createVerifiedUser = (dependencies, email) => Effect.gen(function* () {
|
|
44
|
+
const now = yield* currentUnixMillis;
|
|
45
|
+
const userId = UserId(yield* dependencies.crypto
|
|
46
|
+
.randomToken(dependencies.userIdBytes ?? 16)
|
|
47
|
+
.pipe(Effect.mapError((cause) => new MagicLinkVerifyError({
|
|
48
|
+
message: "Failed to generate user id",
|
|
49
|
+
cause,
|
|
50
|
+
}))));
|
|
51
|
+
const user = {
|
|
52
|
+
id: userId,
|
|
53
|
+
email,
|
|
54
|
+
emailVerified: true,
|
|
55
|
+
createdAt: now,
|
|
56
|
+
updatedAt: now,
|
|
57
|
+
};
|
|
58
|
+
return yield* dependencies.users.insert(user).pipe(Effect.as({ _tag: "User", user }), Effect.catchTag("StorageError", (cause) => findByEmail(dependencies.users, email).pipe(Effect.flatMap((existing) => Option.isSome(existing)
|
|
59
|
+
? verifiedExistingUser(dependencies.users, existing.value)
|
|
60
|
+
: Effect.fail(new MagicLinkVerifyError({
|
|
61
|
+
message: "Failed to create user",
|
|
62
|
+
cause,
|
|
63
|
+
}))))));
|
|
64
|
+
});
|
|
65
|
+
const findOrCreateVerifiedUser = (dependencies, email) => Effect.gen(function* () {
|
|
66
|
+
const existing = yield* findByEmail(dependencies.users, email);
|
|
67
|
+
if (Option.isSome(existing)) {
|
|
68
|
+
return yield* verifiedExistingUser(dependencies.users, existing.value);
|
|
69
|
+
}
|
|
70
|
+
return yield* createVerifiedUser(dependencies, email);
|
|
71
|
+
});
|
|
72
|
+
const invalidateChallenge = (challenge, id) => challenge
|
|
73
|
+
.consume(id)
|
|
74
|
+
.pipe(Effect.catchTag("ChallengeConsumeError", () => Effect.void));
|
|
75
|
+
const startSecret = (crypto, input, secretBytes) => {
|
|
76
|
+
if (input.secret !== undefined) {
|
|
77
|
+
return Effect.succeed(Redacted.make(Redacted.value(input.secret).trim()));
|
|
78
|
+
}
|
|
79
|
+
return crypto.randomToken(secretBytes).pipe(Effect.map(Redacted.make), Effect.mapError((cause) => new MagicLinkStartError({
|
|
80
|
+
message: "Failed to generate magic link secret",
|
|
81
|
+
cause,
|
|
82
|
+
})));
|
|
83
|
+
};
|
|
84
|
+
const makeMagicLinkUrl = (dependencies, input) => Effect.try({
|
|
85
|
+
try: () => dependencies.makeUrl(input),
|
|
86
|
+
catch: (cause) => new MagicLinkStartError({
|
|
87
|
+
message: "Failed to build magic link URL",
|
|
88
|
+
cause,
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
const verifySecret = (secret) => Redacted.make(Redacted.value(secret).trim());
|
|
92
|
+
export const makeMagicLinkLogin = (dependencies) => {
|
|
93
|
+
const ttl = dependencies.ttl ?? defaultMagicLinkTtl;
|
|
94
|
+
const secretBytes = dependencies.secretBytes ?? defaultMagicLinkSecretBytes;
|
|
95
|
+
return MagicLinkLogin.make({
|
|
96
|
+
start: Effect.fn("auth.magic_link.start")(function* (input) {
|
|
97
|
+
yield* Effect.annotateCurrentSpan("auth.method", "magic-link");
|
|
98
|
+
const secret = yield* startSecret(dependencies.crypto, input, secretBytes);
|
|
99
|
+
const issued = yield* dependencies.challenge
|
|
100
|
+
.issue({
|
|
101
|
+
type: "magic-link",
|
|
102
|
+
subject: input.email,
|
|
103
|
+
ttl: input.ttl ?? ttl,
|
|
104
|
+
secret,
|
|
105
|
+
metadata: input.metadata,
|
|
106
|
+
})
|
|
107
|
+
.pipe(Effect.mapError((cause) => new MagicLinkStartError({
|
|
108
|
+
message: "Failed to issue magic link challenge",
|
|
109
|
+
cause,
|
|
110
|
+
})));
|
|
111
|
+
const started = {
|
|
112
|
+
challengeId: issued.id,
|
|
113
|
+
email: input.email,
|
|
114
|
+
expiresAt: issued.expiresAt,
|
|
115
|
+
};
|
|
116
|
+
const url = yield* makeMagicLinkUrl(dependencies, {
|
|
117
|
+
...started,
|
|
118
|
+
secret,
|
|
119
|
+
locale: input.locale,
|
|
120
|
+
metadata: input.metadata,
|
|
121
|
+
}).pipe(Effect.matchEffect({
|
|
122
|
+
onSuccess: Effect.succeed,
|
|
123
|
+
onFailure: (error) => invalidateChallenge(dependencies.challenge, issued.id).pipe(Effect.flatMap(() => Effect.fail(error))),
|
|
124
|
+
}));
|
|
125
|
+
yield* dependencies.authMailer
|
|
126
|
+
.send({
|
|
127
|
+
_tag: "MagicLink",
|
|
128
|
+
to: input.email,
|
|
129
|
+
challengeId: issued.id,
|
|
130
|
+
url,
|
|
131
|
+
expiresAt: issued.expiresAt,
|
|
132
|
+
locale: input.locale,
|
|
133
|
+
metadata: input.metadata,
|
|
134
|
+
})
|
|
135
|
+
.pipe(Effect.matchEffect({
|
|
136
|
+
onSuccess: () => Effect.void,
|
|
137
|
+
onFailure: (cause) => invalidateChallenge(dependencies.challenge, issued.id).pipe(Effect.flatMap(() => Effect.fail(new MagicLinkStartError({
|
|
138
|
+
message: "Failed to send magic link",
|
|
139
|
+
cause,
|
|
140
|
+
})))),
|
|
141
|
+
}));
|
|
142
|
+
return started;
|
|
143
|
+
}),
|
|
144
|
+
verify: Effect.fn("auth.magic_link.verify")(function* (input) {
|
|
145
|
+
yield* Effect.annotateCurrentSpan("auth.method", "magic-link");
|
|
146
|
+
const verifiedOption = yield* dependencies.challenge
|
|
147
|
+
.verify({
|
|
148
|
+
challengeId: input.challengeId,
|
|
149
|
+
type: "magic-link",
|
|
150
|
+
secret: verifySecret(input.secret),
|
|
151
|
+
})
|
|
152
|
+
.pipe(Effect.match({
|
|
153
|
+
onSuccess: Option.some,
|
|
154
|
+
onFailure: () => Option.none(),
|
|
155
|
+
}));
|
|
156
|
+
if (Option.isNone(verifiedOption)) {
|
|
157
|
+
yield* Effect.annotateCurrentSpan("auth.result", "InvalidCredentials");
|
|
158
|
+
return AuthResult.InvalidCredentials();
|
|
159
|
+
}
|
|
160
|
+
const email = Email(verifiedOption.value.subject);
|
|
161
|
+
const userResult = yield* findOrCreateVerifiedUser(dependencies, email);
|
|
162
|
+
if (userResult._tag === "AccountDisabled") {
|
|
163
|
+
yield* Effect.annotateCurrentSpan("auth.result", "AccountDisabled");
|
|
164
|
+
return userResult;
|
|
165
|
+
}
|
|
166
|
+
return yield* dependencies.authFlow
|
|
167
|
+
.completePrimaryFactor({
|
|
168
|
+
userId: userResult.user.id,
|
|
169
|
+
email: userResult.user.email,
|
|
170
|
+
intent: "sign-in",
|
|
171
|
+
method: "magic-link",
|
|
172
|
+
amr: ["email", "link"],
|
|
173
|
+
aal: "aal1",
|
|
174
|
+
claims: { emailVerified: true },
|
|
175
|
+
...(input.trustedDeviceToken === undefined
|
|
176
|
+
? {}
|
|
177
|
+
: { trustedDeviceToken: input.trustedDeviceToken }),
|
|
178
|
+
...(input.request === undefined ? {} : { request: input.request }),
|
|
179
|
+
...(verifiedOption.value.metadata === undefined
|
|
180
|
+
? {}
|
|
181
|
+
: { metadata: verifiedOption.value.metadata }),
|
|
182
|
+
})
|
|
183
|
+
.pipe(Effect.mapError((cause) => new MagicLinkVerifyError({
|
|
184
|
+
message: "Failed to complete magic link authentication",
|
|
185
|
+
cause,
|
|
186
|
+
})));
|
|
187
|
+
}),
|
|
188
|
+
});
|
|
189
|
+
};
|
|
190
|
+
export const MagicLinkLoginLive = (options) => Layer.effect(MagicLinkLogin)(Effect.gen(function* () {
|
|
191
|
+
const challenge = yield* Challenge;
|
|
192
|
+
const users = yield* UserStore;
|
|
193
|
+
const crypto = yield* Crypto;
|
|
194
|
+
const authFlow = yield* AuthFlow;
|
|
195
|
+
const authMailer = yield* AuthMailer;
|
|
196
|
+
return makeMagicLinkLogin({
|
|
197
|
+
...options,
|
|
198
|
+
challenge,
|
|
199
|
+
users,
|
|
200
|
+
crypto,
|
|
201
|
+
authFlow,
|
|
202
|
+
authMailer,
|
|
203
|
+
});
|
|
204
|
+
}));
|
|
205
|
+
export const MagicLinkFeatureLive = MagicLinkLoginLive;
|
|
206
|
+
//# sourceMappingURL=MagicLink.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MagicLink.js","sourceRoot":"","sources":["../src/MagicLink.ts"],"names":[],"mappings":"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"}
|
package/dist/Mailer.d.ts
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Redacted } from "effect";
|
|
2
|
+
import type { ChallengeId, Email, SessionId, UnixMillis, UserId } from "./Identifiers.js";
|
|
3
|
+
import type { LoginRequestContext } from "./LoginRisk.js";
|
|
4
|
+
export type EmailAddress = Email | {
|
|
5
|
+
readonly email: Email;
|
|
6
|
+
readonly name?: string;
|
|
7
|
+
};
|
|
8
|
+
export interface EmailMessage {
|
|
9
|
+
readonly from?: EmailAddress;
|
|
10
|
+
readonly to: EmailAddress | readonly EmailAddress[];
|
|
11
|
+
readonly cc?: EmailAddress | readonly EmailAddress[];
|
|
12
|
+
readonly bcc?: EmailAddress | readonly EmailAddress[];
|
|
13
|
+
readonly replyTo?: EmailAddress;
|
|
14
|
+
readonly subject: string;
|
|
15
|
+
readonly text?: string;
|
|
16
|
+
readonly html?: string;
|
|
17
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
18
|
+
}
|
|
19
|
+
declare const EmailSendError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
20
|
+
readonly _tag: "EmailSendError";
|
|
21
|
+
} & Readonly<A>;
|
|
22
|
+
export declare class EmailSendError extends EmailSendError_base<{
|
|
23
|
+
readonly provider?: string;
|
|
24
|
+
readonly message: string;
|
|
25
|
+
readonly cause?: unknown;
|
|
26
|
+
}> {
|
|
27
|
+
}
|
|
28
|
+
export interface MailerService {
|
|
29
|
+
readonly send: (message: EmailMessage) => Effect.Effect<void, EmailSendError>;
|
|
30
|
+
}
|
|
31
|
+
declare const Mailer_base: Context.ServiceClass<Mailer, "auth/Mailer", MailerService>;
|
|
32
|
+
export declare class Mailer extends Mailer_base {
|
|
33
|
+
}
|
|
34
|
+
export declare namespace Mailer {
|
|
35
|
+
const make: (service: MailerService) => MailerService;
|
|
36
|
+
}
|
|
37
|
+
export interface AuthEmailBase {
|
|
38
|
+
readonly to: Email;
|
|
39
|
+
readonly locale?: string;
|
|
40
|
+
readonly metadata?: Readonly<Record<string, unknown>>;
|
|
41
|
+
}
|
|
42
|
+
export interface AuthEmailOtp extends AuthEmailBase {
|
|
43
|
+
readonly _tag: "EmailOtp";
|
|
44
|
+
readonly challengeId: ChallengeId;
|
|
45
|
+
readonly secret: Redacted.Redacted<string>;
|
|
46
|
+
readonly expiresAt: UnixMillis;
|
|
47
|
+
}
|
|
48
|
+
export interface AuthMagicLinkEmail extends AuthEmailBase {
|
|
49
|
+
readonly _tag: "MagicLink";
|
|
50
|
+
readonly challengeId: ChallengeId;
|
|
51
|
+
readonly url: string;
|
|
52
|
+
readonly expiresAt: UnixMillis;
|
|
53
|
+
}
|
|
54
|
+
export interface AuthPasswordResetEmail extends AuthEmailBase {
|
|
55
|
+
readonly _tag: "PasswordReset";
|
|
56
|
+
readonly challengeId: ChallengeId;
|
|
57
|
+
readonly url: string;
|
|
58
|
+
readonly expiresAt: UnixMillis;
|
|
59
|
+
}
|
|
60
|
+
export interface AuthEmailVerificationEmail extends AuthEmailBase {
|
|
61
|
+
readonly _tag: "EmailVerification";
|
|
62
|
+
readonly challengeId: ChallengeId;
|
|
63
|
+
readonly userId?: UserId;
|
|
64
|
+
readonly secret?: Redacted.Redacted<string>;
|
|
65
|
+
readonly url?: string;
|
|
66
|
+
readonly expiresAt: UnixMillis;
|
|
67
|
+
}
|
|
68
|
+
export interface AuthLoginApprovalEmail extends AuthEmailBase {
|
|
69
|
+
readonly _tag: "LoginApproval";
|
|
70
|
+
readonly challengeId: ChallengeId;
|
|
71
|
+
readonly userId: UserId;
|
|
72
|
+
readonly secret?: Redacted.Redacted<string>;
|
|
73
|
+
readonly url?: string;
|
|
74
|
+
readonly expiresAt: UnixMillis;
|
|
75
|
+
readonly reason: string;
|
|
76
|
+
readonly sessionBinding: "originating-device" | "approval-device" | "none";
|
|
77
|
+
readonly sameDeviceRequired: boolean;
|
|
78
|
+
}
|
|
79
|
+
export interface AuthLoginNotificationEmail extends AuthEmailBase {
|
|
80
|
+
readonly _tag: "LoginNotification";
|
|
81
|
+
readonly userId: UserId;
|
|
82
|
+
readonly sessionId: SessionId;
|
|
83
|
+
readonly method: string;
|
|
84
|
+
readonly reason: string;
|
|
85
|
+
readonly deviceStatus: string;
|
|
86
|
+
readonly request?: LoginRequestContext;
|
|
87
|
+
readonly occurredAt: UnixMillis;
|
|
88
|
+
readonly reportChallengeId?: ChallengeId;
|
|
89
|
+
readonly reportUrl?: string;
|
|
90
|
+
readonly reportExpiresAt?: UnixMillis;
|
|
91
|
+
}
|
|
92
|
+
export type AuthEmail = AuthEmailOtp | AuthMagicLinkEmail | AuthPasswordResetEmail | AuthEmailVerificationEmail | AuthLoginApprovalEmail | AuthLoginNotificationEmail;
|
|
93
|
+
export interface RenderedEmail {
|
|
94
|
+
readonly from?: EmailAddress;
|
|
95
|
+
readonly subject: string;
|
|
96
|
+
readonly text?: string;
|
|
97
|
+
readonly html?: string;
|
|
98
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
99
|
+
}
|
|
100
|
+
declare const AuthEmailTemplateError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
101
|
+
readonly _tag: "AuthEmailTemplateError";
|
|
102
|
+
} & Readonly<A>;
|
|
103
|
+
export declare class AuthEmailTemplateError extends AuthEmailTemplateError_base<{
|
|
104
|
+
readonly message: string;
|
|
105
|
+
readonly cause?: unknown;
|
|
106
|
+
}> {
|
|
107
|
+
}
|
|
108
|
+
export interface AuthEmailTemplatesService {
|
|
109
|
+
readonly render: (input: AuthEmail) => Effect.Effect<RenderedEmail, AuthEmailTemplateError>;
|
|
110
|
+
}
|
|
111
|
+
declare const AuthEmailTemplates_base: Context.ServiceClass<AuthEmailTemplates, "auth/AuthEmailTemplates", AuthEmailTemplatesService>;
|
|
112
|
+
export declare class AuthEmailTemplates extends AuthEmailTemplates_base {
|
|
113
|
+
}
|
|
114
|
+
export declare namespace AuthEmailTemplates {
|
|
115
|
+
const make: (service: AuthEmailTemplatesService) => AuthEmailTemplatesService;
|
|
116
|
+
}
|
|
117
|
+
declare const AuthMailerError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("effect/Cause").YieldableError & {
|
|
118
|
+
readonly _tag: "AuthMailerError";
|
|
119
|
+
} & Readonly<A>;
|
|
120
|
+
export declare class AuthMailerError extends AuthMailerError_base<{
|
|
121
|
+
readonly message: string;
|
|
122
|
+
readonly cause?: unknown;
|
|
123
|
+
}> {
|
|
124
|
+
}
|
|
125
|
+
export interface AuthMailerService {
|
|
126
|
+
readonly send: (input: AuthEmail) => Effect.Effect<void, AuthMailerError>;
|
|
127
|
+
}
|
|
128
|
+
declare const AuthMailer_base: Context.ServiceClass<AuthMailer, "auth/AuthMailer", AuthMailerService>;
|
|
129
|
+
export declare class AuthMailer extends AuthMailer_base {
|
|
130
|
+
}
|
|
131
|
+
export declare namespace AuthMailer {
|
|
132
|
+
const make: (service: AuthMailerService) => AuthMailerService;
|
|
133
|
+
}
|
|
134
|
+
export interface AuthMailerOptions {
|
|
135
|
+
readonly from?: EmailAddress;
|
|
136
|
+
}
|
|
137
|
+
export interface AuthMailerDependencies extends AuthMailerOptions {
|
|
138
|
+
readonly mailer: MailerService;
|
|
139
|
+
readonly templates: AuthEmailTemplatesService;
|
|
140
|
+
}
|
|
141
|
+
export declare const makeDefaultAuthEmailTemplates: () => AuthEmailTemplatesService;
|
|
142
|
+
export declare const AuthEmailTemplatesLive: Layer.Layer<AuthEmailTemplates, never, never>;
|
|
143
|
+
export declare const makeAuthMailer: (dependencies: AuthMailerDependencies) => AuthMailerService;
|
|
144
|
+
export declare const AuthMailerLive: (options?: AuthMailerOptions) => Layer.Layer<AuthMailer, never, Mailer | AuthEmailTemplates>;
|
|
145
|
+
export declare const MailerNoopLive: Layer.Layer<Mailer, never, never>;
|
|
146
|
+
export {};
|
|
147
|
+
//# sourceMappingURL=Mailer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Mailer.d.ts","sourceRoot":"","sources":["../src/Mailer.ts"],"names":[],"mappings":"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"}
|