@aurabase/functions 0.5.2 → 0.5.4
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 +19 -6
- package/dist/index.cjs +65 -1
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +65 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -144,6 +144,14 @@ const { data: parNom } = await aura.functions.get('hello-world')
|
|
|
144
144
|
### Jobs asynchrones (extra vs `@supabase/functions-js`)
|
|
145
145
|
|
|
146
146
|
```ts
|
|
147
|
+
// Enfiler un nouveau job d'exécution en arrière-plan
|
|
148
|
+
const { data: jobInfo, error } = await aura.functions.enqueueJob('generate-report', {
|
|
149
|
+
payload: { month: '2026-10', sendEmail: true },
|
|
150
|
+
maxAttempts: 3,
|
|
151
|
+
delaySecs: 60, // exécuter dans 60 secondes
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
// Consulter les jobs
|
|
147
155
|
const { data: jobs } = await aura.functions.listJobs({ status: 'pending', limit: 20 })
|
|
148
156
|
const { data: job } = await aura.functions.getJob(jobs![0]!.id)
|
|
149
157
|
```
|
|
@@ -159,14 +167,19 @@ const { data: crons } = await aura.functions.listCronJobs()
|
|
|
159
167
|
await aura.functions.deleteCronJob('nightly-cleanup')
|
|
160
168
|
```
|
|
161
169
|
|
|
170
|
+
## Contrat d'invocation et comportement des erreurs
|
|
171
|
+
|
|
172
|
+
- **Déballage transparent :** En mode `responseType: 'json'` (défaut), `data` contient directement le type attendu `T` renvoyé par votre fonction. Pour préserver la compatibilité avec le code existant lisant l'enveloppe, les propriétés `status` et `body` restent accessibles sur l'objet retourné.
|
|
173
|
+
- **Propagation des erreurs HTTP applicatives :** Si votre fonction répond avec un statut HTTP $\ge 400$, le SDK lève désormais une `FunctionsHttpError` avec le statut réel de votre fonction (`error.status`) et son message d'erreur, même lorsque le transport réseau sous-jacent utilise une enveloppe.
|
|
174
|
+
- **Relais et disponibilité :** En cas d'indisponibilité du runtime ou de coupure réseau, une `FunctionsRelayError` est renvoyée.
|
|
175
|
+
- **Propagation d'identité sécurisée :** Les en-têtes d'autorisation (`Authorization: Bearer <token>`, `apikey`) sont validés par la passerelle Aurabase et propagés de façon étanche vers le worker de la fonction (`x-aura-user-id`, `x-aura-role`), protégeant votre backend contre toute falsification client.
|
|
176
|
+
|
|
162
177
|
## Limitations
|
|
163
178
|
|
|
164
|
-
- Pas de streaming de réponse : `invoke()` bufferise
|
|
165
|
-
- Pas de sélection de région d'exécution.
|
|
166
|
-
-
|
|
167
|
-
-
|
|
168
|
-
- Pas de `getCronJob()` ni `updateCronJob()` : seuls `listCronJobs`, `createCronJob` et `deleteCronJob` sont exposés. Pas de `deploy()` / `delete()` de fonction depuis le SDK : le déploiement passe par l'API HTTP, la CLI `aura functions deploy` ou le Studio.
|
|
169
|
-
- `deleteCronJob(name)` et les routes `PATCH`/`DELETE`/`invoke` d'une fonction attendent un **nom** ; seul `get()` accepte aussi l'identifiant.
|
|
179
|
+
- Pas de streaming de réponse : `invoke()` bufferise l'intégralité du corps avant de résoudre. `responseType` configure le décodage du corps (`json`, `text`, `blob`, `arrayBuffer`).
|
|
180
|
+
- Pas de sélection de région d'exécution (exécution sur le cluster Edge actif).
|
|
181
|
+
- Les en-têtes de cadrage de transport (`content-length`, `connection`, `host`, etc.) ne sont pas transmissibles à la fonction.
|
|
182
|
+
- Pas de `getCronJob()` ni `updateCronJob()` : seuls `listCronJobs`, `createCronJob` et `deleteCronJob` sont exposés. Le déploiement s'effectue via le CLI `aura functions deploy` ou Aurabase Studio.
|
|
170
183
|
|
|
171
184
|
## Documentation
|
|
172
185
|
|
package/dist/index.cjs
CHANGED
|
@@ -27,7 +27,7 @@ var FunctionsRelayError = class _FunctionsRelayError extends core.AuraError {
|
|
|
27
27
|
};
|
|
28
28
|
function toFunctionsError(err, context) {
|
|
29
29
|
const body = err.details != null ? err.details : { error: { code: err.code, message: err.message } };
|
|
30
|
-
return isRelayStatus(err.status) ? new FunctionsRelayError(err.status, body, err.details) : new FunctionsHttpError(err.status, body, err.details);
|
|
30
|
+
return isRelayStatus(err.status) ? new FunctionsRelayError(err.status, body, context ?? err.details) : new FunctionsHttpError(err.status, body, context ?? err.details);
|
|
31
31
|
}
|
|
32
32
|
var FunctionsService = class extends core.BaseService {
|
|
33
33
|
constructor(client) {
|
|
@@ -108,6 +108,47 @@ var FunctionsService = class extends core.BaseService {
|
|
|
108
108
|
});
|
|
109
109
|
if (res2.error && controller.signal.aborted) return timeoutError();
|
|
110
110
|
if (res2.error) return { data: null, error: toFunctionsError(res2.error) };
|
|
111
|
+
const rawData = res2.data;
|
|
112
|
+
if (rawData && typeof rawData === "object" && "body" in rawData && "status" in rawData) {
|
|
113
|
+
const invokeStatus = rawData.status;
|
|
114
|
+
const invokeBody = rawData.body;
|
|
115
|
+
if (typeof invokeStatus === "number" && invokeStatus >= 400) {
|
|
116
|
+
const errPayload = typeof invokeBody === "object" && invokeBody !== null ? invokeBody : { message: String(invokeBody) };
|
|
117
|
+
const errorMsg = typeof errPayload.message === "string" ? errPayload.message : typeof errPayload.error === "string" ? errPayload.error : typeof errPayload.error?.message === "string" ? String(errPayload.error.message) : `Function returned HTTP ${invokeStatus}`;
|
|
118
|
+
const normalizedBody = {
|
|
119
|
+
...errPayload,
|
|
120
|
+
message: errorMsg,
|
|
121
|
+
error: {
|
|
122
|
+
code: typeof errPayload.code === "string" ? errPayload.code : `http_${invokeStatus}`,
|
|
123
|
+
message: errorMsg
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
return {
|
|
127
|
+
data: null,
|
|
128
|
+
error: toFunctionsError(new core.AuraError(invokeStatus, normalizedBody), invokeBody)
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
let unwrappedData = invokeBody;
|
|
132
|
+
if (unwrappedData !== null && typeof unwrappedData === "object") {
|
|
133
|
+
if (!("body" in unwrappedData)) {
|
|
134
|
+
Object.defineProperty(unwrappedData, "body", {
|
|
135
|
+
value: unwrappedData,
|
|
136
|
+
enumerable: false,
|
|
137
|
+
writable: true,
|
|
138
|
+
configurable: true
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (!("status" in unwrappedData)) {
|
|
142
|
+
Object.defineProperty(unwrappedData, "status", {
|
|
143
|
+
value: invokeStatus,
|
|
144
|
+
enumerable: false,
|
|
145
|
+
writable: true,
|
|
146
|
+
configurable: true
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return { data: unwrappedData, error: null, meta: res2.meta };
|
|
151
|
+
}
|
|
111
152
|
return res2;
|
|
112
153
|
}
|
|
113
154
|
const client = this.client;
|
|
@@ -184,6 +225,29 @@ var FunctionsService = class extends core.BaseService {
|
|
|
184
225
|
async getJob(jobId) {
|
|
185
226
|
return this.request("GET", `${this.prefix}/jobs/${jobId}`);
|
|
186
227
|
}
|
|
228
|
+
/**
|
|
229
|
+
* Enfile un job d'exécution asynchrone en arrière-plan pour une fonction.
|
|
230
|
+
*
|
|
231
|
+
* @param functionName Nom de la fonction à exécuter.
|
|
232
|
+
* @param options Paramètres optionnels : charge utile (`payload`), délai avant exécution (`delaySecs`)
|
|
233
|
+
* et nombre maximum de tentatives (`maxAttempts`).
|
|
234
|
+
*/
|
|
235
|
+
async enqueueJob(functionName, options) {
|
|
236
|
+
if (!functionName || typeof functionName !== "string" || functionName.trim() === "") {
|
|
237
|
+
return {
|
|
238
|
+
data: null,
|
|
239
|
+
error: new core.AuraError(400, {
|
|
240
|
+
error: { code: "bad_request", message: "Function name is required to enqueue a job" }
|
|
241
|
+
})
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
return this.request("POST", `${this.prefix}/jobs`, {
|
|
245
|
+
function_name: functionName.trim(),
|
|
246
|
+
payload: options?.payload,
|
|
247
|
+
delay_secs: options?.delaySecs,
|
|
248
|
+
max_attempts: options?.maxAttempts
|
|
249
|
+
});
|
|
250
|
+
}
|
|
187
251
|
// -- Cron -------------------------------------------------------------------
|
|
188
252
|
async listCronJobs() {
|
|
189
253
|
return this.request("GET", `${this.prefix}/cron`);
|
package/dist/index.d.cts
CHANGED
|
@@ -98,6 +98,18 @@ declare class FunctionsService extends BaseService {
|
|
|
98
98
|
limit?: number;
|
|
99
99
|
}): Promise<AuraResponse<Job[]>>;
|
|
100
100
|
getJob(jobId: string): Promise<AuraResponse<Job>>;
|
|
101
|
+
/**
|
|
102
|
+
* Enfile un job d'exécution asynchrone en arrière-plan pour une fonction.
|
|
103
|
+
*
|
|
104
|
+
* @param functionName Nom de la fonction à exécuter.
|
|
105
|
+
* @param options Paramètres optionnels : charge utile (`payload`), délai avant exécution (`delaySecs`)
|
|
106
|
+
* et nombre maximum de tentatives (`maxAttempts`).
|
|
107
|
+
*/
|
|
108
|
+
enqueueJob(functionName: string, options?: {
|
|
109
|
+
payload?: unknown;
|
|
110
|
+
delaySecs?: number;
|
|
111
|
+
maxAttempts?: number;
|
|
112
|
+
}): Promise<AuraResponse<Job>>;
|
|
101
113
|
listCronJobs(): Promise<AuraResponse<CronJob[]>>;
|
|
102
114
|
createCronJob(name: string, schedule: string, functionName: string, options?: {
|
|
103
115
|
payload?: unknown;
|
package/dist/index.d.ts
CHANGED
|
@@ -98,6 +98,18 @@ declare class FunctionsService extends BaseService {
|
|
|
98
98
|
limit?: number;
|
|
99
99
|
}): Promise<AuraResponse<Job[]>>;
|
|
100
100
|
getJob(jobId: string): Promise<AuraResponse<Job>>;
|
|
101
|
+
/**
|
|
102
|
+
* Enfile un job d'exécution asynchrone en arrière-plan pour une fonction.
|
|
103
|
+
*
|
|
104
|
+
* @param functionName Nom de la fonction à exécuter.
|
|
105
|
+
* @param options Paramètres optionnels : charge utile (`payload`), délai avant exécution (`delaySecs`)
|
|
106
|
+
* et nombre maximum de tentatives (`maxAttempts`).
|
|
107
|
+
*/
|
|
108
|
+
enqueueJob(functionName: string, options?: {
|
|
109
|
+
payload?: unknown;
|
|
110
|
+
delaySecs?: number;
|
|
111
|
+
maxAttempts?: number;
|
|
112
|
+
}): Promise<AuraResponse<Job>>;
|
|
101
113
|
listCronJobs(): Promise<AuraResponse<CronJob[]>>;
|
|
102
114
|
createCronJob(name: string, schedule: string, functionName: string, options?: {
|
|
103
115
|
payload?: unknown;
|
package/dist/index.js
CHANGED
|
@@ -25,7 +25,7 @@ var FunctionsRelayError = class _FunctionsRelayError extends AuraError {
|
|
|
25
25
|
};
|
|
26
26
|
function toFunctionsError(err, context) {
|
|
27
27
|
const body = err.details != null ? err.details : { error: { code: err.code, message: err.message } };
|
|
28
|
-
return isRelayStatus(err.status) ? new FunctionsRelayError(err.status, body, err.details) : new FunctionsHttpError(err.status, body, err.details);
|
|
28
|
+
return isRelayStatus(err.status) ? new FunctionsRelayError(err.status, body, context ?? err.details) : new FunctionsHttpError(err.status, body, context ?? err.details);
|
|
29
29
|
}
|
|
30
30
|
var FunctionsService = class extends BaseService {
|
|
31
31
|
constructor(client) {
|
|
@@ -106,6 +106,47 @@ var FunctionsService = class extends BaseService {
|
|
|
106
106
|
});
|
|
107
107
|
if (res2.error && controller.signal.aborted) return timeoutError();
|
|
108
108
|
if (res2.error) return { data: null, error: toFunctionsError(res2.error) };
|
|
109
|
+
const rawData = res2.data;
|
|
110
|
+
if (rawData && typeof rawData === "object" && "body" in rawData && "status" in rawData) {
|
|
111
|
+
const invokeStatus = rawData.status;
|
|
112
|
+
const invokeBody = rawData.body;
|
|
113
|
+
if (typeof invokeStatus === "number" && invokeStatus >= 400) {
|
|
114
|
+
const errPayload = typeof invokeBody === "object" && invokeBody !== null ? invokeBody : { message: String(invokeBody) };
|
|
115
|
+
const errorMsg = typeof errPayload.message === "string" ? errPayload.message : typeof errPayload.error === "string" ? errPayload.error : typeof errPayload.error?.message === "string" ? String(errPayload.error.message) : `Function returned HTTP ${invokeStatus}`;
|
|
116
|
+
const normalizedBody = {
|
|
117
|
+
...errPayload,
|
|
118
|
+
message: errorMsg,
|
|
119
|
+
error: {
|
|
120
|
+
code: typeof errPayload.code === "string" ? errPayload.code : `http_${invokeStatus}`,
|
|
121
|
+
message: errorMsg
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
return {
|
|
125
|
+
data: null,
|
|
126
|
+
error: toFunctionsError(new AuraError(invokeStatus, normalizedBody), invokeBody)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
let unwrappedData = invokeBody;
|
|
130
|
+
if (unwrappedData !== null && typeof unwrappedData === "object") {
|
|
131
|
+
if (!("body" in unwrappedData)) {
|
|
132
|
+
Object.defineProperty(unwrappedData, "body", {
|
|
133
|
+
value: unwrappedData,
|
|
134
|
+
enumerable: false,
|
|
135
|
+
writable: true,
|
|
136
|
+
configurable: true
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
if (!("status" in unwrappedData)) {
|
|
140
|
+
Object.defineProperty(unwrappedData, "status", {
|
|
141
|
+
value: invokeStatus,
|
|
142
|
+
enumerable: false,
|
|
143
|
+
writable: true,
|
|
144
|
+
configurable: true
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return { data: unwrappedData, error: null, meta: res2.meta };
|
|
149
|
+
}
|
|
109
150
|
return res2;
|
|
110
151
|
}
|
|
111
152
|
const client = this.client;
|
|
@@ -182,6 +223,29 @@ var FunctionsService = class extends BaseService {
|
|
|
182
223
|
async getJob(jobId) {
|
|
183
224
|
return this.request("GET", `${this.prefix}/jobs/${jobId}`);
|
|
184
225
|
}
|
|
226
|
+
/**
|
|
227
|
+
* Enfile un job d'exécution asynchrone en arrière-plan pour une fonction.
|
|
228
|
+
*
|
|
229
|
+
* @param functionName Nom de la fonction à exécuter.
|
|
230
|
+
* @param options Paramètres optionnels : charge utile (`payload`), délai avant exécution (`delaySecs`)
|
|
231
|
+
* et nombre maximum de tentatives (`maxAttempts`).
|
|
232
|
+
*/
|
|
233
|
+
async enqueueJob(functionName, options) {
|
|
234
|
+
if (!functionName || typeof functionName !== "string" || functionName.trim() === "") {
|
|
235
|
+
return {
|
|
236
|
+
data: null,
|
|
237
|
+
error: new AuraError(400, {
|
|
238
|
+
error: { code: "bad_request", message: "Function name is required to enqueue a job" }
|
|
239
|
+
})
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
return this.request("POST", `${this.prefix}/jobs`, {
|
|
243
|
+
function_name: functionName.trim(),
|
|
244
|
+
payload: options?.payload,
|
|
245
|
+
delay_secs: options?.delaySecs,
|
|
246
|
+
max_attempts: options?.maxAttempts
|
|
247
|
+
});
|
|
248
|
+
}
|
|
185
249
|
// -- Cron -------------------------------------------------------------------
|
|
186
250
|
async listCronJobs() {
|
|
187
251
|
return this.request("GET", `${this.prefix}/cron`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aurabase/functions",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.4",
|
|
4
4
|
"description": "Service edge functions du SDK Aurabase (invoke, jobs asynchrones, cron)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"functions"
|
|
46
46
|
],
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@aurabase/core": "0.5.
|
|
48
|
+
"@aurabase/core": "0.5.4"
|
|
49
49
|
},
|
|
50
50
|
"devDependencies": {
|
|
51
51
|
"@types/node": "20.14.15",
|