@venizia/ignis-docs 0.2.0 → 0.2.1-1
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 +14 -14
- package/content/best-practices/api-usage-examples.md +39 -19
- package/content/best-practices/architectural-patterns.md +24 -13
- package/content/best-practices/architecture-decisions.md +29 -16
- package/content/best-practices/code-style-standards/advanced-patterns.md +43 -31
- package/content/best-practices/code-style-standards/constants-configuration.md +19 -4
- package/content/best-practices/code-style-standards/control-flow.md +33 -1
- package/content/best-practices/code-style-standards/documentation.md +28 -8
- package/content/best-practices/code-style-standards/function-patterns.md +15 -4
- package/content/best-practices/code-style-standards/index.md +7 -2
- package/content/best-practices/code-style-standards/naming-conventions.md +27 -3
- package/content/best-practices/code-style-standards/route-definitions.md +9 -5
- package/content/best-practices/code-style-standards/tooling.md +14 -1
- package/content/best-practices/code-style-standards/type-safety.md +39 -6
- package/content/best-practices/common-pitfalls.md +59 -35
- package/content/best-practices/contribution-workflow.md +8 -4
- package/content/best-practices/data-modeling.md +78 -62
- package/content/best-practices/deployment-strategies.md +56 -19
- package/content/best-practices/error-handling.md +247 -153
- package/content/best-practices/index.md +6 -0
- package/content/best-practices/performance-optimization.md +26 -13
- package/content/best-practices/security-guidelines.md +35 -9
- package/content/best-practices/testing-strategies.md +7 -2
- package/content/best-practices/troubleshooting-tips.md +27 -17
- package/content/extensions/components/api-reference.md +109 -323
- package/content/extensions/components/authentication/api.md +489 -602
- package/content/extensions/components/authentication/errors.md +135 -498
- package/content/extensions/components/authentication/index.md +89 -801
- package/content/extensions/components/authentication/usage.md +231 -955
- package/content/extensions/components/authorization/api.md +991 -644
- package/content/extensions/components/authorization/errors.md +204 -208
- package/content/extensions/components/authorization/getting-started.md +227 -0
- package/content/extensions/components/authorization/index.md +88 -795
- package/content/extensions/components/authorization/usage.md +219 -528
- package/content/extensions/components/health-check.md +77 -243
- package/content/extensions/components/index.md +24 -90
- package/content/extensions/components/mail/api.md +553 -285
- package/content/extensions/components/mail/errors.md +76 -62
- package/content/extensions/components/mail/index.md +111 -463
- package/content/extensions/components/mail/usage.md +139 -173
- package/content/extensions/components/request-tracker.md +70 -173
- package/content/extensions/components/socket-io/api.md +462 -785
- package/content/extensions/components/socket-io/errors.md +49 -51
- package/content/extensions/components/socket-io/index.md +69 -372
- package/content/extensions/components/socket-io/usage.md +212 -105
- package/content/extensions/components/static-asset/api.md +461 -141
- package/content/extensions/components/static-asset/errors.md +121 -53
- package/content/extensions/components/static-asset/index.md +84 -606
- package/content/extensions/components/static-asset/usage.md +184 -299
- package/content/extensions/components/template/index.md +3 -3
- package/content/extensions/components/websocket/api.md +311 -404
- package/content/extensions/components/websocket/errors.md +47 -56
- package/content/extensions/components/websocket/index.md +75 -407
- package/content/extensions/components/websocket/usage.md +120 -338
- package/content/extensions/helpers/cron/index.md +52 -160
- package/content/extensions/helpers/crypto/index.md +67 -480
- package/content/extensions/helpers/crypto/reference.md +528 -0
- package/content/extensions/helpers/env/index.md +64 -178
- package/content/extensions/helpers/error/index.md +286 -196
- package/content/extensions/helpers/index.md +61 -47
- package/content/extensions/helpers/inversion/index.md +76 -550
- package/content/extensions/helpers/inversion/reference.md +530 -0
- package/content/extensions/helpers/kafka/admin.md +23 -3
- package/content/extensions/helpers/kafka/compile-binary.md +83 -52
- package/content/extensions/helpers/kafka/consumer.md +65 -28
- package/content/extensions/helpers/kafka/examples.md +46 -253
- package/content/extensions/helpers/kafka/index.md +55 -617
- package/content/extensions/helpers/kafka/producer.md +156 -22
- package/content/extensions/helpers/kafka/schema-registry.md +59 -79
- package/content/extensions/helpers/logger/hf-logger.md +220 -0
- package/content/extensions/helpers/logger/index.md +78 -552
- package/content/extensions/helpers/logger/pino.md +105 -0
- package/content/extensions/helpers/logger/reference.md +937 -0
- package/content/extensions/helpers/network/api.md +276 -195
- package/content/extensions/helpers/network/index.md +87 -524
- package/content/extensions/helpers/queue/index.md +80 -897
- package/content/extensions/helpers/queue/reference.md +494 -0
- package/content/extensions/helpers/redis/index.md +86 -640
- package/content/extensions/helpers/redis/reference.md +784 -0
- package/content/extensions/helpers/secrets/index.md +136 -0
- package/content/extensions/helpers/socket-io/api.md +325 -204
- package/content/extensions/helpers/socket-io/index.md +79 -429
- package/content/extensions/helpers/storage/api.md +584 -464
- package/content/extensions/helpers/storage/index.md +80 -573
- package/content/extensions/helpers/types/index.md +75 -495
- package/content/extensions/helpers/types/reference.md +689 -0
- package/content/extensions/helpers/uid/index.md +176 -189
- package/content/extensions/helpers/websocket/api.md +366 -214
- package/content/extensions/helpers/websocket/index.md +68 -503
- package/content/extensions/helpers/worker-thread/index.md +62 -396
- package/content/extensions/helpers/worker-thread/reference.md +428 -0
- package/content/extensions/index.md +38 -39
- package/content/extensions/src-details/mcp-server.md +96 -548
- package/content/guides/core-concepts/persistent/datasources.md +2 -2
- package/content/guides/core-concepts/persistent/index.md +5 -1
- package/content/guides/core-concepts/persistent/models.md +1 -1
- package/content/guides/core-concepts/persistent/pglite.md +218 -0
- package/content/guides/core-concepts/persistent/postgres-drivers.md +21 -15
- package/content/guides/core-concepts/persistent/search-meilisearch.md +22 -12
- package/content/guides/core-concepts/persistent/search-typesense.md +28 -16
- package/content/guides/core-concepts/persistent/sqlite.md +296 -0
- package/content/guides/core-concepts/persistent/transactions.md +12 -11
- package/content/guides/core-concepts/secrets-vault.md +177 -0
- package/content/guides/core-concepts/services.md +1 -1
- package/content/guides/get-started/5-minute-quickstart.md +59 -206
- package/content/guides/get-started/philosophy.md +135 -670
- package/content/guides/get-started/setup.md +53 -74
- package/content/guides/migrations/redis-helpers-migration.md +5 -4
- package/content/guides/migrations/scoped-rbac-migration.md +5 -5
- package/content/guides/migrations/unified-connectors-migration.md +8 -7
- package/content/guides/tutorials/ecommerce-api.md +3 -8
- package/content/guides/tutorials/realtime-chat.md +1 -1
- package/content/references/base/application.md +64 -22
- package/content/references/base/components.md +3 -3
- package/content/references/base/connectors.md +79 -136
- package/content/references/base/controllers.md +12 -12
- package/content/references/base/datasources-reference.md +600 -0
- package/content/references/base/datasources.md +84 -444
- package/content/references/base/dependency-injection.md +25 -46
- package/content/references/base/filter-system/application-usage.md +95 -123
- package/content/references/base/filter-system/array-operators.md +33 -43
- package/content/references/base/filter-system/comparison-operators.md +55 -63
- package/content/references/base/filter-system/default-filter.md +144 -350
- package/content/references/base/filter-system/fields-order-pagination.md +116 -148
- package/content/references/base/filter-system/index.md +114 -253
- package/content/references/base/filter-system/json-filtering.md +52 -181
- package/content/references/base/filter-system/list-operators.md +28 -44
- package/content/references/base/filter-system/logical-operators.md +69 -114
- package/content/references/base/filter-system/null-operators.md +41 -98
- package/content/references/base/filter-system/pattern-matching.md +48 -51
- package/content/references/base/filter-system/quick-reference.md +93 -196
- package/content/references/base/filter-system/range-operators.md +22 -38
- package/content/references/base/filter-system/tips.md +70 -133
- package/content/references/base/filter-system/use-cases.md +173 -232
- package/content/references/base/grpc-controllers.md +53 -17
- package/content/references/base/index.md +5 -3
- package/content/references/base/middlewares.md +43 -28
- package/content/references/base/models-reference.md +886 -0
- package/content/references/base/models.md +81 -1452
- package/content/references/base/providers.md +8 -8
- package/content/references/base/repositories/advanced.md +281 -419
- package/content/references/base/repositories/index.md +84 -644
- package/content/references/base/repositories/mixins.md +25 -21
- package/content/references/base/repositories/relations.md +194 -375
- package/content/references/base/repositories/soft-deletable.md +67 -55
- package/content/references/base/secrets.md +267 -0
- package/content/references/base/services.md +8 -6
- package/content/references/configuration/environment-variables.md +73 -21
- package/content/references/configuration/index.md +51 -31
- package/content/references/index.md +1 -1
- package/content/references/quick-reference.md +3 -16
- package/content/references/utilities/crypto.md +35 -76
- package/content/references/utilities/date.md +33 -73
- package/content/references/utilities/duration.md +85 -0
- package/content/references/utilities/index.md +6 -2
- package/content/references/utilities/jsx-reference.md +298 -0
- package/content/references/utilities/jsx.md +82 -525
- package/content/references/utilities/module.md +81 -61
- package/content/references/utilities/parse.md +34 -64
- package/content/references/utilities/performance.md +33 -58
- package/content/references/utilities/promise.md +28 -62
- package/content/references/utilities/request.md +58 -218
- package/content/references/utilities/retry.md +139 -0
- package/content/references/utilities/schema.md +43 -137
- package/content/references/utilities/statuses-reference.md +361 -0
- package/content/references/utilities/statuses.md +63 -667
- package/dist/mcp-server/index.js +0 -0
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/github/list-project-files.tool.js +3 -3
- package/dist/mcp-server/tools/github/search-code.tool.js +1 -1
- package/dist/mcp-server/tools/github/verify-dependencies.tool.js +1 -1
- package/dist/mcp-server/tools/github/view-source-file.tool.js +1 -1
- package/package.json +24 -23
|
@@ -6,271 +6,239 @@ difficulty: intermediate
|
|
|
6
6
|
|
|
7
7
|
# Fields, Ordering & Pagination
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
The `filter` object controls which columns come back, in what order, and how many rows - through the `fields`, `order`, `limit`, and `skip`/`offset` properties.
|
|
10
10
|
|
|
11
|
+
```typescript
|
|
12
|
+
import { userRepository } from '@/repositories';
|
|
13
|
+
|
|
14
|
+
await userRepository.find({
|
|
15
|
+
filter: { fields: ['id', 'email'], order: ['createdAt DESC'], limit: 10 },
|
|
16
|
+
});
|
|
17
|
+
```
|
|
11
18
|
|
|
12
|
-
##
|
|
19
|
+
## Options
|
|
13
20
|
|
|
14
|
-
|
|
21
|
+
| Option | Type | Default | Meaning |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| `fields` | `string[] \| Record<string, boolean>` | every column | Inclusion-only column selection. |
|
|
24
|
+
| `order` | `string[]` (`'column ASC\|DESC'`) | insertion order | Sort columns; `ASC` if no direction is given. |
|
|
25
|
+
| `limit` | `number` | `settings.defaultLimit ?? 10` | Row cap. An explicit value always wins. |
|
|
26
|
+
| `skip` / `offset` | `number` | `0` | Rows to skip. Aliases for the same `OFFSET` clause; `skip` wins if both are set. |
|
|
27
|
+
| `options.shouldQueryRange` | `boolean` | `false` | Adds a `range` envelope (`start`/`end`/`total`) to the result. |
|
|
15
28
|
|
|
16
|
-
|
|
29
|
+
## Field selection
|
|
30
|
+
|
|
31
|
+
`fields` accepts an array or an object. Both select the same columns:
|
|
17
32
|
|
|
18
33
|
```typescript
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
fields: ['id', 'email', 'name']
|
|
23
|
-
}
|
|
34
|
+
// Array format (recommended)
|
|
35
|
+
await userRepository.find({
|
|
36
|
+
filter: { where: { status: 'active' }, fields: ['id', 'email', 'name'] },
|
|
24
37
|
});
|
|
25
38
|
// Returns only: { id, email, name }
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Object Format
|
|
29
39
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
filter: {
|
|
34
|
-
fields: { id: true, email: true, name: true }
|
|
35
|
-
}
|
|
40
|
+
// Object format - only keys set to `true` are selected
|
|
41
|
+
await userRepository.find({
|
|
42
|
+
filter: { fields: { id: true, email: true, name: true } },
|
|
36
43
|
});
|
|
37
44
|
```
|
|
38
45
|
|
|
39
46
|
> [!NOTE]
|
|
40
|
-
> The object format
|
|
41
|
-
|
|
47
|
+
> The object format is inclusion-only. A key set to `false` is ignored, not excluded - it neither adds nor removes the column. To exclude a column, omit its key or use the array format.
|
|
42
48
|
|
|
43
49
|
## Ordering
|
|
44
50
|
|
|
45
|
-
|
|
51
|
+
Each entry in `order` is a `'column DIRECTION'` string. Direction defaults to `ASC` and only `ASC`/`DESC` (case-insensitive) are valid:
|
|
46
52
|
|
|
47
53
|
```typescript
|
|
48
|
-
|
|
49
|
-
await
|
|
50
|
-
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// Multiple columns
|
|
54
|
-
await repository.find({
|
|
55
|
-
filter: { order: ['status ASC', 'createdAt DESC'] }
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
// Default direction is ASC
|
|
59
|
-
await repository.find({
|
|
60
|
-
filter: { order: ['name'] } // Same as 'name ASC'
|
|
61
|
-
});
|
|
54
|
+
await userRepository.find({ filter: { order: ['createdAt DESC'] } });
|
|
55
|
+
await userRepository.find({ filter: { order: ['status ASC', 'createdAt DESC'] } });
|
|
56
|
+
await userRepository.find({ filter: { order: ['name'] } }); // same as 'name ASC'
|
|
62
57
|
```
|
|
63
58
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
Only `ASC` and `DESC` (case-insensitive) are accepted. Invalid directions throw an error:
|
|
59
|
+
An invalid direction throws before the query runs:
|
|
67
60
|
|
|
68
61
|
```
|
|
69
62
|
Error: Invalid direction: 'RANDOM' | Expected: 'ASC' or 'DESC'
|
|
70
63
|
```
|
|
71
64
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
Order by nested fields in JSON columns:
|
|
65
|
+
Order by a nested key inside a JSON column with dot-path notation:
|
|
75
66
|
|
|
76
67
|
```typescript
|
|
77
|
-
await
|
|
78
|
-
filter: { order: ['metadata.priority DESC'] }
|
|
79
|
-
});
|
|
68
|
+
await userRepository.find({ filter: { order: ['metadata.priority DESC'] } });
|
|
80
69
|
// SQL: ORDER BY "metadata" #> '{priority}' DESC
|
|
81
70
|
|
|
82
|
-
await
|
|
83
|
-
filter: { order: ['settings.display.theme ASC'] }
|
|
84
|
-
});
|
|
71
|
+
await userRepository.find({ filter: { order: ['settings.display.theme ASC'] } });
|
|
85
72
|
```
|
|
86
73
|
|
|
87
|
-
|
|
74
|
+
JSONB values sort by type first, then by value within the type:
|
|
88
75
|
|
|
89
|
-
| JSONB
|
|
90
|
-
|
|
76
|
+
| JSONB type | Sort position |
|
|
77
|
+
|---|---|
|
|
91
78
|
| `null` | First (lowest) |
|
|
92
|
-
| `boolean` | `false`
|
|
79
|
+
| `boolean` | `false` before `true` |
|
|
93
80
|
| `number` | Numeric order |
|
|
94
|
-
| `string` | Lexicographic |
|
|
81
|
+
| `string` | Lexicographic order |
|
|
95
82
|
| `array` | Element-wise |
|
|
96
|
-
| `object` | Key-value |
|
|
83
|
+
| `object` | Key-value order |
|
|
97
84
|
|
|
85
|
+
See [JSON Filtering](./json-filtering) for the full path syntax.
|
|
98
86
|
|
|
99
87
|
## Pagination
|
|
100
88
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
Both `skip` and `offset` are supported as aliases -- they both map to the SQL `OFFSET` clause. When both are provided, `skip` takes precedence.
|
|
89
|
+
`limit` caps the row count; `skip` (or its alias `offset`) sets how many rows to skip. Combine them for page N:
|
|
104
90
|
|
|
105
91
|
```typescript
|
|
106
|
-
|
|
107
|
-
await
|
|
108
|
-
filter: { limit: 10 }
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
// Page 2 (skip first 10, get next 10)
|
|
112
|
-
await repository.find({
|
|
113
|
-
filter: { limit: 10, skip: 10 }
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
// Using offset (equivalent to skip)
|
|
117
|
-
await repository.find({
|
|
118
|
-
filter: { limit: 10, offset: 10 }
|
|
119
|
-
});
|
|
92
|
+
await userRepository.find({ filter: { limit: 10 } }); // first 10
|
|
93
|
+
await userRepository.find({ filter: { limit: 10, skip: 10 } }); // page 2
|
|
120
94
|
|
|
121
|
-
// Page N formula: skip = (page - 1) * limit
|
|
122
95
|
const page = 3;
|
|
123
96
|
const pageSize = 20;
|
|
124
|
-
await
|
|
125
|
-
filter: {
|
|
126
|
-
limit: pageSize,
|
|
127
|
-
skip: (page - 1) * pageSize
|
|
128
|
-
}
|
|
97
|
+
await userRepository.find({
|
|
98
|
+
filter: { limit: pageSize, skip: (page - 1) * pageSize },
|
|
129
99
|
});
|
|
130
100
|
```
|
|
131
101
|
|
|
132
102
|
> [!TIP]
|
|
133
|
-
>
|
|
103
|
+
> Set `limit` on every public-facing endpoint. An unbounded query can exhaust memory - the repository always falls back to a default of `10`, never to "no limit".
|
|
134
104
|
|
|
135
|
-
### Default
|
|
105
|
+
### Default limit resolution
|
|
136
106
|
|
|
137
|
-
|
|
107
|
+
A query that omits `limit` gets one from this precedence chain:
|
|
138
108
|
|
|
139
109
|
```
|
|
140
|
-
query.limit ??
|
|
110
|
+
query.limit ?? settings.defaultLimit ?? DEFAULT_LIMIT (10)
|
|
141
111
|
```
|
|
142
112
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
113
|
+
| Source | Meaning |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `query.limit` | An explicit `limit` in the caller's filter. Always wins. |
|
|
116
|
+
| `settings.defaultLimit` | A per-model default on the `@model` decorator. Must be a positive integer - `@model` validates it at decoration time. Applies to top-level `find()` and to every to-many relation, using the related model's own `defaultLimit`. |
|
|
117
|
+
| `DEFAULT_LIMIT` | The global fallback, `10`. |
|
|
146
118
|
|
|
147
119
|
```typescript
|
|
120
|
+
import { model, BaseEntity } from '@venizia/ignis';
|
|
121
|
+
import { countryTable } from '@/schemas';
|
|
122
|
+
import { countryRepository } from '@/repositories';
|
|
123
|
+
|
|
148
124
|
@model({
|
|
149
125
|
type: 'entity',
|
|
150
|
-
settings: { defaultLimit: 200 },
|
|
126
|
+
settings: { defaultLimit: 200 }, // small lookup table - default to 200 rows
|
|
151
127
|
})
|
|
152
|
-
export class Country extends BaseEntity<typeof Country.schema> {
|
|
128
|
+
export class Country extends BaseEntity<typeof Country.schema> {
|
|
129
|
+
static override schema = countryTable;
|
|
130
|
+
}
|
|
153
131
|
|
|
154
|
-
await countryRepository.find({ filter: {} });
|
|
155
|
-
await countryRepository.find({ filter: { limit: 10 } }); // LIMIT 10
|
|
132
|
+
await countryRepository.find({ filter: {} }); // LIMIT 200
|
|
133
|
+
await countryRepository.find({ filter: { limit: 10 } }); // LIMIT 10 (explicit wins)
|
|
156
134
|
```
|
|
157
135
|
|
|
158
136
|
> [!NOTE]
|
|
159
|
-
> `defaultLimit` is independent of `defaultFilter
|
|
137
|
+
> `defaultLimit` is independent of `defaultFilter`. Passing `shouldSkipDefaultFilter` bypasses the default `where` clause but never drops the default limit. There is no "unbounded" sentinel - to fetch more rows, pass an explicit `limit`.
|
|
160
138
|
|
|
161
|
-
|
|
139
|
+
A small helper keeps page-to-filter math in one place:
|
|
162
140
|
|
|
163
141
|
```typescript
|
|
164
142
|
function getPaginationFilter(page: number, pageSize: number = 20) {
|
|
165
|
-
return {
|
|
166
|
-
limit: pageSize,
|
|
167
|
-
skip: (page - 1) * pageSize
|
|
168
|
-
};
|
|
143
|
+
return { limit: pageSize, skip: (page - 1) * pageSize };
|
|
169
144
|
}
|
|
170
145
|
|
|
171
|
-
|
|
172
|
-
const filter = {
|
|
173
|
-
where: { status: 'active' },
|
|
174
|
-
...getPaginationFilter(3, 20)
|
|
175
|
-
};
|
|
146
|
+
const filter = { where: { status: 'active' }, ...getPaginationFilter(3, 20) };
|
|
176
147
|
// { where: {...}, limit: 20, skip: 40 }
|
|
177
148
|
```
|
|
178
149
|
|
|
150
|
+
## Range queries (Content-Range header)
|
|
179
151
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
When building paginated APIs, you often need to return the total count alongside the data for pagination UI. Use `shouldQueryRange: true` to get range information following the HTTP Content-Range standard.
|
|
183
|
-
|
|
184
|
-
### Basic Usage
|
|
152
|
+
Set `options.shouldQueryRange: true` to get the total row count alongside the data, formatted for the HTTP `Content-Range` header:
|
|
185
153
|
|
|
186
154
|
```typescript
|
|
187
|
-
const result = await
|
|
155
|
+
const result = await userRepository.find({
|
|
188
156
|
filter: { limit: 10, skip: 20 },
|
|
189
|
-
options: { shouldQueryRange: true }
|
|
157
|
+
options: { shouldQueryRange: true },
|
|
190
158
|
});
|
|
191
159
|
|
|
192
|
-
//
|
|
193
|
-
// {
|
|
194
|
-
// data: [...], // Array of records
|
|
195
|
-
// range: {
|
|
196
|
-
// start: 20, // Starting index (inclusive)
|
|
197
|
-
// end: 29, // Ending index (inclusive)
|
|
198
|
-
// total: 100 // Total matching records
|
|
199
|
-
// }
|
|
200
|
-
// }
|
|
160
|
+
// result.data -> the matching rows
|
|
161
|
+
// result.range -> { start: 20, end: 29, total: 100 }
|
|
201
162
|
```
|
|
202
163
|
|
|
203
|
-
|
|
164
|
+
`range` has this shape:
|
|
204
165
|
|
|
205
|
-
|
|
166
|
+
```typescript
|
|
167
|
+
type TDataRange = {
|
|
168
|
+
start: number; // starting index, 0-based, inclusive
|
|
169
|
+
end: number; // ending index, 0-based, inclusive
|
|
170
|
+
total: number; // total rows matching the query
|
|
171
|
+
};
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Build the header value from `range`:
|
|
206
175
|
|
|
207
176
|
```typescript
|
|
208
|
-
const { data, range } = await
|
|
177
|
+
const { data, range } = await userRepository.find({
|
|
209
178
|
filter: { limit: 10, skip: 20, where: { status: 'active' } },
|
|
210
|
-
options: { shouldQueryRange: true }
|
|
179
|
+
options: { shouldQueryRange: true },
|
|
211
180
|
});
|
|
212
181
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
? `records ${range.start}-${range.end}/${range.total}`
|
|
216
|
-
: `records */${range.total}`;
|
|
182
|
+
const contentRange =
|
|
183
|
+
data.length > 0 ? `records ${range.start}-${range.end}/${range.total}` : `records */${range.total}`;
|
|
217
184
|
|
|
218
185
|
res.setHeader('Content-Range', contentRange);
|
|
219
186
|
// -> "records 20-29/100"
|
|
220
187
|
```
|
|
221
188
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
```typescript
|
|
225
|
-
type TDataRange = {
|
|
226
|
-
start: number; // Starting index (0-based, inclusive)
|
|
227
|
-
end: number; // Ending index (0-based, inclusive)
|
|
228
|
-
total: number; // Total count matching the query
|
|
229
|
-
};
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
### Content-Range Format Reference
|
|
233
|
-
|
|
234
|
-
| Scenario | Content-Range Header |
|
|
235
|
-
|----------|---------------------|
|
|
189
|
+
| Scenario | Content-Range header |
|
|
190
|
+
|---|---|
|
|
236
191
|
| Items 0-9 of 100 | `records 0-9/100` |
|
|
237
192
|
| Items 20-29 of 100 | `records 20-29/100` |
|
|
238
193
|
| No items found | `records */0` |
|
|
239
194
|
| Last page (items 90-99) | `records 90-99/100` |
|
|
240
195
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
When `shouldQueryRange: true`, the repository executes the data query and count query **in parallel** using `Promise.all` for optimal performance.
|
|
244
|
-
|
|
196
|
+
> [!NOTE]
|
|
197
|
+
> With `shouldQueryRange: true`, the repository runs the data query and the count query in parallel via `Promise.all`.
|
|
245
198
|
|
|
246
|
-
## Combined
|
|
199
|
+
## Combined example
|
|
247
200
|
|
|
248
201
|
```typescript
|
|
249
|
-
await
|
|
202
|
+
await userRepository.find({
|
|
250
203
|
filter: {
|
|
251
204
|
where: { status: 'active' },
|
|
252
205
|
fields: ['id', 'name', 'price', 'createdAt'],
|
|
253
206
|
order: ['price ASC', 'createdAt DESC'],
|
|
254
207
|
limit: 20,
|
|
255
|
-
skip: 0
|
|
256
|
-
}
|
|
208
|
+
skip: 0,
|
|
209
|
+
},
|
|
257
210
|
});
|
|
258
211
|
```
|
|
259
212
|
|
|
260
|
-
|
|
213
|
+
With range information:
|
|
261
214
|
|
|
262
215
|
```typescript
|
|
263
|
-
const { data, range } = await
|
|
216
|
+
const { data, range } = await userRepository.find({
|
|
264
217
|
filter: {
|
|
265
218
|
where: { status: 'active' },
|
|
266
219
|
fields: ['id', 'name', 'price', 'createdAt'],
|
|
267
220
|
order: ['price ASC', 'createdAt DESC'],
|
|
268
221
|
limit: 20,
|
|
269
|
-
skip: 0
|
|
222
|
+
skip: 0,
|
|
270
223
|
},
|
|
271
|
-
options: { shouldQueryRange: true }
|
|
224
|
+
options: { shouldQueryRange: true },
|
|
272
225
|
});
|
|
273
226
|
|
|
274
227
|
console.log(`Showing ${range.start}-${range.end} of ${range.total}`);
|
|
275
228
|
// -> "Showing 0-19 of 150"
|
|
276
229
|
```
|
|
230
|
+
|
|
231
|
+
## See also
|
|
232
|
+
|
|
233
|
+
- [Filter System Overview](./) - the `filter` shape and the full `where` operator table
|
|
234
|
+
- [JSON Filtering](./json-filtering) - JSON path ordering and the JSONB sort-order table
|
|
235
|
+
- [Default Filter](./default-filter) - `settings.defaultFilter`, the sibling of `settings.defaultLimit`
|
|
236
|
+
- [Quick Reference](./quick-reference) - every operator, one line each
|
|
237
|
+
|
|
238
|
+
**Files:**
|
|
239
|
+
|
|
240
|
+
- [`packages/core-server/src/connectors/relational/repositories/dialect/filter.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/relational/repositories/dialect/filter.ts) - `FilterBuilder`, `toColumns`/`toOrderBy`
|
|
241
|
+
- [`packages/core-server/src/connectors/postgres/repositories/core/readable.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/connectors/postgres/repositories/core/readable.ts) - `find()`'s `query.limit ?? getDefaultLimit() ?? DEFAULT_LIMIT` resolution
|
|
242
|
+
- [`packages/filter/src/common/operators.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/filter/src/common/operators.ts) - `Sorts` constants
|
|
243
|
+
- [`packages/core-server/src/base/repositories/common/constants.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/base/repositories/common/constants.ts) - `DEFAULT_LIMIT`
|
|
244
|
+
- [`packages/core-server/src/base/repositories/common/types.ts`](https://github.com/VENIZIA-AI/ignis/blob/main/packages/core-server/src/base/repositories/common/types.ts) - `TDataRange`, `buildDataRange`
|