@tthr/vue 0.0.61 → 0.0.63
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.
|
@@ -126,6 +126,9 @@ async function reportExecution(config, trigger, result, durationMs) {
|
|
|
126
126
|
* Execute a function via the Tether API
|
|
127
127
|
* This is used when no local handler is registered - the function is executed
|
|
128
128
|
* on the Tether server which has access to the database and environment.
|
|
129
|
+
*
|
|
130
|
+
* Tries endpoints in order based on functionType hint, with fallback to other
|
|
131
|
+
* types if the first attempt fails with a type mismatch error.
|
|
129
132
|
*/
|
|
130
133
|
async function executeViaApi(config, functionName, functionType, args) {
|
|
131
134
|
const base = config.url.replace(/\/$/, '');
|
|
@@ -137,32 +140,56 @@ async function executeViaApi(config, functionName, functionType, args) {
|
|
|
137
140
|
else {
|
|
138
141
|
apiPath = `${base}/api/v1/projects/${config.projectId}`;
|
|
139
142
|
}
|
|
140
|
-
//
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
endpoint = `${apiPath}/mutation`;
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
// Default to action endpoint for actions and unknown types
|
|
150
|
-
endpoint = `${apiPath}/action`;
|
|
143
|
+
// Order endpoints to try based on functionType hint
|
|
144
|
+
const endpointTypes = ['action', 'mutation', 'query'];
|
|
145
|
+
// Move the hinted type to the front if valid
|
|
146
|
+
if (functionType && endpointTypes.includes(functionType)) {
|
|
147
|
+
endpointTypes.splice(endpointTypes.indexOf(functionType), 1);
|
|
148
|
+
endpointTypes.unshift(functionType);
|
|
151
149
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
150
|
+
let lastError = null;
|
|
151
|
+
for (const type of endpointTypes) {
|
|
152
|
+
const endpoint = `${apiPath}/${type}`;
|
|
153
|
+
try {
|
|
154
|
+
const response = await fetch(endpoint, {
|
|
155
|
+
method: 'POST',
|
|
156
|
+
headers: {
|
|
157
|
+
'Content-Type': 'application/json',
|
|
158
|
+
'Authorization': `Bearer ${config.apiKey}`,
|
|
159
|
+
},
|
|
160
|
+
body: JSON.stringify({ function: functionName, args }),
|
|
161
|
+
});
|
|
162
|
+
if (!response.ok) {
|
|
163
|
+
const responseText = await response.text();
|
|
164
|
+
let errorMsg;
|
|
165
|
+
try {
|
|
166
|
+
const error = JSON.parse(responseText);
|
|
167
|
+
errorMsg = error.error || error.message || `Function '${functionName}' failed with status ${response.status}`;
|
|
168
|
+
} catch {
|
|
169
|
+
errorMsg = responseText || `Function '${functionName}' failed with status ${response.status}`;
|
|
170
|
+
}
|
|
171
|
+
log.debug(`/${type} endpoint returned ${response.status}: ${errorMsg}`);
|
|
172
|
+
// If it's a type mismatch error, try the next endpoint
|
|
173
|
+
if (errorMsg.includes('not a') && errorMsg.includes("it's a")) {
|
|
174
|
+
log.debug(`Function type mismatch on /${type}, trying next endpoint...`);
|
|
175
|
+
lastError = new Error(errorMsg);
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
throw new Error(errorMsg);
|
|
179
|
+
}
|
|
180
|
+
const result = await response.json();
|
|
181
|
+
return result.data;
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (error instanceof Error && error.message.includes('not a') && error.message.includes("it's a")) {
|
|
185
|
+
lastError = error;
|
|
186
|
+
continue;
|
|
187
|
+
}
|
|
188
|
+
throw error;
|
|
189
|
+
}
|
|
163
190
|
}
|
|
164
|
-
|
|
165
|
-
|
|
191
|
+
// All endpoints failed
|
|
192
|
+
throw lastError || new Error(`Function '${functionName}' failed on all endpoints`);
|
|
166
193
|
}
|
|
167
194
|
async function handleCronTrigger(config, trigger) {
|
|
168
195
|
log.info(`Received trigger for ${trigger.functionName} (execution: ${trigger.executionId})`);
|