@adobe/spacecat-shared-data-access 2.77.1 → 2.79.0
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/CHANGELOG.md +14 -0
- package/package.json +1 -1
- package/src/models/configuration/configuration.model.js +1 -0
- package/src/readme.md +201 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [@adobe/spacecat-shared-data-access-v2.79.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v2.78.0...@adobe/spacecat-shared-data-access-v2.79.0) (2025-11-07)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* PTA2 Summary query ([#1102](https://github.com/adobe/spacecat-shared/issues/1102)) ([06e902a](https://github.com/adobe/spacecat-shared/commit/06e902a5487c2fc2e79a3f15d7acf1072900fab4))
|
|
7
|
+
|
|
8
|
+
# [@adobe/spacecat-shared-data-access-v2.78.0](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v2.77.1...@adobe/spacecat-shared-data-access-v2.78.0) (2025-11-06)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* **data-access:** add early-monday interval ([#1099](https://github.com/adobe/spacecat-shared/issues/1099)) ([3c7cc87](https://github.com/adobe/spacecat-shared/commit/3c7cc87b89c2bf06c9b5322ca20c26863cac14ac))
|
|
14
|
+
|
|
1
15
|
# [@adobe/spacecat-shared-data-access-v2.77.1](https://github.com/adobe/spacecat-shared/compare/@adobe/spacecat-shared-data-access-v2.77.0...@adobe/spacecat-shared-data-access-v2.77.1) (2025-11-01)
|
|
2
16
|
|
|
3
17
|
|
package/package.json
CHANGED
package/src/readme.md
CHANGED
|
@@ -88,7 +88,7 @@ const single = await Suggestion.findByOpportunityIdAndStatus('op-12345', 'OPEN')
|
|
|
88
88
|
- `get...()`: Getters for entity attributes.
|
|
89
89
|
- `set...()`: Setters for entity attributes.
|
|
90
90
|
|
|
91
|
-
Additionally, `BaseModel` generates methods to fetch referenced entities.
|
|
91
|
+
Additionally, `BaseModel` generates methods to fetch referenced entities.
|
|
92
92
|
For example, if `User` belongs to `Organization`, `BaseModel` will create:
|
|
93
93
|
|
|
94
94
|
- `getOrganization()`: Fetch the referenced `Organization` entity.
|
|
@@ -116,6 +116,206 @@ const org = await user.getOrganization();
|
|
|
116
116
|
console.log(org.getName());
|
|
117
117
|
```
|
|
118
118
|
|
|
119
|
+
## Pagination Support
|
|
120
|
+
|
|
121
|
+
All `allBy...` methods automatically support pagination through an optional `options` parameter. Pagination is built into `BaseCollection` and available for every entity without additional configuration.
|
|
122
|
+
|
|
123
|
+
### Query Options
|
|
124
|
+
|
|
125
|
+
Every `allBy...` method accepts an optional `options` object with the following parameters:
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface QueryOptions {
|
|
129
|
+
// Pagination control
|
|
130
|
+
limit?: number; // Limit results per page
|
|
131
|
+
cursor?: string; // Cursor from previous page
|
|
132
|
+
returnCursor?: boolean; // Return {data, cursor} instead of array
|
|
133
|
+
fetchAllPages?: boolean; // true: fetch all pages, false: single page only
|
|
134
|
+
|
|
135
|
+
// Query control
|
|
136
|
+
order?: 'asc' | 'desc'; // Sort order (default: 'desc')
|
|
137
|
+
attributes?: string[]; // Which fields to return
|
|
138
|
+
|
|
139
|
+
// Range queries
|
|
140
|
+
between?: {
|
|
141
|
+
attribute: string;
|
|
142
|
+
start: string | number;
|
|
143
|
+
end: string | number;
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Pagination Behavior
|
|
149
|
+
|
|
150
|
+
By default, `allBy...` methods **automatically fetch all pages** of results. You can control this behavior:
|
|
151
|
+
|
|
152
|
+
- **Default (no options):** Fetches all pages automatically
|
|
153
|
+
- **`fetchAllPages: true`:** Explicitly fetch all pages
|
|
154
|
+
- **`fetchAllPages: false`:** Fetch only the first page
|
|
155
|
+
- **`limit` without `fetchAllPages`:** Fetch only the first page (limited results)
|
|
156
|
+
|
|
157
|
+
### Usage Examples
|
|
158
|
+
|
|
159
|
+
#### Fetch All Results (Default)
|
|
160
|
+
```js
|
|
161
|
+
// Automatically fetches all pages
|
|
162
|
+
const suggestions = await Suggestion.allByOpportunityId('op-12345');
|
|
163
|
+
// Returns: Suggestion[] (all matching results)
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
#### Manual Pagination with Cursor
|
|
167
|
+
```js
|
|
168
|
+
// Fetch first page
|
|
169
|
+
const firstPage = await Suggestion.allByOpportunityIdAndStatus(
|
|
170
|
+
'op-12345',
|
|
171
|
+
'NEW',
|
|
172
|
+
{ limit: 50, returnCursor: true }
|
|
173
|
+
);
|
|
174
|
+
// Returns: { data: Suggestion[], cursor: string | null }
|
|
175
|
+
|
|
176
|
+
console.log(`Found ${firstPage.data.length} suggestions`);
|
|
177
|
+
|
|
178
|
+
// Fetch next page if cursor exists
|
|
179
|
+
if (firstPage.cursor) {
|
|
180
|
+
const secondPage = await Suggestion.allByOpportunityIdAndStatus(
|
|
181
|
+
'op-12345',
|
|
182
|
+
'NEW',
|
|
183
|
+
{ limit: 50, cursor: firstPage.cursor, returnCursor: true }
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### Limit Results (Single Page)
|
|
189
|
+
```js
|
|
190
|
+
// Get only first 20 results (stops after first page)
|
|
191
|
+
const limitedResults = await Suggestion.allByOpportunityId(
|
|
192
|
+
'op-12345',
|
|
193
|
+
{ limit: 20, fetchAllPages: false }
|
|
194
|
+
);
|
|
195
|
+
// Returns: Suggestion[] (max 20 items)
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
#### Filter by Attributes
|
|
199
|
+
```js
|
|
200
|
+
// Fetch only specific fields
|
|
201
|
+
const suggestions = await Suggestion.allByOpportunityId(
|
|
202
|
+
'op-12345',
|
|
203
|
+
{ attributes: ['suggestionId', 'status', 'rank'] }
|
|
204
|
+
);
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Exposing Pagination in TypeScript
|
|
208
|
+
|
|
209
|
+
Pagination is implemented in `BaseCollection` but must be exposed in your entity's TypeScript definitions to provide IntelliSense support for consumers.
|
|
210
|
+
|
|
211
|
+
#### Required Steps
|
|
212
|
+
|
|
213
|
+
**1. Import Required Types**
|
|
214
|
+
|
|
215
|
+
In your entity's `index.d.ts`, add these imports:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import type {
|
|
219
|
+
BaseCollection,
|
|
220
|
+
BaseModel,
|
|
221
|
+
QueryOptions, // For options parameter
|
|
222
|
+
PaginatedResult, // For return type
|
|
223
|
+
// ... other imports
|
|
224
|
+
} from '../index';
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
**2. Update Method Signatures**
|
|
228
|
+
|
|
229
|
+
For each `allBy...` method, add the `options` parameter and update the return type:
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
export interface MyEntityCollection extends BaseCollection<MyEntity> {
|
|
233
|
+
// Before: allByParentId(parentId: string): Promise<MyEntity[]>;
|
|
234
|
+
|
|
235
|
+
// After:
|
|
236
|
+
allByParentId(
|
|
237
|
+
parentId: string,
|
|
238
|
+
options?: QueryOptions
|
|
239
|
+
): Promise<MyEntity[] | PaginatedResult<MyEntity>>;
|
|
240
|
+
|
|
241
|
+
allByParentIdAndStatus(
|
|
242
|
+
parentId: string,
|
|
243
|
+
status: string,
|
|
244
|
+
options?: QueryOptions
|
|
245
|
+
): Promise<MyEntity[] | PaginatedResult<MyEntity>>;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
**3. Update `findBy...` Methods (Optional)**
|
|
250
|
+
|
|
251
|
+
For `findBy...` methods, add the `options` parameter (keeps single-item return type):
|
|
252
|
+
|
|
253
|
+
```typescript
|
|
254
|
+
export interface MyEntityCollection extends BaseCollection<MyEntity> {
|
|
255
|
+
findByParentId(
|
|
256
|
+
parentId: string,
|
|
257
|
+
options?: QueryOptions
|
|
258
|
+
): Promise<MyEntity | null>;
|
|
259
|
+
}
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
#### Complete Example
|
|
263
|
+
|
|
264
|
+
```typescript
|
|
265
|
+
import type {
|
|
266
|
+
BaseCollection, BaseModel, QueryOptions, PaginatedResult,
|
|
267
|
+
} from '../index';
|
|
268
|
+
|
|
269
|
+
export interface Suggestion extends BaseModel {
|
|
270
|
+
getStatus(): string;
|
|
271
|
+
setStatus(status: string): Suggestion;
|
|
272
|
+
// ... other methods
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export interface SuggestionCollection extends BaseCollection<Suggestion> {
|
|
276
|
+
// With pagination support
|
|
277
|
+
allByOpportunityId(
|
|
278
|
+
opportunityId: string,
|
|
279
|
+
options?: QueryOptions
|
|
280
|
+
): Promise<Suggestion[] | PaginatedResult<Suggestion>>;
|
|
281
|
+
|
|
282
|
+
allByOpportunityIdAndStatus(
|
|
283
|
+
opportunityId: string,
|
|
284
|
+
status: string,
|
|
285
|
+
options?: QueryOptions
|
|
286
|
+
): Promise<Suggestion[] | PaginatedResult<Suggestion>>;
|
|
287
|
+
|
|
288
|
+
findByOpportunityId(
|
|
289
|
+
opportunityId: string,
|
|
290
|
+
options?: QueryOptions
|
|
291
|
+
): Promise<Suggestion | null>;
|
|
292
|
+
}
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### Type-Safe Result Handling
|
|
296
|
+
|
|
297
|
+
TypeScript will correctly infer the return type based on usage:
|
|
298
|
+
|
|
299
|
+
```typescript
|
|
300
|
+
// Returns Suggestion[]
|
|
301
|
+
const all = await Suggestion.allByOpportunityId('op-12345');
|
|
302
|
+
|
|
303
|
+
// Returns { data: Suggestion[], cursor: string | null }
|
|
304
|
+
const page = await Suggestion.allByOpportunityId(
|
|
305
|
+
'op-12345',
|
|
306
|
+
{ limit: 50, returnCursor: true }
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
// Type guard for handling both cases
|
|
310
|
+
if (Array.isArray(result)) {
|
|
311
|
+
// result is Suggestion[]
|
|
312
|
+
console.log(result.length);
|
|
313
|
+
} else {
|
|
314
|
+
// result is PaginatedResult<Suggestion>
|
|
315
|
+
console.log(result.data.length, result.cursor);
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
119
319
|
## Step-by-Step: Adding a New Entity
|
|
120
320
|
|
|
121
321
|
Follow these steps to introduce a new entity into the framework.
|