@robosystems/client 0.6.2 → 1.0.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/README.md CHANGED
@@ -10,9 +10,9 @@ Official TypeScript Client for the RoboSystems Financial Knowledge Graph API. Ac
10
10
  - **Type-safe API client** with full TypeScript types
11
11
  - **Browser & Node.js support** with different auth strategies
12
12
  - **React hooks** for seamless UI integration
13
- - **Table ingestion** with simplified Parquet file uploads
13
+ - **High-level domain clients** for RoboLedger, RoboInvestor, and the element library
14
14
  - **Streaming support** for memory-efficient processing of large result sets
15
- - **Financial AI Agent** integration for natural language queries
15
+ - **AI Operator** integration for natural language financial analysis
16
16
  - **Comprehensive error handling** with typed errors
17
17
 
18
18
  ## Installation
@@ -1,6 +1,7 @@
1
1
  import type { CreatePortfolioBlockRequest, CreateSecurityRequest, PortfolioBlockPortfolioPatch, PortfolioBlockPositions, UpdateSecurityOperation } from '../types.gen';
2
2
  import type { TokenProvider } from './graphql/client';
3
3
  import { type GetInvestorHoldingsQuery, type GetInvestorPortfolioBlockQuery, type GetInvestorPositionQuery, type GetInvestorSecurityQuery, type ListInvestorPortfoliosQuery, type ListInvestorPositionsQuery, type ListInvestorSecuritiesQuery } from './graphql/generated/graphql';
4
+ export { GraphQLError } from './graphql/client';
4
5
  export type InvestorPortfolioList = NonNullable<ListInvestorPortfoliosQuery['portfolios']>;
5
6
  export type InvestorPortfolioSummary = InvestorPortfolioList['portfolios'][number];
6
7
  export type InvestorPortfolioBlock = NonNullable<GetInvestorPortfolioBlockQuery['portfolioBlock']>;
@@ -27,6 +28,8 @@ interface InvestorClientConfig {
27
28
  * request so refreshes flow through automatically.
28
29
  */
29
30
  tokenProvider?: TokenProvider;
31
+ /** GraphQL request timeout in milliseconds (default 60s). */
32
+ timeout?: number;
30
33
  }
31
34
  export declare class InvestorClient {
32
35
  private config;
@@ -110,4 +113,3 @@ export declare class InvestorClient {
110
113
  private gqlQuery;
111
114
  private callOperation;
112
115
  }
113
- export {};
@@ -1,11 +1,15 @@
1
1
  'use client';
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.InvestorClient = void 0;
4
+ exports.InvestorClient = exports.GraphQLError = void 0;
5
5
  const graphql_request_1 = require("graphql-request");
6
6
  const sdk_gen_1 = require("../sdk.gen");
7
7
  const client_1 = require("./graphql/client");
8
8
  const graphql_1 = require("./graphql/generated/graphql");
9
+ // Re-export the structured GraphQL error type so consumers importing
10
+ // from the `@robosystems/client/investor` subpath can `instanceof` it.
11
+ var client_2 = require("./graphql/client");
12
+ Object.defineProperty(exports, "GraphQLError", { enumerable: true, get: function () { return client_2.GraphQLError; } });
9
13
  class InvestorClient {
10
14
  constructor(config) {
11
15
  this.config = config;
@@ -141,7 +145,7 @@ class InvestorClient {
141
145
  }
142
146
  catch (err) {
143
147
  if (err instanceof graphql_request_1.ClientError) {
144
- throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`);
148
+ throw (0, client_1.toGraphQLError)(label, err);
145
149
  }
146
150
  throw err;
147
151
  }
@@ -42,7 +42,7 @@ import type {
42
42
  UpdateSecurityOperation,
43
43
  } from '../types.gen'
44
44
  import type { TokenProvider } from './graphql/client'
45
- import { GraphQLClientCache } from './graphql/client'
45
+ import { GraphQLClientCache, toGraphQLError } from './graphql/client'
46
46
  import {
47
47
  GetInvestorHoldingsDocument,
48
48
  GetInvestorPortfolioBlockDocument,
@@ -60,6 +60,10 @@ import {
60
60
  type ListInvestorSecuritiesQuery,
61
61
  } from './graphql/generated/graphql'
62
62
 
63
+ // Re-export the structured GraphQL error type so consumers importing
64
+ // from the `@robosystems/client/investor` subpath can `instanceof` it.
65
+ export { GraphQLError } from './graphql/client'
66
+
63
67
  // ── Friendly types derived from GraphQL codegen ────────────────────────
64
68
 
65
69
  export type InvestorPortfolioList = NonNullable<ListInvestorPortfoliosQuery['portfolios']>
@@ -95,6 +99,8 @@ interface InvestorClientConfig {
95
99
  * request so refreshes flow through automatically.
96
100
  */
97
101
  tokenProvider?: TokenProvider
102
+ /** GraphQL request timeout in milliseconds (default 60s). */
103
+ timeout?: number
98
104
  }
99
105
 
100
106
  export class InvestorClient {
@@ -363,7 +369,7 @@ export class InvestorClient {
363
369
  return pick(data)
364
370
  } catch (err) {
365
371
  if (err instanceof ClientError) {
366
- throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`)
372
+ throw toGraphQLError(label, err)
367
373
  }
368
374
  throw err
369
375
  }
@@ -1,6 +1,7 @@
1
1
  import type { AssociationResponse, AutoMapElementsOperation, BindTextBlockRequest, BindTextBlockResponse, ComputeMetricsRequest, ComputeMetricsResponse, CreateAgentRequest, CreateEventBlockRequest, CreateEventHandlerRequest, CreateInformationBlockRequest, CreateMappingAssociationOperation, CreateTaxonomyBlockRequest, CreateViewRequest, DeleteInformationBlockRequest, DeleteInformationBlockResponse, DeleteMappingAssociationOperation, DeleteResult, DeleteTaxonomyBlockRequest, DeleteTaxonomyBlockResponse, EntityTaxonomyResponse, EvaluateRulesRequest, EvaluateRulesResponse, EventBlockEnvelope, EventHandlerResponse, FinancialStatementAnalysisRequest, FinancialStatementAnalysisResponse, InformationBlockEnvelope, JournalEntryResponse, LedgerAgentResponse, LinkEntityTaxonomyRequest, LiveFinancialStatementRequest, LiveFinancialStatementResponse, OperationEnvelope, PreviewEventBlockResponse, PublishListMemberResponse, PublishListResponse, ReportResponse, ShareReportResponse, TaxonomyBlockEnvelope, UpdateAgentRequest, UpdateEntityRequest, UpdateEventBlockRequest, UpdateEventHandlerRequest, UpdateInformationBlockRequest, UpdateJournalEntryRequest, UpdateTaxonomyBlockRequest, ViewResponse } from '../types.gen';
2
2
  import type { TokenProvider } from './graphql/client';
3
3
  import { type GetInformationBlockQuery, type GetLedgerAccountRollupsQuery, type GetLedgerAccountTreeQuery, type GetLedgerAgentQuery, type GetLedgerClosingBookStructuresQuery, type GetLedgerEntityQuery, type GetLedgerEventBlockQuery, type GetLedgerFiscalCalendarQuery, type GetLedgerMappedTrialBalanceQuery, type GetLedgerMappingCoverageQuery, type GetLedgerMappingQuery, type GetLedgerPeriodCloseStatusQuery, type GetLedgerPeriodDraftsQuery, type GetLedgerPublishListQuery, type GetLedgerReportingTaxonomyQuery, type GetLedgerReportPackageQuery, type GetLedgerReportQuery, type GetLedgerStatementQuery, type GetLedgerSummaryQuery, type GetLedgerTransactionQuery, type GetLedgerTrialBalanceQuery, type ListInformationBlocksQuery, type ListLedgerAccountsQuery, type ListLedgerAgentsQuery, type ListLedgerElementsQuery, type ListLedgerEntitiesQuery, type ListLedgerEventBlocksQuery, type ListLedgerMappingsQuery, type ListLedgerPublishListsQuery, type ListLedgerReportsQuery, type ListLedgerStructuresQuery, type ListLedgerTaxonomiesQuery, type ListLedgerTransactionsQuery, type ListLedgerUnmappedElementsQuery, type MappingCandidatesQuery, type ReportDownloadFormat } from './graphql/generated/graphql';
4
+ export { GraphQLError } from './graphql/client';
4
5
  export type LedgerEntity = NonNullable<GetLedgerEntityQuery['entity']>;
5
6
  export type LedgerEntitySummary = ListLedgerEntitiesQuery['entities'][number];
6
7
  export type LedgerSummary = NonNullable<GetLedgerSummaryQuery['summary']>;
@@ -89,18 +90,6 @@ export interface CreateReportOptions {
89
90
  comparative?: boolean;
90
91
  periods?: PeriodSpecInput[];
91
92
  }
92
- /**
93
- * Wrapper returned by report write methods — pairs the audit-side
94
- * envelope fields (`operationId`, `status`) with the typed result
95
- * payload. Generic on ``T`` so each method advertises its specific
96
- * result type (e.g. ``ReportResponse`` for creates, ``DeleteResult``
97
- * for deletes).
98
- */
99
- export interface ReportOperationAck<T = unknown> {
100
- operationId: string;
101
- status: OperationEnvelope['status'];
102
- result: T | null;
103
- }
104
93
  export interface InitializeLedgerResult {
105
94
  fiscalCalendar: LedgerFiscalCalendar;
106
95
  periodsCreated: number;
@@ -218,6 +207,8 @@ interface LedgerClientConfig {
218
207
  * request so refreshes flow through automatically.
219
208
  */
220
209
  tokenProvider?: TokenProvider;
210
+ /** GraphQL request timeout in milliseconds (default 60s). */
211
+ timeout?: number;
221
212
  }
222
213
  export declare class LedgerClient {
223
214
  private config;
@@ -635,10 +626,11 @@ export declare class LedgerClient {
635
626
  */
636
627
  private gqlQuery;
637
628
  /**
638
- * Kick off report creation (async). Use the returned `operationId` to
639
- * subscribe to progress via SSE, then call `getReport()` once finished.
629
+ * Generate report facts from the ledger and publish a Report
630
+ * definition. Synchronous — the backend materializes the report
631
+ * inline and this resolves with the published report header.
640
632
  */
641
- createReport(graphId: string, options: CreateReportOptions): Promise<ReportOperationAck<ReportResponse>>;
633
+ createReport(graphId: string, options: CreateReportOptions): Promise<ReportResponse>;
642
634
  /** List all reports for a graph (includes received shared reports). */
643
635
  listReports(graphId: string): Promise<ReportListItem[]>;
644
636
  /** Get a single report with its period list + available structures. */
@@ -657,10 +649,11 @@ export declare class LedgerClient {
657
649
  */
658
650
  getStatement(graphId: string, reportId: string, blockType: string): Promise<StatementData | null>;
659
651
  /**
660
- * Regenerate an existing report (async). Returns an operation id;
661
- * subscribe via SSE for progress.
652
+ * Re-run fact generation for an existing Report against the latest
653
+ * ledger state. Synchronous — resolves with the regenerated report
654
+ * header.
662
655
  */
663
- regenerateReport(graphId: string, reportId: string, periodStart?: string, periodEnd?: string): Promise<ReportOperationAck<ReportResponse>>;
656
+ regenerateReport(graphId: string, reportId: string, periodStart?: string, periodEnd?: string): Promise<ReportResponse>;
664
657
  /** Delete a report and its generated facts. */
665
658
  deleteReport(graphId: string, reportId: string): Promise<DeleteResult>;
666
659
  /**
@@ -693,20 +686,24 @@ export declare class LedgerClient {
693
686
  /**
694
687
  * Share a published report to every member of a publish list. Each
695
688
  * target graph receives a snapshot copy of the report's facts.
689
+ * Synchronous — per-recipient outcomes appear in the response's
690
+ * `results` list.
696
691
  */
697
- shareReport(graphId: string, reportId: string, publishListId: string): Promise<ReportOperationAck<ShareReportResponse>>;
692
+ shareReport(graphId: string, reportId: string, publishListId: string): Promise<ShareReportResponse>;
698
693
  /**
699
694
  * Transition a Report's filing_status to 'filed' — locks the package.
700
695
  * Allowed from 'draft' or 'under_review'. Stamps filed_at + filed_by
701
- * from the auth context + server clock.
696
+ * from the auth context + server clock. Synchronous — resolves with
697
+ * the updated report header.
702
698
  */
703
- fileReport(graphId: string, reportId: string): Promise<ReportOperationAck<ReportResponse>>;
699
+ fileReport(graphId: string, reportId: string): Promise<ReportResponse>;
704
700
  /**
705
701
  * Move a Report along the non-file legs of the filing lifecycle
706
702
  * (draft ↔ under_review, filed → archived). Use ``fileReport`` to
707
- * reach 'filed' so the audit fields land cleanly.
703
+ * reach 'filed' so the audit fields land cleanly. Synchronous —
704
+ * resolves with the updated report header.
708
705
  */
709
- transitionFilingStatus(graphId: string, reportId: string, targetStatus: string): Promise<ReportOperationAck<ReportResponse>>;
706
+ transitionFilingStatus(graphId: string, reportId: string, targetStatus: string): Promise<ReportResponse>;
710
707
  /** Check if a report was received via sharing (vs locally created). */
711
708
  isSharedReport(report: Report): boolean;
712
709
  /** List publish lists with pagination. */
@@ -751,9 +748,10 @@ export declare class LedgerClient {
751
748
  * calls. Mirrors the GraphQL client's behaviour — dynamic
752
749
  * ``tokenProvider`` is consulted first (so JWT rotation flows
753
750
  * naturally), then the static ``token`` config. Returns ``null``
754
- * when no credential is configured; the caller decides whether to
755
- * proceed anonymously or short-circuit with an error.
751
+ * when no credential is configured (cookie-based / anonymous flows).
752
+ * A ``tokenProvider`` that **throws** fails the call fast instead of
753
+ * silently proceeding unauthenticated — matching the Python client,
754
+ * which raises when its configured credential cannot be resolved.
756
755
  */
757
756
  private resolveToken;
758
757
  }
759
- export {};
@@ -1,11 +1,15 @@
1
1
  'use client';
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.LedgerClient = void 0;
4
+ exports.LedgerClient = exports.GraphQLError = void 0;
5
5
  const graphql_request_1 = require("graphql-request");
6
6
  const sdk_gen_1 = require("../sdk.gen");
7
7
  const client_1 = require("./graphql/client");
8
8
  const graphql_1 = require("./graphql/generated/graphql");
9
+ // Re-export the structured GraphQL error type so consumers importing
10
+ // from the `@robosystems/client/ledger` subpath can `instanceof` it.
11
+ var client_2 = require("./graphql/client");
12
+ Object.defineProperty(exports, "GraphQLError", { enumerable: true, get: function () { return client_2.GraphQLError; } });
9
13
  class LedgerClient {
10
14
  constructor(config) {
11
15
  this.config = config;
@@ -790,15 +794,16 @@ class LedgerClient {
790
794
  }
791
795
  catch (err) {
792
796
  if (err instanceof graphql_request_1.ClientError) {
793
- throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`);
797
+ throw (0, client_1.toGraphQLError)(label, err);
794
798
  }
795
799
  throw err;
796
800
  }
797
801
  }
798
802
  // ── Reports ─────────────────────────────────────────────────────────
799
803
  /**
800
- * Kick off report creation (async). Use the returned `operationId` to
801
- * subscribe to progress via SSE, then call `getReport()` once finished.
804
+ * Generate report facts from the ledger and publish a Report
805
+ * definition. Synchronous — the backend materializes the report
806
+ * inline and this resolves with the published report header.
802
807
  */
803
808
  async createReport(graphId, options) {
804
809
  const body = {
@@ -814,11 +819,7 @@ class LedgerClient {
814
819
  body.periods = options.periods;
815
820
  }
816
821
  const envelope = await this.callOperation('Create report', (0, sdk_gen_1.createReport)({ path: { graph_id: graphId }, body }));
817
- return {
818
- operationId: envelope.operationId,
819
- status: envelope.status,
820
- result: envelope.result ?? null,
821
- };
822
+ return this.requireResult('Create report', envelope.result);
822
823
  }
823
824
  /** List all reports for a graph (includes received shared reports). */
824
825
  async listReports(graphId) {
@@ -847,8 +848,9 @@ class LedgerClient {
847
848
  return this.gqlQuery(graphId, graphql_1.GetLedgerStatementDocument, { reportId, blockType }, 'Get statement', (data) => data.statement);
848
849
  }
849
850
  /**
850
- * Regenerate an existing report (async). Returns an operation id;
851
- * subscribe via SSE for progress.
851
+ * Re-run fact generation for an existing Report against the latest
852
+ * ledger state. Synchronous — resolves with the regenerated report
853
+ * header.
852
854
  */
853
855
  async regenerateReport(graphId, reportId, periodStart, periodEnd) {
854
856
  const envelope = await this.callOperation('Regenerate report', (0, sdk_gen_1.regenerateReport)({
@@ -859,11 +861,7 @@ class LedgerClient {
859
861
  period_end: periodEnd,
860
862
  },
861
863
  }));
862
- return {
863
- operationId: envelope.operationId,
864
- status: envelope.status,
865
- result: envelope.result ?? null,
866
- };
864
+ return this.requireResult('Regenerate report', envelope.result);
867
865
  }
868
866
  /** Delete a report and its generated facts. */
869
867
  async deleteReport(graphId, reportId) {
@@ -917,6 +915,8 @@ class LedgerClient {
917
915
  /**
918
916
  * Share a published report to every member of a publish list. Each
919
917
  * target graph receives a snapshot copy of the report's facts.
918
+ * Synchronous — per-recipient outcomes appear in the response's
919
+ * `results` list.
920
920
  */
921
921
  async shareReport(graphId, reportId, publishListId) {
922
922
  const envelope = await this.callOperation('Share report', (0, sdk_gen_1.shareReport)({
@@ -926,30 +926,24 @@ class LedgerClient {
926
926
  publish_list_id: publishListId,
927
927
  },
928
928
  }));
929
- return {
930
- operationId: envelope.operationId,
931
- status: envelope.status,
932
- result: envelope.result ?? null,
933
- };
929
+ return this.requireResult('Share report', envelope.result);
934
930
  }
935
931
  /**
936
932
  * Transition a Report's filing_status to 'filed' — locks the package.
937
933
  * Allowed from 'draft' or 'under_review'. Stamps filed_at + filed_by
938
- * from the auth context + server clock.
934
+ * from the auth context + server clock. Synchronous — resolves with
935
+ * the updated report header.
939
936
  */
940
937
  async fileReport(graphId, reportId) {
941
938
  const body = { report_id: reportId };
942
939
  const envelope = await this.callOperation('File report', (0, sdk_gen_1.fileReport)({ path: { graph_id: graphId }, body }));
943
- return {
944
- operationId: envelope.operationId,
945
- status: envelope.status,
946
- result: envelope.result ?? null,
947
- };
940
+ return this.requireResult('File report', envelope.result);
948
941
  }
949
942
  /**
950
943
  * Move a Report along the non-file legs of the filing lifecycle
951
944
  * (draft ↔ under_review, filed → archived). Use ``fileReport`` to
952
- * reach 'filed' so the audit fields land cleanly.
945
+ * reach 'filed' so the audit fields land cleanly. Synchronous —
946
+ * resolves with the updated report header.
953
947
  */
954
948
  async transitionFilingStatus(graphId, reportId, targetStatus) {
955
949
  const body = {
@@ -957,11 +951,7 @@ class LedgerClient {
957
951
  target_status: targetStatus,
958
952
  };
959
953
  const envelope = await this.callOperation('Transition filing status', (0, sdk_gen_1.transitionFilingStatus)({ path: { graph_id: graphId }, body }));
960
- return {
961
- operationId: envelope.operationId,
962
- status: envelope.status,
963
- result: envelope.result ?? null,
964
- };
954
+ return this.requireResult('Transition filing status', envelope.result);
965
955
  }
966
956
  /** Check if a report was received via sharing (vs locally created). */
967
957
  isSharedReport(report) {
@@ -1065,19 +1055,24 @@ class LedgerClient {
1065
1055
  * calls. Mirrors the GraphQL client's behaviour — dynamic
1066
1056
  * ``tokenProvider`` is consulted first (so JWT rotation flows
1067
1057
  * naturally), then the static ``token`` config. Returns ``null``
1068
- * when no credential is configured; the caller decides whether to
1069
- * proceed anonymously or short-circuit with an error.
1058
+ * when no credential is configured (cookie-based / anonymous flows).
1059
+ * A ``tokenProvider`` that **throws** fails the call fast instead of
1060
+ * silently proceeding unauthenticated — matching the Python client,
1061
+ * which raises when its configured credential cannot be resolved.
1070
1062
  */
1071
1063
  async resolveToken() {
1072
1064
  if (this.config.tokenProvider) {
1065
+ let token;
1073
1066
  try {
1074
- const token = await this.config.tokenProvider();
1075
- return token ?? null;
1067
+ token = await this.config.tokenProvider();
1076
1068
  }
1077
1069
  catch (err) {
1078
- console.warn('[RoboSystems SDK] tokenProvider threw — sending unauthenticated request:', err);
1079
- return null;
1070
+ const detail = err instanceof Error ? err.message : String(err);
1071
+ throw new Error(`RoboSystems SDK: tokenProvider threw while resolving the request credential (${detail}). ` +
1072
+ 'Fix the tokenProvider passed in the client config (or via setSDKClientConfig) so it ' +
1073
+ 'returns the current token, or null to send an unauthenticated (cookie-based) request.');
1080
1074
  }
1075
+ return token ?? null;
1081
1076
  }
1082
1077
  return this.config.token ?? null;
1083
1078
  }
@@ -131,7 +131,7 @@ import type {
131
131
  ViewResponse,
132
132
  } from '../types.gen'
133
133
  import type { TokenProvider } from './graphql/client'
134
- import { GraphQLClientCache } from './graphql/client'
134
+ import { GraphQLClientCache, toGraphQLError } from './graphql/client'
135
135
  import {
136
136
  GetInformationBlockDocument,
137
137
  GetInformationBlockWindowedDocument,
@@ -208,6 +208,10 @@ import {
208
208
  type ReportDownloadFormat,
209
209
  } from './graphql/generated/graphql'
210
210
 
211
+ // Re-export the structured GraphQL error type so consumers importing
212
+ // from the `@robosystems/client/ledger` subpath can `instanceof` it.
213
+ export { GraphQLError } from './graphql/client'
214
+
211
215
  // ── Friendly types derived from GraphQL codegen ────────────────────────
212
216
  //
213
217
  // These are the single source of truth for read payload shapes. Write
@@ -334,19 +338,6 @@ export interface CreateReportOptions {
334
338
  periods?: PeriodSpecInput[]
335
339
  }
336
340
 
337
- /**
338
- * Wrapper returned by report write methods — pairs the audit-side
339
- * envelope fields (`operationId`, `status`) with the typed result
340
- * payload. Generic on ``T`` so each method advertises its specific
341
- * result type (e.g. ``ReportResponse`` for creates, ``DeleteResult``
342
- * for deletes).
343
- */
344
- export interface ReportOperationAck<T = unknown> {
345
- operationId: string
346
- status: OperationEnvelope['status']
347
- result: T | null
348
- }
349
-
350
341
  // ── Write result shapes (envelope.result payloads) ─────────────────────
351
342
  //
352
343
  // Backend Pydantic models serialize these write results in snake_case.
@@ -536,6 +527,8 @@ interface LedgerClientConfig {
536
527
  * request so refreshes flow through automatically.
537
528
  */
538
529
  tokenProvider?: TokenProvider
530
+ /** GraphQL request timeout in milliseconds (default 60s). */
531
+ timeout?: number
539
532
  }
540
533
 
541
534
  export class LedgerClient {
@@ -1941,7 +1934,7 @@ export class LedgerClient {
1941
1934
  return pick(data)
1942
1935
  } catch (err) {
1943
1936
  if (err instanceof ClientError) {
1944
- throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`)
1937
+ throw toGraphQLError(label, err)
1945
1938
  }
1946
1939
  throw err
1947
1940
  }
@@ -1950,13 +1943,11 @@ export class LedgerClient {
1950
1943
  // ── Reports ─────────────────────────────────────────────────────────
1951
1944
 
1952
1945
  /**
1953
- * Kick off report creation (async). Use the returned `operationId` to
1954
- * subscribe to progress via SSE, then call `getReport()` once finished.
1946
+ * Generate report facts from the ledger and publish a Report
1947
+ * definition. Synchronous — the backend materializes the report
1948
+ * inline and this resolves with the published report header.
1955
1949
  */
1956
- async createReport(
1957
- graphId: string,
1958
- options: CreateReportOptions
1959
- ): Promise<ReportOperationAck<ReportResponse>> {
1950
+ async createReport(graphId: string, options: CreateReportOptions): Promise<ReportResponse> {
1960
1951
  const body: CreateReportRequest = {
1961
1952
  name: options.name,
1962
1953
  mapping_id: options.mappingId,
@@ -1973,11 +1964,7 @@ export class LedgerClient {
1973
1964
  'Create report',
1974
1965
  createReport({ path: { graph_id: graphId }, body })
1975
1966
  )
1976
- return {
1977
- operationId: envelope.operationId,
1978
- status: envelope.status,
1979
- result: envelope.result ?? null,
1980
- }
1967
+ return this.requireResult('Create report', envelope.result)
1981
1968
  }
1982
1969
 
1983
1970
  /** List all reports for a graph (includes received shared reports). */
@@ -2039,15 +2026,16 @@ export class LedgerClient {
2039
2026
  }
2040
2027
 
2041
2028
  /**
2042
- * Regenerate an existing report (async). Returns an operation id;
2043
- * subscribe via SSE for progress.
2029
+ * Re-run fact generation for an existing Report against the latest
2030
+ * ledger state. Synchronous — resolves with the regenerated report
2031
+ * header.
2044
2032
  */
2045
2033
  async regenerateReport(
2046
2034
  graphId: string,
2047
2035
  reportId: string,
2048
2036
  periodStart?: string,
2049
2037
  periodEnd?: string
2050
- ): Promise<ReportOperationAck<ReportResponse>> {
2038
+ ): Promise<ReportResponse> {
2051
2039
  const envelope = await this.callOperation(
2052
2040
  'Regenerate report',
2053
2041
  regenerateReport({
@@ -2059,11 +2047,7 @@ export class LedgerClient {
2059
2047
  } as Parameters<typeof regenerateReport>[0]['body'],
2060
2048
  })
2061
2049
  )
2062
- return {
2063
- operationId: envelope.operationId,
2064
- status: envelope.status,
2065
- result: envelope.result ?? null,
2066
- }
2050
+ return this.requireResult('Regenerate report', envelope.result)
2067
2051
  }
2068
2052
 
2069
2053
  /** Delete a report and its generated facts. */
@@ -2132,12 +2116,14 @@ export class LedgerClient {
2132
2116
  /**
2133
2117
  * Share a published report to every member of a publish list. Each
2134
2118
  * target graph receives a snapshot copy of the report's facts.
2119
+ * Synchronous — per-recipient outcomes appear in the response's
2120
+ * `results` list.
2135
2121
  */
2136
2122
  async shareReport(
2137
2123
  graphId: string,
2138
2124
  reportId: string,
2139
2125
  publishListId: string
2140
- ): Promise<ReportOperationAck<ShareReportResponse>> {
2126
+ ): Promise<ShareReportResponse> {
2141
2127
  const envelope = await this.callOperation(
2142
2128
  'Share report',
2143
2129
  shareReport({
@@ -2148,41 +2134,35 @@ export class LedgerClient {
2148
2134
  } as Parameters<typeof shareReport>[0]['body'],
2149
2135
  })
2150
2136
  )
2151
- return {
2152
- operationId: envelope.operationId,
2153
- status: envelope.status,
2154
- result: envelope.result ?? null,
2155
- }
2137
+ return this.requireResult('Share report', envelope.result)
2156
2138
  }
2157
2139
 
2158
2140
  /**
2159
2141
  * Transition a Report's filing_status to 'filed' — locks the package.
2160
2142
  * Allowed from 'draft' or 'under_review'. Stamps filed_at + filed_by
2161
- * from the auth context + server clock.
2143
+ * from the auth context + server clock. Synchronous — resolves with
2144
+ * the updated report header.
2162
2145
  */
2163
- async fileReport(graphId: string, reportId: string): Promise<ReportOperationAck<ReportResponse>> {
2146
+ async fileReport(graphId: string, reportId: string): Promise<ReportResponse> {
2164
2147
  const body: FileReportRequest = { report_id: reportId }
2165
2148
  const envelope = await this.callOperation(
2166
2149
  'File report',
2167
2150
  fileReport({ path: { graph_id: graphId }, body })
2168
2151
  )
2169
- return {
2170
- operationId: envelope.operationId,
2171
- status: envelope.status,
2172
- result: envelope.result ?? null,
2173
- }
2152
+ return this.requireResult('File report', envelope.result)
2174
2153
  }
2175
2154
 
2176
2155
  /**
2177
2156
  * Move a Report along the non-file legs of the filing lifecycle
2178
2157
  * (draft ↔ under_review, filed → archived). Use ``fileReport`` to
2179
- * reach 'filed' so the audit fields land cleanly.
2158
+ * reach 'filed' so the audit fields land cleanly. Synchronous —
2159
+ * resolves with the updated report header.
2180
2160
  */
2181
2161
  async transitionFilingStatus(
2182
2162
  graphId: string,
2183
2163
  reportId: string,
2184
2164
  targetStatus: string
2185
- ): Promise<ReportOperationAck<ReportResponse>> {
2165
+ ): Promise<ReportResponse> {
2186
2166
  const body: TransitionFilingStatusRequest = {
2187
2167
  report_id: reportId,
2188
2168
  target_status: targetStatus,
@@ -2191,11 +2171,7 @@ export class LedgerClient {
2191
2171
  'Transition filing status',
2192
2172
  transitionFilingStatus({ path: { graph_id: graphId }, body })
2193
2173
  )
2194
- return {
2195
- operationId: envelope.operationId,
2196
- status: envelope.status,
2197
- result: envelope.result ?? null,
2198
- }
2174
+ return this.requireResult('Transition filing status', envelope.result)
2199
2175
  }
2200
2176
 
2201
2177
  /** Check if a report was received via sharing (vs locally created). */
@@ -2361,21 +2337,25 @@ export class LedgerClient {
2361
2337
  * calls. Mirrors the GraphQL client's behaviour — dynamic
2362
2338
  * ``tokenProvider`` is consulted first (so JWT rotation flows
2363
2339
  * naturally), then the static ``token`` config. Returns ``null``
2364
- * when no credential is configured; the caller decides whether to
2365
- * proceed anonymously or short-circuit with an error.
2340
+ * when no credential is configured (cookie-based / anonymous flows).
2341
+ * A ``tokenProvider`` that **throws** fails the call fast instead of
2342
+ * silently proceeding unauthenticated — matching the Python client,
2343
+ * which raises when its configured credential cannot be resolved.
2366
2344
  */
2367
2345
  private async resolveToken(): Promise<string | null> {
2368
2346
  if (this.config.tokenProvider) {
2347
+ let token: string | null | undefined
2369
2348
  try {
2370
- const token = await this.config.tokenProvider()
2371
- return token ?? null
2349
+ token = await this.config.tokenProvider()
2372
2350
  } catch (err) {
2373
- console.warn(
2374
- '[RoboSystems SDK] tokenProvider threw — sending unauthenticated request:',
2375
- err
2351
+ const detail = err instanceof Error ? err.message : String(err)
2352
+ throw new Error(
2353
+ `RoboSystems SDK: tokenProvider threw while resolving the request credential (${detail}). ` +
2354
+ 'Fix the tokenProvider passed in the client config (or via setSDKClientConfig) so it ' +
2355
+ 'returns the current token, or null to send an unauthenticated (cookie-based) request.'
2376
2356
  )
2377
- return null
2378
2357
  }
2358
+ return token ?? null
2379
2359
  }
2380
2360
  return this.config.token ?? null
2381
2361
  }
@@ -1,5 +1,6 @@
1
1
  import type { TokenProvider } from './graphql/client';
2
2
  import { type GetLibraryElementArcsQuery, type GetLibraryElementClassificationsQuery, type GetLibraryElementEquivalentsQuery, type GetLibraryElementQuery, type GetLibraryTaxonomyQuery, type ListLibraryElementsQuery, type ListLibraryStructuresQuery, type ListLibraryTaxonomiesQuery, type ListLibraryTaxonomyArcsQuery, type SearchLibraryElementsQuery } from './graphql/generated/graphql';
3
+ export { GraphQLError } from './graphql/client';
3
4
  export type LibraryTaxonomy = ListLibraryTaxonomiesQuery['libraryTaxonomies'][number];
4
5
  export type LibraryTaxonomyDetail = NonNullable<GetLibraryTaxonomyQuery['libraryTaxonomy']>;
5
6
  export type LibraryElement = ListLibraryElementsQuery['libraryElements'][number];
@@ -68,6 +69,8 @@ interface LibraryClientConfig {
68
69
  * request so refreshes flow through automatically.
69
70
  */
70
71
  tokenProvider?: TokenProvider;
72
+ /** GraphQL request timeout in milliseconds (default 60s). */
73
+ timeout?: number;
71
74
  }
72
75
  export declare class LibraryClient {
73
76
  private config;
@@ -131,4 +134,3 @@ export declare class LibraryClient {
131
134
  getLibraryElementEquivalents(graphId: string, id: string): Promise<LibraryEquivalence | null>;
132
135
  private gqlQuery;
133
136
  }
134
- export {};
@@ -1,10 +1,14 @@
1
1
  'use client';
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.LibraryClient = exports.LIBRARY_GRAPH_ID = void 0;
4
+ exports.LibraryClient = exports.LIBRARY_GRAPH_ID = exports.GraphQLError = void 0;
5
5
  const graphql_request_1 = require("graphql-request");
6
6
  const client_1 = require("./graphql/client");
7
7
  const graphql_1 = require("./graphql/generated/graphql");
8
+ // Re-export the structured GraphQL error type so consumers importing
9
+ // from the `@robosystems/client/library` subpath can `instanceof` it.
10
+ var client_2 = require("./graphql/client");
11
+ Object.defineProperty(exports, "GraphQLError", { enumerable: true, get: function () { return client_2.GraphQLError; } });
8
12
  // ── Client ──────────────────────────────────────────────────────────────
9
13
  /**
10
14
  * Sentinel graph_id for the canonical library read surface. Passing
@@ -139,7 +143,7 @@ class LibraryClient {
139
143
  }
140
144
  catch (err) {
141
145
  if (err instanceof graphql_request_1.ClientError) {
142
- throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`);
146
+ throw (0, client_1.toGraphQLError)(label, err);
143
147
  }
144
148
  throw err;
145
149
  }