@simtlix/simfinity-js-client 1.0.1 → 1.0.6

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 CHANGED
@@ -16,16 +16,29 @@ import SimfinityClient from '@simtlix/simfinity-js-client';
16
16
  const client = new SimfinityClient('http://localhost:3000/graphql');
17
17
  await client.init();
18
18
 
19
+ // Optional: attach auth headers (perform login in your app; this client does not include login)
20
+ const tokenStore = { accessToken: null };
21
+ const authedClient = new SimfinityClient('http://localhost:3000/graphql', {
22
+ prepareHeaders(headers) {
23
+ if (tokenStore.accessToken) {
24
+ headers['Authorization'] = `Bearer ${tokenStore.accessToken}`;
25
+ }
26
+ },
27
+ });
28
+ await authedClient.init();
29
+
19
30
  const series = await client.find('serie').exec();
20
31
  console.log(series);
21
32
  ```
22
33
 
23
34
  ## API Reference
24
35
 
25
- ### `new SimfinityClient(endpoint)`
36
+ ### `new SimfinityClient(endpoint [, options])`
26
37
 
27
38
  Creates a new client instance pointing at the given GraphQL endpoint.
28
39
 
40
+ - **`options.prepareHeaders(headers)`** (optional): invoked before every GraphQL HTTP request. Mutate the plain `headers` object to add credentials (for example `Authorization`). The client does not implement login — call your auth API separately, then set tokens in a closure or store that `prepareHeaders` reads.
41
+
29
42
  ### `client.init()`
30
43
 
31
44
  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.**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simtlix/simfinity-js-client",
3
- "version": "1.0.1",
3
+ "version": "1.0.6",
4
4
  "description": "Introspection-driven GraphQL client for simfinity-js APIs",
5
5
  "type": "module",
6
6
  "main": "src/SimfinityClient.js",
@@ -268,6 +268,12 @@ class QueryBuilder {
268
268
  return this;
269
269
  }
270
270
 
271
+ clearSort() {
272
+ this._sortTerms = [];
273
+ delete this._variables.sort;
274
+ return this;
275
+ }
276
+
271
277
  autoSelect() {
272
278
  const result = this._client.buildSelectionSet(this._typeName);
273
279
  this._hasExplicitFields = true;
@@ -312,7 +318,7 @@ class QueryBuilder {
312
318
  const query = `query${varDefsStr} { ${queryInfo.name}${argsBlock} { ${selectionSet} } }`;
313
319
 
314
320
  const response = await this._client._sendRequest(query, variables);
315
- if (response.errors) {
321
+ if (response.errors && !response.data?.[queryInfo.name]) {
316
322
  const error = new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`);
317
323
  error.graphQLErrors = response.errors;
318
324
  throw error;
@@ -361,7 +367,7 @@ class QueryBuilder {
361
367
  const query = `query${varDefsStr} { ${queryInfo.name}${argsBlock} { ${selectionSet} } }`;
362
368
 
363
369
  const response = await this._client._sendRequest(query, variables);
364
- if (response.errors) {
370
+ if (response.errors && !response.data?.[queryInfo.name]) {
365
371
  const error = new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`);
366
372
  error.graphQLErrors = response.errors;
367
373
  throw error;
@@ -475,7 +481,14 @@ class AggregateBuilder {
475
481
  // ---------------------------------------------------------------------------
476
482
 
477
483
  export default class SimfinityClient {
478
- constructor(endpoint) {
484
+ /**
485
+ * @param {string} endpoint GraphQL HTTP endpoint URL
486
+ * @param {{ prepareHeaders?: (headers: Record<string, string>) => void }} [options]
487
+ * Optional `prepareHeaders` runs before each request; mutate `headers` to add auth
488
+ * (e.g. `headers['Authorization'] = 'Bearer …'`). Login is not part of this client —
489
+ * perform auth in your app and set tokens inside this callback or a closure it sees.
490
+ */
491
+ constructor(endpoint, options = {}) {
479
492
  this._endpoint = endpoint;
480
493
  this._types = new Map();
481
494
  this._queries = new Map();
@@ -485,6 +498,8 @@ export default class SimfinityClient {
485
498
  this._typeNameToAggregate = new Map();
486
499
  this._queryNameToType = new Map();
487
500
  this._initialized = false;
501
+ this._prepareHeaders =
502
+ typeof options.prepareHeaders === 'function' ? options.prepareHeaders : null;
488
503
  }
489
504
 
490
505
  // -- Initialization ------------------------------------------------------
@@ -658,9 +673,13 @@ export default class SimfinityClient {
658
673
  if (variables && Object.keys(variables).length > 0) {
659
674
  body.variables = variables;
660
675
  }
676
+ const headers = { 'Content-Type': 'application/json' };
677
+ if (this._prepareHeaders) {
678
+ this._prepareHeaders(headers);
679
+ }
661
680
  const response = await _fetch(this._endpoint, {
662
681
  method: 'POST',
663
- headers: { 'Content-Type': 'application/json' },
682
+ headers,
664
683
  body: JSON.stringify(body),
665
684
  });
666
685
  return response.json();
@@ -750,7 +769,7 @@ export default class SimfinityClient {
750
769
  const query = `query($id: ${idType}) { ${queryInfo.name}(id: $id) { ${selectionSet} } }`;
751
770
  const response = await this._sendRequest(query, { id });
752
771
 
753
- if (response.errors) {
772
+ if (response.errors && !response.data?.[queryInfo.name]) {
754
773
  const error = new Error(`GraphQL errors: ${JSON.stringify(response.errors)}`);
755
774
  error.graphQLErrors = response.errors;
756
775
  throw error;