arcane-os 0.17.0 → 0.19.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/CHANGELOG.md +30 -0
- package/NOTICE +1 -1
- package/README.md +1 -1
- package/docs/architecture.md +4 -2
- package/docs/reference/cli.md +45 -16
- package/docs/reference/mail.md +72 -15
- package/docs/reference/sdk-api.md +11 -6
- package/docs/reviews/mail-server-purpose-review.md +49 -6
- package/package.json +2 -2
- package/src/cli/main.mjs +16 -17
- package/src/mail-credentials.mjs +101 -632
- package/src/mail-server.mjs +9 -0
- package/src/mail.mjs +17 -26
- package/src/templates/workspace-template.mjs +1 -0
package/src/mail-server.mjs
CHANGED
|
@@ -1033,6 +1033,15 @@ export async function startResendMailServer(options={}){
|
|
|
1033
1033
|
server=await listenForMailRequests(mailServer);
|
|
1034
1034
|
}catch(error){
|
|
1035
1035
|
await Promise.allSettled([mailServer.close(),requestHandler.close()]);
|
|
1036
|
+
if (error?.code === 'EADDRINUSE') {
|
|
1037
|
+
throw Object.assign(
|
|
1038
|
+
new Error(
|
|
1039
|
+
`Mail port ${configuration.port} is already taken, possibly by another mail server.`,
|
|
1040
|
+
{cause:error}
|
|
1041
|
+
),
|
|
1042
|
+
error
|
|
1043
|
+
);
|
|
1044
|
+
}
|
|
1036
1045
|
throw error;
|
|
1037
1046
|
}
|
|
1038
1047
|
const address=server.address();
|
package/src/mail.mjs
CHANGED
|
@@ -3,6 +3,7 @@ import {ArcaneError,ERROR_CODES,throwIfAborted} from './errors.mjs';
|
|
|
3
3
|
import {
|
|
4
4
|
deleteMailCredential,
|
|
5
5
|
getMailCredentialStatus,
|
|
6
|
+
mailCredentialLocation,
|
|
6
7
|
readMailCredential,
|
|
7
8
|
setMailCredential
|
|
8
9
|
} from './mail-credentials.mjs';
|
|
@@ -54,13 +55,9 @@ function mailRecipientOptions(value,label){
|
|
|
54
55
|
function mailCredentialOptions(options){
|
|
55
56
|
return {
|
|
56
57
|
profile:options.profile,
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
spawnImpl:options.spawnImpl,
|
|
61
|
-
runner:options.credentialRunner,
|
|
62
|
-
signal:options.signal,
|
|
63
|
-
timeoutMs:options.credentialTimeoutMs
|
|
58
|
+
cwd:options.cwd,
|
|
59
|
+
workspaceRoot:options.workspaceRoot,
|
|
60
|
+
signal:options.signal
|
|
64
61
|
};
|
|
65
62
|
}
|
|
66
63
|
|
|
@@ -92,24 +89,11 @@ async function deleteMailCredentialProfile(options){
|
|
|
92
89
|
|
|
93
90
|
async function sendMailFromReport(options){
|
|
94
91
|
const readReport=resolveMailCommandDependency(options,'readReport',null);
|
|
95
|
-
const readCredential=resolveMailCommandDependency(options,'readCredential',readMailCredential);
|
|
96
92
|
const send=resolveMailCommandDependency(options,'sendMail',sendResendMail);
|
|
97
93
|
throwIfAborted(options.signal);
|
|
98
94
|
const report=await readReport();
|
|
99
95
|
throwIfAborted(options.signal);
|
|
100
|
-
let apiKey=await
|
|
101
|
-
if(apiKey===null){
|
|
102
|
-
throw new ArcaneError(
|
|
103
|
-
ERROR_CODES.prerequisiteMissing,
|
|
104
|
-
`No Resend credential is configured for profile ${String(options.profile)}.`
|
|
105
|
-
);
|
|
106
|
-
}
|
|
107
|
-
if(!is.string(apiKey)||!apiKey){
|
|
108
|
-
throw new ArcaneError(
|
|
109
|
-
ERROR_CODES.operationFailed,
|
|
110
|
-
'The configured Resend credential could not be read.'
|
|
111
|
-
);
|
|
112
|
-
}
|
|
96
|
+
let apiKey=await readMailProviderKey(options);
|
|
113
97
|
try{
|
|
114
98
|
throwIfAborted(options.signal);
|
|
115
99
|
const result=await send({
|
|
@@ -141,15 +125,15 @@ async function sendMailFromReport(options){
|
|
|
141
125
|
}
|
|
142
126
|
}
|
|
143
127
|
|
|
144
|
-
async function
|
|
128
|
+
async function readMailProviderKey(options){
|
|
145
129
|
const readCredential=resolveMailCommandDependency(options,'readCredential',readMailCredential);
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
let apiKey=await readCredential(mailCredentialOptions(options));
|
|
130
|
+
const credentialOptions=mailCredentialOptions(options);
|
|
131
|
+
const apiKey=await readCredential(credentialOptions);
|
|
149
132
|
if(apiKey===null){
|
|
133
|
+
const location=mailCredentialLocation(credentialOptions);
|
|
150
134
|
throw new ArcaneError(
|
|
151
135
|
ERROR_CODES.prerequisiteMissing,
|
|
152
|
-
`
|
|
136
|
+
`Missing ${location.setting} in ${location.filePath}.`
|
|
153
137
|
);
|
|
154
138
|
}
|
|
155
139
|
if(!is.string(apiKey)||!apiKey){
|
|
@@ -158,6 +142,13 @@ async function serveMailGateway(options){
|
|
|
158
142
|
'The configured Resend credential could not be read.'
|
|
159
143
|
);
|
|
160
144
|
}
|
|
145
|
+
return apiKey;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async function serveMailGateway(options){
|
|
149
|
+
const startServer=resolveMailCommandDependency(options,'startServer',startResendMailServer);
|
|
150
|
+
throwIfAborted(options.signal);
|
|
151
|
+
let apiKey=await readMailProviderKey(options);
|
|
161
152
|
try{
|
|
162
153
|
throwIfAborted(options.signal);
|
|
163
154
|
const recipientAllowlist=mailRecipientOptions(options.allowTo,'allowTo');
|