Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Change Log

## 29.2.0

* Added: optional `interval` parameter on `functions.create` and `functions.update` to run a function every N minutes
* Added: `interval` on the `Function` model and `functionsIntervalMinimum` on the `BillingPlan` model

## 29.1.0

* Added: optional `state` parameter on `createOAuth2Token`, returned unchanged on the success and failure URLs
Expand Down
1 change: 1 addition & 0 deletions docs/examples/functions/create.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ const result = await functions.create({
buildSpecification: 's-1vcpu-512mb', // optional
runtimeSpecification: 's-1vcpu-512mb', // optional
deploymentRetention: 0, // optional
interval: 0, // optional

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Examples combine mutually exclusive scheduling fields

This example still sets schedule to a CRON expression above, so copying it sends schedule together with interval: 0, which the API documentation says cannot be combined. The update example has the same conflict; please show only one scheduling option in each example.

Prompt To Fix With AI
This is a comment left during a code review.
Path: docs/examples/functions/create.md
Line: 34

Comment:
**Examples combine mutually exclusive scheduling fields**

This example still sets `schedule` to a CRON expression above, so copying it sends `schedule` together with `interval: 0`, which the API documentation says cannot be combined. The update example has the same conflict; please show only one scheduling option in each example.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

🟡 Minor · documentation · Reply if this doesn't apply.

});
```
1 change: 1 addition & 0 deletions docs/examples/functions/update.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ const result = await functions.update({
buildSpecification: 's-1vcpu-512mb', // optional
runtimeSpecification: 's-1vcpu-512mb', // optional
deploymentRetention: 0, // optional
interval: 0, // optional
});
```
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "node-appwrite",
"homepage": "https://appwrite.io/support",
"description": "Appwrite is an open-source self-hosted backend server that abstracts and simplifies complex and repetitive development tasks behind a very simple REST API",
"version": "29.1.0",
"version": "29.2.0",
"license": "BSD-3-Clause",
"main": "dist/index.js",
"type": "commonjs",
Expand Down
4 changes: 2 additions & 2 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class AppwriteException extends Error {
}

function getUserAgent() {
let ua = 'AppwriteNodeJSSDK/29.1.0';
let ua = 'AppwriteNodeJSSDK/29.2.0';

// `process` is a global in Node.js, but not fully available in all runtimes.
const platform: string[] = [];
Expand Down Expand Up @@ -142,7 +142,7 @@ class Client {
'x-sdk-name': 'Node.js',
'x-sdk-platform': 'server',
'x-sdk-language': 'nodejs',
'x-sdk-version': '29.1.0',
'x-sdk-version': '29.2.0',
'user-agent': getUserAgent(),
'X-Appwrite-Response-Format': '2.0.0',
};
Expand Down
8 changes: 8 additions & 0 deletions src/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4187,6 +4187,10 @@ export namespace Models {
* Function execution schedule in CRON format.
*/
schedule: string;
/**
* Minutes between scheduled executions. 0 when the function has no interval.
*/
interval?: number;
/**
* Function execution timeout in seconds.
*/
Expand Down Expand Up @@ -7834,6 +7838,10 @@ export namespace Models {
* Maximum function and site deployment size in MB
*/
buildSize: number;
/**
* Shortest function schedule interval allowed, in minutes. 0 allows every interval.
*/
functionsIntervalMinimum: number;
/**
* Does the plan support encrypted string attributes or not.
*/
Expand Down
34 changes: 30 additions & 4 deletions src/services/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export class Functions {
* @param {Runtime} params.runtime - Execution runtime.
* @param {string[]} params.execute - An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.
* @param {string[]} params.events - Events list. Maximum of 100 events are allowed.
* @param {string} params.schedule - Schedule CRON syntax.
* @param {string} params.schedule - Schedule CRON syntax. Cannot be combined with interval.
* @param {number} params.timeout - Function maximum execution time in seconds.
* @param {boolean} params.enabled - Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.
* @param {boolean} params.logging - When disabled, executions will exclude logs and errors, and will be slightly faster.
Expand All @@ -124,6 +124,7 @@ export class Functions {
* @param {string} params.buildSpecification - Build specification for the function deployments.
* @param {string} params.runtimeSpecification - Runtime specification for the function executions.
* @param {number} params.deploymentRetention - Days to keep non-active deployments before deletion. Value 0 means all deployments will be kept.
* @param {number} params.interval - Minutes between scheduled executions. Appwrite picks when within each interval the function runs. Use 0 to disable. Cannot be combined with schedule.
* @throws {AppwriteException}
* @returns {Promise<Models.Function>}
*/
Expand All @@ -150,6 +151,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
}): Promise<Models.Function>;
/**
* Create a new function. You can pass a list of [permissions](https://appwrite.io/docs/permissions) to allow different project users or team with access to execute the function using the client API.
Expand All @@ -159,7 +161,7 @@ export class Functions {
* @param {Runtime} runtime - Execution runtime.
* @param {string[]} execute - An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.
* @param {string[]} events - Events list. Maximum of 100 events are allowed.
* @param {string} schedule - Schedule CRON syntax.
* @param {string} schedule - Schedule CRON syntax. Cannot be combined with interval.
* @param {number} timeout - Function maximum execution time in seconds.
* @param {boolean} enabled - Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.
* @param {boolean} logging - When disabled, executions will exclude logs and errors, and will be slightly faster.
Expand All @@ -176,6 +178,7 @@ export class Functions {
* @param {string} buildSpecification - Build specification for the function deployments.
* @param {string} runtimeSpecification - Runtime specification for the function executions.
* @param {number} deploymentRetention - Days to keep non-active deployments before deletion. Value 0 means all deployments will be kept.
* @param {number} interval - Minutes between scheduled executions. Appwrite picks when within each interval the function runs. Use 0 to disable. Cannot be combined with schedule.
* @throws {AppwriteException}
* @returns {Promise<Models.Function>}
* @deprecated Use the object parameter style method for a better developer experience.
Expand Down Expand Up @@ -203,6 +206,7 @@ export class Functions {
buildSpecification?: string,
runtimeSpecification?: string,
deploymentRetention?: number,
interval?: number,
): Promise<Models.Function>;
create(
paramsOrFirst:
Expand All @@ -229,6 +233,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
}
| string,
...rest: [
Expand All @@ -253,6 +258,7 @@ export class Functions {
string?,
string?,
number?,
number?,
]
): Promise<Models.Function> {
let params: {
Expand All @@ -278,6 +284,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
};

if (
Expand Down Expand Up @@ -308,6 +315,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
};
} else {
params = {
Expand All @@ -333,6 +341,7 @@ export class Functions {
buildSpecification: rest[18] as string,
runtimeSpecification: rest[19] as string,
deploymentRetention: rest[20] as number,
interval: rest[21] as number,
};
}

Expand All @@ -358,6 +367,7 @@ export class Functions {
const buildSpecification = params.buildSpecification;
const runtimeSpecification = params.runtimeSpecification;
const deploymentRetention = params.deploymentRetention;
const interval = params.interval;
if (typeof functionId === 'undefined') {
throw new AppwriteException(
'Missing required parameter: "functionId"',
Expand Down Expand Up @@ -439,6 +449,9 @@ export class Functions {
if (typeof deploymentRetention !== 'undefined') {
apiPayload['deploymentRetention'] = deploymentRetention;
}
if (typeof interval !== 'undefined') {
apiPayload['interval'] = interval;
}
Comment on lines +452 to +454

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add coverage for interval serialization

The existing create/update tests in test/services/functions.test.js only check returned data and do not assert request payloads, so they would pass if interval were omitted or mapped incorrectly. Please cover interval serialization for the new API parameter, including the positional overload if it remains supported.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/services/functions.ts
Line: 452-454

Comment:
**Add coverage for interval serialization**

The existing create/update tests in `test/services/functions.test.js` only check returned data and do not assert request payloads, so they would pass if `interval` were omitted or mapped incorrectly. Please cover interval serialization for the new API parameter, including the positional overload if it remains supported.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

🟡 Minor · testing · Reply if this doesn't apply.

const uri = new URL(this.client.config.endpoint + apiPath);

const apiHeaders: { [header: string]: string } = {
Expand Down Expand Up @@ -585,7 +598,7 @@ export class Functions {
* @param {Runtime} params.runtime - Execution runtime.
* @param {string[]} params.execute - An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.
* @param {string[]} params.events - Events list. Maximum of 100 events are allowed.
* @param {string} params.schedule - Schedule CRON syntax.
* @param {string} params.schedule - Schedule CRON syntax. Cannot be combined with interval.
* @param {number} params.timeout - Maximum execution time in seconds.
* @param {boolean} params.enabled - Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.
* @param {boolean} params.logging - When disabled, executions will exclude logs and errors, and will be slightly faster.
Expand All @@ -602,6 +615,7 @@ export class Functions {
* @param {string} params.buildSpecification - Build specification for the function deployments.
* @param {string} params.runtimeSpecification - Runtime specification for the function executions.
* @param {number} params.deploymentRetention - Days to keep non-active deployments before deletion. Value 0 means all deployments will be kept.
* @param {number} params.interval - Minutes between scheduled executions. Appwrite picks when within each interval the function runs. Use 0 to disable. Cannot be combined with schedule. When omitted, the current interval is kept unless schedule is set.
* @throws {AppwriteException}
* @returns {Promise<Models.Function>}
*/
Expand All @@ -628,6 +642,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
}): Promise<Models.Function>;
/**
* Update function by its unique ID.
Expand All @@ -637,7 +652,7 @@ export class Functions {
* @param {Runtime} runtime - Execution runtime.
* @param {string[]} execute - An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https://appwrite.io/docs/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.
* @param {string[]} events - Events list. Maximum of 100 events are allowed.
* @param {string} schedule - Schedule CRON syntax.
* @param {string} schedule - Schedule CRON syntax. Cannot be combined with interval.
* @param {number} timeout - Maximum execution time in seconds.
* @param {boolean} enabled - Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.
* @param {boolean} logging - When disabled, executions will exclude logs and errors, and will be slightly faster.
Expand All @@ -654,6 +669,7 @@ export class Functions {
* @param {string} buildSpecification - Build specification for the function deployments.
* @param {string} runtimeSpecification - Runtime specification for the function executions.
* @param {number} deploymentRetention - Days to keep non-active deployments before deletion. Value 0 means all deployments will be kept.
* @param {number} interval - Minutes between scheduled executions. Appwrite picks when within each interval the function runs. Use 0 to disable. Cannot be combined with schedule. When omitted, the current interval is kept unless schedule is set.
* @throws {AppwriteException}
* @returns {Promise<Models.Function>}
* @deprecated Use the object parameter style method for a better developer experience.
Expand Down Expand Up @@ -681,6 +697,7 @@ export class Functions {
buildSpecification?: string,
runtimeSpecification?: string,
deploymentRetention?: number,
interval?: number,
): Promise<Models.Function>;
update(
paramsOrFirst:
Expand All @@ -707,6 +724,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
}
| string,
...rest: [
Expand All @@ -731,6 +749,7 @@ export class Functions {
string?,
string?,
number?,
number?,
]
): Promise<Models.Function> {
let params: {
Expand All @@ -756,6 +775,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
};

if (
Expand Down Expand Up @@ -786,6 +806,7 @@ export class Functions {
buildSpecification?: string;
runtimeSpecification?: string;
deploymentRetention?: number;
interval?: number;
};
} else {
params = {
Expand All @@ -811,6 +832,7 @@ export class Functions {
buildSpecification: rest[18] as string,
runtimeSpecification: rest[19] as string,
deploymentRetention: rest[20] as number,
interval: rest[21] as number,
};
}

Expand All @@ -836,6 +858,7 @@ export class Functions {
const buildSpecification = params.buildSpecification;
const runtimeSpecification = params.runtimeSpecification;
const deploymentRetention = params.deploymentRetention;
const interval = params.interval;
if (typeof functionId === 'undefined') {
throw new AppwriteException(
'Missing required parameter: "functionId"',
Expand Down Expand Up @@ -912,6 +935,9 @@ export class Functions {
if (typeof deploymentRetention !== 'undefined') {
apiPayload['deploymentRetention'] = deploymentRetention;
}
if (typeof interval !== 'undefined') {
apiPayload['interval'] = interval;
}
const uri = new URL(this.client.config.endpoint + apiPath);

const apiHeaders: { [header: string]: string } = {
Expand Down
Loading