@ts-cloud/core 0.9.4 → 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.
- package/dist/app-mail.d.ts +130 -0
- package/dist/drivers/types.d.ts +29 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +404 -404
- package/dist/types.d.ts +283 -0
- package/package.json +2 -2
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import type { CloudConfig, EnvironmentType, MailServiceConfig, MailServiceMode } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* The one place that decides what "mail" means for an environment.
|
|
4
|
+
*
|
|
5
|
+
* `services.mail` is deliberately allowed to be `true`, because the useful
|
|
6
|
+
* declaration is "this project sends email" and not "this project runs an MTA
|
|
7
|
+
* on 25 with DKIM keys for two domains and a smarthost". Everything after that
|
|
8
|
+
* follows from the environment: production wants a real server, a preview box
|
|
9
|
+
* wants a trap. Both are the same binary, which is the point - see
|
|
10
|
+
* {@link MailServiceMode}.
|
|
11
|
+
*
|
|
12
|
+
* The provisioner, the firewall, the DNS planner and the `.env` writer all
|
|
13
|
+
* resolve through here so they cannot disagree about which ports are open,
|
|
14
|
+
* which hostname is announced, or where the webmail UI is. That mattered
|
|
15
|
+
* immediately: a catcher whose SMTP port the `.env` said was 1025 and whose
|
|
16
|
+
* firewall rule said 25 is a box where mail silently goes nowhere.
|
|
17
|
+
*/
|
|
18
|
+
/** Everything about the mail service, with nothing left to infer. */
|
|
19
|
+
export interface ResolvedMailService {
|
|
20
|
+
/** Whether mail is provisioned at all. */
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
/** Real MTA or local trap. */
|
|
23
|
+
mode: MailServiceMode;
|
|
24
|
+
/** Pinned version, or `undefined` for the latest release. */
|
|
25
|
+
version?: string;
|
|
26
|
+
/** The FQDN the server announces and signs as. */
|
|
27
|
+
hostname: string;
|
|
28
|
+
/** Every domain delivered to mailboxes here, `hostname`'s parent included. */
|
|
29
|
+
domains: string[];
|
|
30
|
+
/** Resolved listening ports; a port that is off is absent. */
|
|
31
|
+
ports: ResolvedMailPorts;
|
|
32
|
+
/** TLS, resolved. `acme` implies the server obtains its own certificate. */
|
|
33
|
+
tls: {
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
acme: boolean;
|
|
36
|
+
certPath?: string;
|
|
37
|
+
keyPath?: string;
|
|
38
|
+
requireForAuth: boolean;
|
|
39
|
+
acmeEmail?: string;
|
|
40
|
+
};
|
|
41
|
+
/** DKIM, resolved. Off means the server signs nothing. */
|
|
42
|
+
dkim: {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
selector: string;
|
|
45
|
+
rotate: boolean;
|
|
46
|
+
rotateIntervalDays: number;
|
|
47
|
+
};
|
|
48
|
+
/** Webmail UI, resolved. */
|
|
49
|
+
webmail: {
|
|
50
|
+
enabled: boolean;
|
|
51
|
+
port: number;
|
|
52
|
+
domain?: string;
|
|
53
|
+
};
|
|
54
|
+
/** How outbound mail leaves. */
|
|
55
|
+
delivery: 'direct' | 'ses' | 'none';
|
|
56
|
+
/** SES region for `delivery: 'ses'`. */
|
|
57
|
+
sesRegion: string;
|
|
58
|
+
/** Mailboxes created on provision. */
|
|
59
|
+
accounts: Array<{
|
|
60
|
+
address: string;
|
|
61
|
+
password: string;
|
|
62
|
+
}>;
|
|
63
|
+
/** Where mailboxes, the database and the DKIM keys live. */
|
|
64
|
+
storagePath: string;
|
|
65
|
+
/** Largest accepted message, in bytes. */
|
|
66
|
+
maxMessageSize: number;
|
|
67
|
+
/** Inbound spam handling, resolved. */
|
|
68
|
+
spam: {
|
|
69
|
+
enabled: boolean;
|
|
70
|
+
enforce: boolean;
|
|
71
|
+
junkScore: number;
|
|
72
|
+
rejectScore: number;
|
|
73
|
+
dnsbl: boolean;
|
|
74
|
+
greylist: boolean;
|
|
75
|
+
};
|
|
76
|
+
/** Where received mail is POSTed, when configured. */
|
|
77
|
+
webhookUrl?: string;
|
|
78
|
+
/** Whether the mail ports face the internet. */
|
|
79
|
+
expose: boolean;
|
|
80
|
+
/** The address the listeners bind to, which follows from {@link expose}. */
|
|
81
|
+
bindAddress: string;
|
|
82
|
+
}
|
|
83
|
+
/** Resolved ports. A protocol this mode does not serve is absent, not zero. */
|
|
84
|
+
export interface ResolvedMailPorts {
|
|
85
|
+
smtp: number;
|
|
86
|
+
submission?: number;
|
|
87
|
+
submissions?: number;
|
|
88
|
+
imap?: number;
|
|
89
|
+
imaps?: number;
|
|
90
|
+
webmail: number;
|
|
91
|
+
managesieve?: number;
|
|
92
|
+
}
|
|
93
|
+
/** Whether a `services.mail` declaration asks for anything at all. */
|
|
94
|
+
export declare function mailEnabled(value: boolean | MailServiceConfig | undefined): boolean;
|
|
95
|
+
export interface ResolveMailOptions {
|
|
96
|
+
/** Which environment is being provisioned, e.g. `'production'`. */
|
|
97
|
+
environment?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Its type, when the caller already knows it. Otherwise it is read from
|
|
100
|
+
* `config.environments[environment].type`, and an unknown environment is
|
|
101
|
+
* treated as non-production - which is the safe direction: the mistake that
|
|
102
|
+
* costs something is provisioning an open relay, not provisioning a trap.
|
|
103
|
+
*/
|
|
104
|
+
environmentType?: EnvironmentType;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Resolve `infrastructure.compute.managedServices.mail` for an environment.
|
|
108
|
+
*
|
|
109
|
+
* Returns `enabled: false` (and defaults everywhere else) when mail is not
|
|
110
|
+
* declared, so callers can read the shape unconditionally instead of guarding
|
|
111
|
+
* every field.
|
|
112
|
+
*/
|
|
113
|
+
export declare function resolveMailService(config: Pick<CloudConfig, 'project' | 'sites' | 'environments' | 'infrastructure'>, options?: ResolveMailOptions): ResolvedMailService;
|
|
114
|
+
/**
|
|
115
|
+
* The ports the host firewall has to open for this mail service.
|
|
116
|
+
*
|
|
117
|
+
* Empty when mail is not exposed, which is the whole reason this is a function
|
|
118
|
+
* rather than a list somebody maintains beside the resolver: a catcher's ports
|
|
119
|
+
* must never end up in an allow list.
|
|
120
|
+
*/
|
|
121
|
+
export declare function mailFirewallPorts(mail: ResolvedMailService): number[];
|
|
122
|
+
/**
|
|
123
|
+
* `.env` pairs pointing an application at this mail service, in the shape the
|
|
124
|
+
* Stacks/Laravel families of framework read.
|
|
125
|
+
*
|
|
126
|
+
* Merge into a site's `env` so `MAIL_*` is set from the same resolution the
|
|
127
|
+
* provisioner used. The alternative - a hand-copied `MAIL_PORT` - is the
|
|
128
|
+
* mistake this whole module exists to make impossible.
|
|
129
|
+
*/
|
|
130
|
+
export declare function buildMailEnv(mail: ResolvedMailService): Record<string, string>;
|
package/dist/drivers/types.d.ts
CHANGED
|
@@ -119,6 +119,35 @@ export interface CloudDriver {
|
|
|
119
119
|
findComputeTargets(options: FindComputeTargetsOptions): Promise<ComputeTarget[]>;
|
|
120
120
|
/** Run a shell script on every target (SSM, SSH, etc.) */
|
|
121
121
|
runRemoteDeploy(options: RunRemoteDeployOptions): Promise<RemoteDeployResult>;
|
|
122
|
+
/**
|
|
123
|
+
* Enumerate every resource this driver's credential can see — and therefore,
|
|
124
|
+
* on providers without per-resource scoping, write to and delete.
|
|
125
|
+
*
|
|
126
|
+
* Exists so nothing above the driver has to assume "one all-powerful token"
|
|
127
|
+
* is the only credential shape. Attaching to another project's box works by
|
|
128
|
+
* LISTING the provider with the attaching project's own credential, so the
|
|
129
|
+
* radius is a property of that credential rather than of the config, and only
|
|
130
|
+
* the driver holding it can report it. A driver whose credential IS narrowly
|
|
131
|
+
* scoped simply enumerates less, and the same reporting comes out right
|
|
132
|
+
* without a special case.
|
|
133
|
+
*
|
|
134
|
+
* Optional: a driver that cannot enumerate omits it, and callers report no
|
|
135
|
+
* radius rather than a wrong one.
|
|
136
|
+
*
|
|
137
|
+
* @see https://github.com/stacksjs/ts-cloud/issues/169
|
|
138
|
+
*/
|
|
139
|
+
listReachableResources?(): Promise<ReachableResource[]>;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* One resource a provider credential can reach, reduced to what attribution
|
|
143
|
+
* needs: a name to print and the labels that say who owns it.
|
|
144
|
+
*
|
|
145
|
+
* Deliberately structural and provider-agnostic — a Hetzner server satisfies it
|
|
146
|
+
* as-is, and another driver can satisfy it without importing anything.
|
|
147
|
+
*/
|
|
148
|
+
export interface ReachableResource {
|
|
149
|
+
name: string;
|
|
150
|
+
labels?: Record<string, string>;
|
|
122
151
|
}
|
|
123
152
|
export interface DeploySiteReleaseOptions {
|
|
124
153
|
config: CloudConfig;
|
package/dist/index.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ export * from './types';
|
|
|
5
5
|
export * from './state-dir';
|
|
6
6
|
export * from './deployment-mode';
|
|
7
7
|
export * from './app-database';
|
|
8
|
+
export * from './app-mail';
|
|
8
9
|
export * from './drivers';
|
|
9
10
|
export * from './template-builder';
|
|
10
11
|
export { validateTemplate, validateTemplateSize, validateResourceLimits, type ValidationResult, } from './template-validator';
|