@simtlix/simfinity-js-client 1.0.0 → 1.0.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/IMPLEMENTATION_PROMPT.md +1137 -0
- package/README.md +195 -5
- package/examples/demo.js +146 -0
- package/package.json +3 -3
- package/simtlix-simfinity-js-client-1.0.0.tgz +0 -0
- package/src/SimfinityClient.js +675 -17
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @simtlix/simfinity-js-client
|
|
2
2
|
|
|
3
|
-
Introspection-driven GraphQL client for [simfinity-js](https://github.com/simtlix/simfinity.js) APIs. It discovers your schema at runtime via introspection and exposes a chainable query builder, CRUD helpers, aggregate queries,
|
|
3
|
+
Introspection-driven GraphQL client for [simfinity-js](https://github.com/simtlix/simfinity.js) APIs. It discovers your schema at runtime via introspection and exposes a chainable query builder, CRUD helpers, aggregate queries, state-machine transitions, schema metadata access, mutation input transformation, and more — no code generation required.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -28,7 +28,7 @@ Creates a new client instance pointing at the given GraphQL endpoint.
|
|
|
28
28
|
|
|
29
29
|
### `client.init()`
|
|
30
30
|
|
|
31
|
-
Runs an introspection query against the endpoint and builds internal registries of types, queries, and mutations. **Must be called before any other method.**
|
|
31
|
+
Runs an introspection query against the endpoint and builds internal registries of types, queries, and mutations — including Simfinity-specific field extensions (relation metadata, state machine flags, read-only markers). **Must be called before any other method.**
|
|
32
32
|
|
|
33
33
|
### Schema Inspection
|
|
34
34
|
|
|
@@ -58,7 +58,7 @@ const results = await client.find('serie')
|
|
|
58
58
|
|
|
59
59
|
#### `.where(field, operator, value [, value2])`
|
|
60
60
|
|
|
61
|
-
Filter by a scalar field. Supported operators depend on the server schema (e.g. `EQ`, `NE`, `GT`, `LT`, `GTE`, `LTE`, `BETWEEN`, `LIKE`).
|
|
61
|
+
Filter by a scalar field. Supported operators depend on the server schema (e.g. `EQ`, `NE`, `GT`, `LT`, `GTE`, `LTE`, `BETWEEN`, `LIKE`, `NIN`).
|
|
62
62
|
|
|
63
63
|
#### `.where(field, terms)`
|
|
64
64
|
|
|
@@ -82,14 +82,42 @@ Include a related collection's fields. Supports dot-notation for nested joins (e
|
|
|
82
82
|
|
|
83
83
|
Space-separated list of scalar fields to select on the root type. If omitted, all scalar and enum fields are selected automatically.
|
|
84
84
|
|
|
85
|
+
#### `.autoSelect()`
|
|
86
|
+
|
|
87
|
+
Automatically builds a full selection set using schema metadata, including nested object fields with display field resolution. Returns the builder for chaining. The selection metadata is available via `builder._selectionMeta`.
|
|
88
|
+
|
|
89
|
+
```js
|
|
90
|
+
const results = await client.find('serie')
|
|
91
|
+
.autoSelect()
|
|
92
|
+
.page(1, 10)
|
|
93
|
+
.exec();
|
|
94
|
+
```
|
|
95
|
+
|
|
85
96
|
#### `.page(page, size [, count])`
|
|
86
97
|
|
|
87
|
-
Paginate results. `page` is 1-based.
|
|
98
|
+
Paginate results. `page` is 1-based. Set `count` to `true` to include total count in response extensions.
|
|
88
99
|
|
|
89
100
|
#### `.sort(field, order)`
|
|
90
101
|
|
|
91
102
|
Sort results. `order` is `'ASC'` or `'DESC'`. Can be called multiple times for multi-field sorting.
|
|
92
103
|
|
|
104
|
+
#### `.exec()`
|
|
105
|
+
|
|
106
|
+
Executes the query and returns the result array. If the server returns extensions (e.g. pagination count), they are attached as `result.__extensions`.
|
|
107
|
+
|
|
108
|
+
#### `.execWithMeta()`
|
|
109
|
+
|
|
110
|
+
Executes the query and returns a `{ data, extensions }` wrapper for clean access to response metadata:
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
const { data: series, extensions } = await client.find('serie')
|
|
114
|
+
.page(1, 10, true)
|
|
115
|
+
.execWithMeta();
|
|
116
|
+
|
|
117
|
+
console.log(series); // the result array
|
|
118
|
+
console.log(extensions?.count); // total count from server
|
|
119
|
+
```
|
|
120
|
+
|
|
93
121
|
---
|
|
94
122
|
|
|
95
123
|
### Aggregate Builder — `client.aggregate(typeName)`
|
|
@@ -130,6 +158,44 @@ If `fields` is omitted, all scalar fields are returned.
|
|
|
130
158
|
|
|
131
159
|
---
|
|
132
160
|
|
|
161
|
+
### Collection Item Queries — `client.findByParent()`
|
|
162
|
+
|
|
163
|
+
Query collection items filtered by their parent entity:
|
|
164
|
+
|
|
165
|
+
```js
|
|
166
|
+
const seasons = await client.findByParent('season', 'serie', parentSerieId)
|
|
167
|
+
.page(1, 10, true)
|
|
168
|
+
.fields('id number year state')
|
|
169
|
+
.exec();
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Returns a `QueryBuilder` pre-configured with a connection field filter and default sort by `id ASC`. Chain additional `.where()`, `.page()`, `.fields()`, `.sort()` as needed.
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
### FK/Relation Search — `client.search()`
|
|
177
|
+
|
|
178
|
+
Search-as-you-type for FK reference fields:
|
|
179
|
+
|
|
180
|
+
```js
|
|
181
|
+
const results = await client.search('Genre', 'com', {
|
|
182
|
+
displayField: 'name',
|
|
183
|
+
page: 1,
|
|
184
|
+
size: 10,
|
|
185
|
+
});
|
|
186
|
+
// [{ id: '1', name: 'Comedy' }, { id: '2', name: 'Romantic Comedy' }]
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Automatically selects the appropriate operator (`LIKE` for strings, `EQ` for numeric/boolean) and casts the search term to the field's scalar type.
|
|
190
|
+
|
|
191
|
+
| Option | Default | Description |
|
|
192
|
+
|---|---|---|
|
|
193
|
+
| `displayField` | auto-resolved (`name` or first scalar) | Field to search by |
|
|
194
|
+
| `page` | `1` | Page number |
|
|
195
|
+
| `size` | `10` | Page size |
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
133
199
|
### CRUD Mutations
|
|
134
200
|
|
|
135
201
|
```js
|
|
@@ -140,6 +206,56 @@ const updated = await client.update('star', createdId, { name: 'Jane Doe' }, 'id
|
|
|
140
206
|
const deleted = await client.delete('star', createdId, 'id name');
|
|
141
207
|
```
|
|
142
208
|
|
|
209
|
+
#### Automatic Input Transformation
|
|
210
|
+
|
|
211
|
+
Pass `{ transform: true }` as the last argument to have the client automatically clean mutation input based on schema metadata — stripping `__typename`, coercing scalar types, extracting FK IDs, handling embedded objects, and skipping read-only/state-machine fields:
|
|
212
|
+
|
|
213
|
+
```js
|
|
214
|
+
const created = await client.add('serie', rawFormData, 'id name', { transform: true });
|
|
215
|
+
|
|
216
|
+
const updated = await client.update('serie', id, rawFormData, 'id name', {
|
|
217
|
+
transform: true,
|
|
218
|
+
skipFields: ['temporaryField'],
|
|
219
|
+
});
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
### Mutation Input Transformation — `client.transformInput()`
|
|
225
|
+
|
|
226
|
+
Schema-aware mutation input cleaning, usable standalone:
|
|
227
|
+
|
|
228
|
+
```js
|
|
229
|
+
const cleaned = client.transformInput('serie', rawInput, {
|
|
230
|
+
mode: 'create', // or 'update'
|
|
231
|
+
skipFields: [], // fields to exclude
|
|
232
|
+
transientFields: [], // transient fields to exclude
|
|
233
|
+
});
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
Handles: `__typename` removal, numeric/date coercion, embedded object cleaning, FK reference extraction (`{ id }` only), and skipping read-only, state-machine, and collection fields.
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
### Collection Delta Mutations — `client.transformCollectionDelta()`
|
|
241
|
+
|
|
242
|
+
Build the `{ added, updated, deleted }` structure for collection field mutations:
|
|
243
|
+
|
|
244
|
+
```js
|
|
245
|
+
const delta = {
|
|
246
|
+
added: [{ id: 'temp_1', number: '3', year: '2025', __status: 'added' }],
|
|
247
|
+
updated: [{ id: 'real-id', number: '2', year: '2024', __status: 'modified' }],
|
|
248
|
+
deleted: [{ id: 'del-id' }],
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const cleaned = client.transformCollectionDelta('season', delta, {
|
|
252
|
+
connectionField: 'serie',
|
|
253
|
+
});
|
|
254
|
+
// { added: [{ number: 3, year: 2025 }], updated: [{ id: 'real-id', number: 2, year: 2024 }], deleted: ['del-id'] }
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
Strips metadata (`__status`, `__originalData`, `__typename`), removes temporary IDs and connection fields, coerces scalar types, and extracts FK object IDs.
|
|
258
|
+
|
|
143
259
|
---
|
|
144
260
|
|
|
145
261
|
### State Machine Transitions
|
|
@@ -175,9 +291,83 @@ console.log(response.data);
|
|
|
175
291
|
|
|
176
292
|
---
|
|
177
293
|
|
|
294
|
+
### Selection Set Building — `client.buildSelectionSet()`
|
|
295
|
+
|
|
296
|
+
Generate a complete GraphQL selection set string with metadata from the schema, useful for building dynamic UIs:
|
|
297
|
+
|
|
298
|
+
```js
|
|
299
|
+
const { selection, columns, sortFieldByColumn, fieldTypeByColumn } =
|
|
300
|
+
client.buildSelectionSet('serie');
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Returns:
|
|
304
|
+
|
|
305
|
+
| Property | Type | Description |
|
|
306
|
+
|---|---|---|
|
|
307
|
+
| `selection` | `string` | GraphQL selection set string (includes nested object sub-selections) |
|
|
308
|
+
| `columns` | `string[]` | Display column names (excludes `id`) |
|
|
309
|
+
| `sortFieldByColumn` | `object` | Maps column name to sort field path (e.g. `director` -> `director.name`) |
|
|
310
|
+
| `fieldTypeByColumn` | `object` | Maps column name to scalar type name |
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
### Schema Metadata Access
|
|
315
|
+
|
|
316
|
+
#### Field Extensions
|
|
317
|
+
|
|
318
|
+
```js
|
|
319
|
+
const ext = client.getFieldExtensions('serie', 'director');
|
|
320
|
+
// { relation: { displayField: 'name', embedded: true, connectionField: null }, stateMachine: null, readOnly: null }
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
| Method | Signature | Description |
|
|
324
|
+
|---|---|---|
|
|
325
|
+
| `getFieldExtensions` | `(typeName, fieldName)` | Full extensions object for a field |
|
|
326
|
+
| `getDisplayField` | `(typeName, fieldName)` | Display field with fallback chain (extension -> `name` -> first scalar) |
|
|
327
|
+
| `isEmbeddedField` | `(typeName, fieldName)` | Whether the field is an embedded object |
|
|
328
|
+
| `getConnectionField` | `(typeName, fieldName)` | Back-reference field name for collections |
|
|
329
|
+
| `isStateMachineField` | `(typeName, fieldName)` | Whether the field is state-machine managed |
|
|
330
|
+
| `isReadOnlyField` | `(typeName, fieldName)` | Whether the field is read-only |
|
|
331
|
+
| `getEnumValues` | `(typeName)` | Enum values for an enum type |
|
|
332
|
+
| `getFieldsOfType` | `(typeName)` | All fields with full metadata |
|
|
333
|
+
| `getDescriptionFieldType` | `(typeName, fieldName)` | Scalar type name of a display field |
|
|
334
|
+
|
|
335
|
+
#### Entity & Query Name Resolution
|
|
336
|
+
|
|
337
|
+
```js
|
|
338
|
+
client.getTypeNameForQuery('series'); // 'serie'
|
|
339
|
+
client.getPluralQueryName('serie'); // 'series'
|
|
340
|
+
client.getSingularQueryName('serie'); // 'serie'
|
|
341
|
+
client.getListEntityNames(); // ['episodes', 'seasons', 'series', 'stars', ...]
|
|
342
|
+
client.getListEntityNamesOfType('serie'); // ['series']
|
|
343
|
+
client.getQueryNamesForType('serie');
|
|
344
|
+
// { pluralQueryName: 'series', singularQueryName: 'serie', aggregateQueryName: 'series_aggregate' }
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
#### Scalar Type Utilities
|
|
348
|
+
|
|
349
|
+
Simfinity uses validated scalar names like `SeasonNumber_Int` where the suffix after `_` indicates the base type:
|
|
350
|
+
|
|
351
|
+
```js
|
|
352
|
+
client.getActualScalarType('SeasonNumber_Int'); // 'Int'
|
|
353
|
+
client.isNumericScalar('SeasonNumber_Int'); // true
|
|
354
|
+
client.isBooleanScalar('Boolean'); // true
|
|
355
|
+
client.isDateTimeScalar('StartDate_DateTime'); // true
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
#### State Machine Metadata
|
|
359
|
+
|
|
360
|
+
```js
|
|
361
|
+
client.getStateMachineFields('season'); // ['state']
|
|
362
|
+
client.getAvailableTransitions('season');
|
|
363
|
+
// [{ action: 'activate', mutationName: 'activate_season' }, { action: 'finalize', mutationName: 'finalize_season' }]
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
---
|
|
367
|
+
|
|
178
368
|
## Examples
|
|
179
369
|
|
|
180
|
-
See [`examples/demo.js`](examples/demo.js) for a comprehensive walkthrough covering all features: schema discovery, filtering, joins, pagination, sorting, CRUD, state machine transitions, aggregates, and
|
|
370
|
+
See [`examples/demo.js`](examples/demo.js) for a comprehensive walkthrough covering all features: schema discovery, filtering, joins, pagination, sorting, CRUD, state machine transitions, aggregates, raw queries, schema metadata, selection set building, entity resolution, input transformation, collection deltas, parent queries, FK search, and response extensions.
|
|
181
371
|
|
|
182
372
|
```bash
|
|
183
373
|
GRAPHQL_ENDPOINT=http://localhost:3000/graphql npm run demo
|
package/examples/demo.js
CHANGED
|
@@ -198,6 +198,152 @@ const log = (label, data) => {
|
|
|
198
198
|
.exec();
|
|
199
199
|
log('17. aggregate("episode") -- count episodes per season', aggFiltered);
|
|
200
200
|
|
|
201
|
+
// -----------------------------------------------------------------------
|
|
202
|
+
// 18. Scalar type utilities (Feature 2)
|
|
203
|
+
// -----------------------------------------------------------------------
|
|
204
|
+
log('18. Scalar type utilities', {
|
|
205
|
+
'getActualScalarType("SeasonNumber_Int")': client.getActualScalarType('SeasonNumber_Int'),
|
|
206
|
+
'getActualScalarType("StartDate_Date")': client.getActualScalarType('StartDate_Date'),
|
|
207
|
+
'isNumericScalar("SeasonNumber_Int")': client.isNumericScalar('SeasonNumber_Int'),
|
|
208
|
+
'isNumericScalar("String")': client.isNumericScalar('String'),
|
|
209
|
+
'isBooleanScalar("Boolean")': client.isBooleanScalar('Boolean'),
|
|
210
|
+
'isDateTimeScalar("EpisodeDate_DateTime")': client.isDateTimeScalar('EpisodeDate_DateTime'),
|
|
211
|
+
'isDateTimeScalar("Int")': client.isDateTimeScalar('Int'),
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
// -----------------------------------------------------------------------
|
|
215
|
+
// 19. Schema metadata access (Feature 3)
|
|
216
|
+
// -----------------------------------------------------------------------
|
|
217
|
+
const serieType = client.getTypes()['serie'] ? 'serie' : 'Serie';
|
|
218
|
+
const serieFields = client.getFieldsOfType(serieType);
|
|
219
|
+
log('19. Schema metadata -- getFieldsOfType(' + serieType + ')', serieFields.map(f => ({
|
|
220
|
+
name: f.name,
|
|
221
|
+
kind: f.type.kind,
|
|
222
|
+
typeName: f.type.name,
|
|
223
|
+
extensions: f.extensions,
|
|
224
|
+
})));
|
|
225
|
+
|
|
226
|
+
const objectFields = serieFields.filter(f => f.type.kind === 'OBJECT');
|
|
227
|
+
if (objectFields.length > 0) {
|
|
228
|
+
const objField = objectFields[0];
|
|
229
|
+
log('19b. Schema metadata -- extensions for ' + serieType + '.' + objField.name, {
|
|
230
|
+
extensions: client.getFieldExtensions(serieType, objField.name),
|
|
231
|
+
displayField: client.getDisplayField(serieType, objField.name),
|
|
232
|
+
isEmbedded: client.isEmbeddedField(serieType, objField.name),
|
|
233
|
+
connectionField: client.getConnectionField(serieType, objField.name),
|
|
234
|
+
isStateMachine: client.isStateMachineField(serieType, objField.name),
|
|
235
|
+
isReadOnly: client.isReadOnlyField(serieType, objField.name),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// -----------------------------------------------------------------------
|
|
240
|
+
// 20. buildSelectionSet / autoSelect (Feature 4)
|
|
241
|
+
// -----------------------------------------------------------------------
|
|
242
|
+
const selSet = client.buildSelectionSet(serieType);
|
|
243
|
+
log('20. buildSelectionSet(' + serieType + ')', selSet);
|
|
244
|
+
|
|
245
|
+
const autoSelectResult = await client.find(serieType)
|
|
246
|
+
.autoSelect()
|
|
247
|
+
.page(1, 2)
|
|
248
|
+
.exec();
|
|
249
|
+
log('20b. find().autoSelect().page(1,2).exec()', autoSelectResult);
|
|
250
|
+
|
|
251
|
+
// -----------------------------------------------------------------------
|
|
252
|
+
// 21. Entity & query name resolution (Feature 5)
|
|
253
|
+
// -----------------------------------------------------------------------
|
|
254
|
+
log('21. Entity & query name resolution', {
|
|
255
|
+
listEntityNames: client.getListEntityNames(),
|
|
256
|
+
'getQueryNamesForType(serieType)': client.getQueryNamesForType(serieType),
|
|
257
|
+
'getPluralQueryName(serieType)': client.getPluralQueryName(serieType),
|
|
258
|
+
'getSingularQueryName(serieType)': client.getSingularQueryName(serieType),
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
const pluralName = client.getPluralQueryName(serieType);
|
|
262
|
+
if (pluralName) {
|
|
263
|
+
log('21b. getTypeNameForQuery("' + pluralName + '")',
|
|
264
|
+
client.getTypeNameForQuery(pluralName));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// -----------------------------------------------------------------------
|
|
268
|
+
// 22. transformInput (Feature 6)
|
|
269
|
+
// -----------------------------------------------------------------------
|
|
270
|
+
const rawInput = {
|
|
271
|
+
name: 'Test Serie',
|
|
272
|
+
categories: 'Drama',
|
|
273
|
+
year: '2025',
|
|
274
|
+
__typename: 'Serie',
|
|
275
|
+
director: { id: 'dir-123', name: 'Some Director', __typename: 'Director' },
|
|
276
|
+
};
|
|
277
|
+
const transformed = client.transformInput(serieType, rawInput, { mode: 'create' });
|
|
278
|
+
log('22. transformInput -- raw vs transformed', { rawInput, transformed });
|
|
279
|
+
|
|
280
|
+
// -----------------------------------------------------------------------
|
|
281
|
+
// 23. transformCollectionDelta (Feature 7)
|
|
282
|
+
// -----------------------------------------------------------------------
|
|
283
|
+
const seasonType = client.getTypes()['season'] ? 'season' : 'Season';
|
|
284
|
+
const delta = {
|
|
285
|
+
added: [
|
|
286
|
+
{ id: 'temp_1', number: '3', year: '2025', __typename: 'Season', __status: 'added' },
|
|
287
|
+
],
|
|
288
|
+
updated: [
|
|
289
|
+
{ id: 'real-id-1', number: '2', year: '2024', __status: 'modified' },
|
|
290
|
+
],
|
|
291
|
+
deleted: [
|
|
292
|
+
{ id: 'del-id-1' },
|
|
293
|
+
],
|
|
294
|
+
};
|
|
295
|
+
const connectionField = client.getConnectionField(serieType, 'seasons');
|
|
296
|
+
const transformedDelta = client.transformCollectionDelta(seasonType, delta, {
|
|
297
|
+
connectionField: connectionField || 'serie',
|
|
298
|
+
});
|
|
299
|
+
log('23. transformCollectionDelta', { delta, transformedDelta });
|
|
300
|
+
|
|
301
|
+
// -----------------------------------------------------------------------
|
|
302
|
+
// 24. findByParent (Feature 8)
|
|
303
|
+
// -----------------------------------------------------------------------
|
|
304
|
+
if (allSeries.length > 0) {
|
|
305
|
+
const parentId = allSeries[0].id;
|
|
306
|
+
const childSeasons = await client
|
|
307
|
+
.findByParent(seasonType, 'serie', parentId)
|
|
308
|
+
.page(1, 5, true)
|
|
309
|
+
.fields('id number year')
|
|
310
|
+
.exec();
|
|
311
|
+
log('24. findByParent(' + seasonType + ', "serie", "' + parentId + '")', childSeasons);
|
|
312
|
+
} else {
|
|
313
|
+
log('24. findByParent -- skipped (no series)', '');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// -----------------------------------------------------------------------
|
|
317
|
+
// 25. search (Feature 9)
|
|
318
|
+
// -----------------------------------------------------------------------
|
|
319
|
+
const searchResults = await client.search('star', 'a', {
|
|
320
|
+
displayField: 'name',
|
|
321
|
+
page: 1,
|
|
322
|
+
size: 5,
|
|
323
|
+
});
|
|
324
|
+
log('25. search("star", "a", { displayField: "name" })', searchResults);
|
|
325
|
+
|
|
326
|
+
// -----------------------------------------------------------------------
|
|
327
|
+
// 26. State machine metadata (Feature 10)
|
|
328
|
+
// -----------------------------------------------------------------------
|
|
329
|
+
log('26. State machine metadata', {
|
|
330
|
+
'getStateMachineFields(seasonType)': client.getStateMachineFields(seasonType),
|
|
331
|
+
'getAvailableTransitions(seasonType)': client.getAvailableTransitions(seasonType),
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// -----------------------------------------------------------------------
|
|
335
|
+
// 27. execWithMeta -- pagination count (Feature 11)
|
|
336
|
+
// -----------------------------------------------------------------------
|
|
337
|
+
const { data: pagedSeries, extensions } = await client
|
|
338
|
+
.find(serieType)
|
|
339
|
+
.page(1, 2, true)
|
|
340
|
+
.execWithMeta();
|
|
341
|
+
log('27. execWithMeta -- pagination count', {
|
|
342
|
+
data: pagedSeries,
|
|
343
|
+
extensions,
|
|
344
|
+
totalCount: extensions?.count,
|
|
345
|
+
});
|
|
346
|
+
|
|
201
347
|
console.log('\n' + '='.repeat(60));
|
|
202
348
|
console.log('Demo complete.');
|
|
203
349
|
console.log('='.repeat(60));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@simtlix/simfinity-js-client",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Introspection-driven GraphQL client for simfinity-js APIs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/SimfinityClient.js",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"type": "git",
|
|
24
24
|
"url": "https://github.com/simtlix/simfinity-js-client"
|
|
25
25
|
},
|
|
26
|
-
"
|
|
27
|
-
"node
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
28
|
}
|
|
29
29
|
}
|
|
Binary file
|