@tthr/vue 0.0.61 → 0.0.62
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,49 @@ 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`;
|
|
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);
|
|
147
149
|
}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
endpoint = `${apiPath}
|
|
151
|
-
|
|
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 error = await response.json().catch(() => ({ error: 'Unknown error' }));
|
|
164
|
+
const errorMsg = error.error || `Function '${functionName}' failed with status ${response.status}`;
|
|
165
|
+
// If it's a type mismatch error, try the next endpoint
|
|
166
|
+
if (errorMsg.includes('not a') && errorMsg.includes("it's a")) {
|
|
167
|
+
log.debug(`Function type mismatch on /${type}, trying next endpoint...`);
|
|
168
|
+
lastError = new Error(errorMsg);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
throw new Error(errorMsg);
|
|
172
|
+
}
|
|
173
|
+
const result = await response.json();
|
|
174
|
+
return result.data;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
if (error instanceof Error && error.message.includes('not a') && error.message.includes("it's a")) {
|
|
178
|
+
lastError = error;
|
|
179
|
+
continue;
|
|
180
|
+
}
|
|
181
|
+
throw error;
|
|
182
|
+
}
|
|
163
183
|
}
|
|
164
|
-
|
|
165
|
-
|
|
184
|
+
// All endpoints failed
|
|
185
|
+
throw lastError || new Error(`Function '${functionName}' failed on all endpoints`);
|
|
166
186
|
}
|
|
167
187
|
async function handleCronTrigger(config, trigger) {
|
|
168
188
|
log.info(`Received trigger for ${trigger.functionName} (execution: ${trigger.executionId})`);
|