From a471bbdfad6855839e0aeb07e2e0707845713cb9 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 20 Jan 2026 20:58:36 +0000 Subject: [PATCH 1/4] Document countOnly parameter and count security rule type - Add "Count Records Only" section to JS API docs - Add "Count Only Query" section to REST API docs - Add operation types table to security rules docs - Add 'count' case to custom security rule examples Related to DEV-859 Co-Authored-By: Claude Opus 4.5 --- docs/API/fliplet-datasources.md | 43 ++++++++++++++++++++++++++++ docs/Data-source-security.md | 22 +++++++++++++- docs/REST-API/fliplet-datasources.md | 33 ++++++++++++++++++++- 3 files changed, 96 insertions(+), 2 deletions(-) diff --git a/docs/API/fliplet-datasources.md b/docs/API/fliplet-datasources.md index 8deb56d9..150ece75 100644 --- a/docs/API/fliplet-datasources.md +++ b/docs/API/fliplet-datasources.md @@ -228,6 +228,49 @@ The `$filters` operator provides optimized performance and additional conditions **📖 Complete Operators Reference:** [View detailed query operators documentation](datasources/query-operators.md) +--- + +### Count Records Only + +**Purpose:** Efficiently count entries matching criteria without retrieving data +**Syntax:** `connection.find({ countOnly: true, where?: object })` +**Returns:** `Promise` - The count of matching entries +**When to use:** Checking availability, preventing duplicates, analytics + +#### Basic Usage +```js +// Count all entries +const connection = await Fliplet.DataSources.connectByName("Users"); +const totalUsers = await connection.find({ countOnly: true }); +console.log(`Total users: ${totalUsers}`); + +// Count with filter +const connection = await Fliplet.DataSources.connectByName("Bookings"); +const bookedSlots = await connection.find({ + where: { SessionId: 123 }, + countOnly: true +}); +console.log(`Booked slots: ${bookedSlots}`); + +// Check if user already registered +const connection = await Fliplet.DataSources.connectByName("Registrations"); +const existingCount = await connection.find({ + where: { Email: 'user@example.com' }, + countOnly: true +}); +if (existingCount > 0) { + console.log('User already registered'); +} +``` + +#### Security Notes +- Requires `count` or `select` permission in security rules +- `select` permission automatically grants `count` (backwards compatible) +- Use `count`-only rules to allow checking availability without exposing data +- Only database-compatible filters are supported (no complex Sift.js operators like `$regex`, `$elemMatch`) + +--- + ### 2. Insert Records (Add Data) **Purpose:** Add new records to the data source diff --git a/docs/Data-source-security.md b/docs/Data-source-security.md index dcb38281..f5fa728a 100644 --- a/docs/Data-source-security.md +++ b/docs/Data-source-security.md @@ -37,11 +37,25 @@ Fliplet apps can have each of their screens and data sources secured so that the If you need more control on your security rules granting access to Data Sources, you can write your custom conditions using Javascript. When doing so, **these variables are available to the context of the script**: -- `type` (String) the type of operation the user is attempting to run on the Data Source (`select`, `insert`, `update`, `delete`) +- `type` (String) the type of operation the user is attempting to run on the Data Source (`select`, `insert`, `update`, `delete`, `count`) - `user` (Object) the user's session with its data, when the user is logged in - `query` (Object or Array) the input query (when reading data) or data to write (when inserting or updating an entry). When using the commit endpoint, this will be the array of entries being inserted or updated. - `entry` (Object) the existing entry being updated, if applicable +### Operation Types + +The following operation types are available for security rules: + +| Type | Description | +|------|-------------| +| `select` | Read entries from the data source. Also implies `count` permission. | +| `insert` | Create new entries in the data source. | +| `update` | Modify existing entries in the data source. | +| `delete` | Remove entries from the data source. | +| `count` | Count entries matching a query without reading entry data. | + +**Note:** The `select` permission automatically grants `count` permission (backwards compatible). You can grant `count` without `select` to allow users to check entry counts without accessing the actual data. + Given the possible values of the `query` object, you may need to write your code in a way that it can handle all situations. Here's a full example of a security rule handling all scenarios at once: ```js @@ -87,6 +101,12 @@ switch (type) { // Check the input data return { granted: query.foo === 'bar' }; + + case 'count': + // Check scenario when counting records. + // "query" here is the input query filter from the API request. + // Note: 'select' permission implies 'count' permission (backwards compatible). + return { granted: query.foo !== 'bar' }; } ``` diff --git a/docs/REST-API/fliplet-datasources.md b/docs/REST-API/fliplet-datasources.md index 036ae853..3d8db2f3 100644 --- a/docs/REST-API/fliplet-datasources.md +++ b/docs/REST-API/fliplet-datasources.md @@ -82,7 +82,7 @@ curl -X GET \ ## Data source access -Data sources requires access to be accessed to. Roles can have multiple permissions: **read, write, update, delete**. Once you create a data source, permissions need to be assigned to it. +Data sources requires access to be accessed to. Roles can have multiple permissions: **read, write, update, delete, count**. Once you create a data source, permissions need to be assigned to it. If an API token you're using doesn't have access to one of your organization data sources, you will need to grant permissions to it via Fliplet Studio: @@ -425,6 +425,7 @@ All operators of the [Data Source "find" JS API](https://developers.fliplet.com/ - [limit](https://developers.fliplet.com/API/fliplet-datasources.html#fetch-records-with-pagination) - Limit number of results - [offset](https://developers.fliplet.com/API/fliplet-datasources.html#fetch-records-with-pagination) - Skip records for pagination - [includePagination](https://developers.fliplet.com/API/fliplet-datasources.html#pagination-and-performance) - Include pagination metadata +- [countOnly](https://developers.fliplet.com/API/fliplet-datasources.html#count-records-only) - Return count without entry data #### Basic Query Example @@ -502,6 +503,36 @@ Response (Status code: 200 OK): } ``` +#### Count Only Query + +To retrieve just the count of matching entries without the actual data, use `countOnly: true`: + +Request body (JSON): + +```json +{ + "where": { + "SessionId": "123" + }, + "countOnly": true +} +``` + +Response (Status code: 200 OK): + +```json +{ + "count": 42, + "dataSourceId": 123 +} +``` + +**Notes:** +- Only database-compatible filters are supported (equality, `$in`, `$gt`, `$lt`, etc.) +- Complex Sift.js operators (like `$regex`, `$elemMatch`) return a 400 error +- Requires `count` or `select` permission in security rules +- The `select` permission automatically grants `count` permission + #### Advanced Query with Complex Filters For detailed information on all available query operators including MongoDB-style operators and Fliplet's custom `$filters` operator, see the [Query Operators Reference](../API/datasources/query-operators.html). From 69ddcd1a6b5f84f033ffb77585376b64ffa5eca1 Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 20 Jan 2026 21:43:24 +0000 Subject: [PATCH 2/4] Update docs/REST-API/fliplet-datasources.md Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- docs/REST-API/fliplet-datasources.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/REST-API/fliplet-datasources.md b/docs/REST-API/fliplet-datasources.md index 3d8db2f3..325817ce 100644 --- a/docs/REST-API/fliplet-datasources.md +++ b/docs/REST-API/fliplet-datasources.md @@ -82,7 +82,7 @@ curl -X GET \ ## Data source access -Data sources requires access to be accessed to. Roles can have multiple permissions: **read, write, update, delete, count**. Once you create a data source, permissions need to be assigned to it. +Data sources require access to be used. Roles can have multiple permissions: **read, write, update, delete, count**. Once you create a data source, permissions need to be assigned to it. If an API token you're using doesn't have access to one of your organization data sources, you will need to grant permissions to it via Fliplet Studio: From a13b7e8bb4cbe0f131a3465e1de509b6f2e1a38e Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Tue, 20 Jan 2026 21:46:59 +0000 Subject: [PATCH 3/4] Fix markdown formatting in Count Records Only section - Add blank line after headings before code blocks - Add blank line after Security Notes heading before list - Indent list items with 2 spaces for proper nesting Co-Authored-By: Claude Opus 4.5 --- docs/API/fliplet-datasources.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/API/fliplet-datasources.md b/docs/API/fliplet-datasources.md index 150ece75..998cdc45 100644 --- a/docs/API/fliplet-datasources.md +++ b/docs/API/fliplet-datasources.md @@ -238,6 +238,7 @@ The `$filters` operator provides optimized performance and additional conditions **When to use:** Checking availability, preventing duplicates, analytics #### Basic Usage + ```js // Count all entries const connection = await Fliplet.DataSources.connectByName("Users"); @@ -264,10 +265,11 @@ if (existingCount > 0) { ``` #### Security Notes -- Requires `count` or `select` permission in security rules -- `select` permission automatically grants `count` (backwards compatible) -- Use `count`-only rules to allow checking availability without exposing data -- Only database-compatible filters are supported (no complex Sift.js operators like `$regex`, `$elemMatch`) + + - Requires `count` or `select` permission in security rules + - `select` permission automatically grants `count` (backwards compatible) + - Use `count`-only rules to allow checking availability without exposing data + - Only database-compatible filters are supported (no complex Sift.js operators like `$regex`, `$elemMatch`) --- From cf2615b5d02564926839bdf2218a612f557df7bb Mon Sep 17 00:00:00 2001 From: Tony Wu Date: Wed, 21 Jan 2026 01:14:00 +0000 Subject: [PATCH 4/4] Update countOnly docs to reflect Sift.js fallback support - Remove "database-compatible only" restriction from docs - Add Performance Notes section explaining fast path vs fallback - Simple filters use COUNT(*), complex filters use Sift.js Co-Authored-By: Claude Opus 4.5 --- docs/API/fliplet-datasources.md | 6 +++++- docs/REST-API/fliplet-datasources.md | 3 +-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/docs/API/fliplet-datasources.md b/docs/API/fliplet-datasources.md index 998cdc45..a57efd63 100644 --- a/docs/API/fliplet-datasources.md +++ b/docs/API/fliplet-datasources.md @@ -269,7 +269,11 @@ if (existingCount > 0) { - Requires `count` or `select` permission in security rules - `select` permission automatically grants `count` (backwards compatible) - Use `count`-only rules to allow checking availability without exposing data - - Only database-compatible filters are supported (no complex Sift.js operators like `$regex`, `$elemMatch`) + +#### Performance Notes + + - Simple filters (equality, `$eq`, `$gt`, `$lt`, `$and`, `$or`) use fast database `COUNT(*)` + - Complex filters (`$regex`, `$elemMatch`, etc.) fall back to fetching + filtering, same performance as a regular query but returns only the count --- diff --git a/docs/REST-API/fliplet-datasources.md b/docs/REST-API/fliplet-datasources.md index 325817ce..8c9b8cab 100644 --- a/docs/REST-API/fliplet-datasources.md +++ b/docs/REST-API/fliplet-datasources.md @@ -528,10 +528,9 @@ Response (Status code: 200 OK): ``` **Notes:** -- Only database-compatible filters are supported (equality, `$in`, `$gt`, `$lt`, etc.) -- Complex Sift.js operators (like `$regex`, `$elemMatch`) return a 400 error - Requires `count` or `select` permission in security rules - The `select` permission automatically grants `count` permission +- Simple filters use fast database `COUNT(*)`, complex filters use Sift.js fallback #### Advanced Query with Complex Filters