@robosystems/client 0.3.7 → 0.3.8

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.
@@ -0,0 +1,117 @@
1
+ import type { TokenProvider } from './graphql/client';
2
+ import { type GetLibraryElementArcsQuery, type GetLibraryElementClassificationsQuery, type GetLibraryElementEquivalentsQuery, type GetLibraryElementQuery, type GetLibraryTaxonomyQuery, type ListLibraryElementsQuery, type ListLibraryTaxonomiesQuery, type ListLibraryTaxonomyArcsQuery, type SearchLibraryElementsQuery } from './graphql/generated/graphql';
3
+ export type LibraryTaxonomy = ListLibraryTaxonomiesQuery['libraryTaxonomies'][number];
4
+ export type LibraryTaxonomyDetail = NonNullable<GetLibraryTaxonomyQuery['libraryTaxonomy']>;
5
+ export type LibraryElement = ListLibraryElementsQuery['libraryElements'][number];
6
+ export type LibraryElementDetail = NonNullable<GetLibraryElementQuery['libraryElement']>;
7
+ export type LibrarySearchResult = SearchLibraryElementsQuery['searchLibraryElements'][number];
8
+ export type LibraryLabel = LibraryElementDetail['labels'][number];
9
+ export type LibraryReference = LibraryElementDetail['references'][number];
10
+ export type LibraryArc = ListLibraryTaxonomyArcsQuery['libraryTaxonomyArcs'][number];
11
+ export type LibraryElementArc = GetLibraryElementArcsQuery['libraryElementArcs'][number];
12
+ export type LibraryElementClassification = GetLibraryElementClassificationsQuery['libraryElementClassifications'][number];
13
+ export type LibraryEquivalence = NonNullable<GetLibraryElementEquivalentsQuery['libraryElementEquivalents']>;
14
+ export interface ListLibraryElementsOptions {
15
+ taxonomyId?: string;
16
+ source?: string;
17
+ /** FASB elementsOfFinancialStatements axis (asset | liability | equity | revenue | expense | …). */
18
+ classification?: string;
19
+ /** Cash-flow activity axis (operatingActivity | investingActivity | financingActivity). */
20
+ activityType?: string;
21
+ elementType?: string;
22
+ /** `true` → abstract only; `false` → concrete only; omit for both. */
23
+ isAbstract?: boolean | null;
24
+ limit?: number;
25
+ offset?: number;
26
+ includeLabels?: boolean;
27
+ includeReferences?: boolean;
28
+ }
29
+ export interface SearchLibraryElementsOptions {
30
+ source?: string;
31
+ limit?: number;
32
+ }
33
+ export interface ListLibraryTaxonomyArcsOptions {
34
+ associationType?: string;
35
+ limit?: number;
36
+ offset?: number;
37
+ }
38
+ export interface ListLibraryTaxonomyArcsResult {
39
+ arcs: LibraryArc[];
40
+ count: number;
41
+ }
42
+ export interface GetLibraryElementIdentifier {
43
+ id?: string;
44
+ qname?: string;
45
+ }
46
+ /**
47
+ * Sentinel graph_id for the canonical library read surface. Passing
48
+ * this to any LibraryClient method routes the GraphQL request to
49
+ * `/extensions/library/graphql` and reads from the public schema only.
50
+ */
51
+ export declare const LIBRARY_GRAPH_ID = "library";
52
+ interface LibraryClientConfig {
53
+ baseUrl: string;
54
+ credentials?: 'include' | 'same-origin' | 'omit';
55
+ headers?: Record<string, string>;
56
+ /** Static credential — use `tokenProvider` instead if the JWT rotates. */
57
+ token?: string;
58
+ /**
59
+ * Dynamic credential callback. When set, invoked on every GraphQL
60
+ * request so refreshes flow through automatically.
61
+ */
62
+ tokenProvider?: TokenProvider;
63
+ }
64
+ export declare class LibraryClient {
65
+ private config;
66
+ private gql;
67
+ constructor(config: LibraryClientConfig);
68
+ /**
69
+ * List every taxonomy visible at this graph_id.
70
+ *
71
+ * On the `"library"` sentinel this is the canonical set (sfac6,
72
+ * fac, rs-gaap, …). On a tenant graph_id this also includes the
73
+ * tenant's own CoA and any custom taxonomies they've created.
74
+ */
75
+ listLibraryTaxonomies(graphId: string, options?: {
76
+ standard?: string;
77
+ includeElementCount?: boolean;
78
+ }): Promise<LibraryTaxonomy[]>;
79
+ /** Fetch one taxonomy by id or by (standard, version). */
80
+ getLibraryTaxonomy(graphId: string, identifier: {
81
+ id?: string;
82
+ standard?: string;
83
+ version?: string;
84
+ }, options?: {
85
+ includeElementCount?: boolean;
86
+ }): Promise<LibraryTaxonomyDetail | null>;
87
+ /** List library elements with filters + pagination. */
88
+ listLibraryElements(graphId: string, options?: ListLibraryElementsOptions): Promise<LibraryElement[]>;
89
+ /**
90
+ * Substring search across qname, name, and standard label text.
91
+ * Always includes labels + references inline — search UIs render them.
92
+ */
93
+ searchLibraryElements(graphId: string, query: string, options?: SearchLibraryElementsOptions): Promise<LibrarySearchResult[]>;
94
+ /**
95
+ * Get a single element by id or by qname. Returns null when neither
96
+ * identifier is supplied or neither resolves.
97
+ */
98
+ getLibraryElement(graphId: string, identifier: GetLibraryElementIdentifier): Promise<LibraryElementDetail | null>;
99
+ /**
100
+ * All arcs contributed by a taxonomy, plus their total count, in one
101
+ * round-trip. For mapping taxonomies (fac-to-rs-gaap, sfac6-to-fac,
102
+ * type-subtype) this is the primary browse view.
103
+ */
104
+ listLibraryTaxonomyArcs(graphId: string, taxonomyId: string, options?: ListLibraryTaxonomyArcsOptions): Promise<ListLibraryTaxonomyArcsResult>;
105
+ /**
106
+ * All mapping arcs where this element is source or target. Covers
107
+ * every `taxonomy_type='mapping'` bridge — equivalence,
108
+ * general-special, type-subtype.
109
+ */
110
+ getLibraryElementArcs(graphId: string, id: string): Promise<LibraryElementArc[]>;
111
+ /** All classification traits (category + identifier) assigned to this element. */
112
+ getLibraryElementClassifications(graphId: string, id: string): Promise<LibraryElementClassification[]>;
113
+ /** Equivalence fan-out (FAC ↔ us-gaap collapse). */
114
+ getLibraryElementEquivalents(graphId: string, id: string): Promise<LibraryEquivalence | null>;
115
+ private gqlQuery;
116
+ }
117
+ export {};
@@ -0,0 +1,132 @@
1
+ 'use client';
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.LibraryClient = exports.LIBRARY_GRAPH_ID = void 0;
5
+ const graphql_request_1 = require("graphql-request");
6
+ const client_1 = require("./graphql/client");
7
+ const graphql_1 = require("./graphql/generated/graphql");
8
+ // ── Client ──────────────────────────────────────────────────────────────
9
+ /**
10
+ * Sentinel graph_id for the canonical library read surface. Passing
11
+ * this to any LibraryClient method routes the GraphQL request to
12
+ * `/extensions/library/graphql` and reads from the public schema only.
13
+ */
14
+ exports.LIBRARY_GRAPH_ID = 'library';
15
+ class LibraryClient {
16
+ constructor(config) {
17
+ this.config = config;
18
+ this.gql = new client_1.GraphQLClientCache(config);
19
+ }
20
+ // ── Taxonomies ──────────────────────────────────────────────────────
21
+ /**
22
+ * List every taxonomy visible at this graph_id.
23
+ *
24
+ * On the `"library"` sentinel this is the canonical set (sfac6,
25
+ * fac, rs-gaap, …). On a tenant graph_id this also includes the
26
+ * tenant's own CoA and any custom taxonomies they've created.
27
+ */
28
+ async listLibraryTaxonomies(graphId, options) {
29
+ return this.gqlQuery(graphId, graphql_1.ListLibraryTaxonomiesDocument, {
30
+ standard: options?.standard ?? null,
31
+ includeElementCount: options?.includeElementCount ?? false,
32
+ }, 'List library taxonomies', (data) => data.libraryTaxonomies);
33
+ }
34
+ /** Fetch one taxonomy by id or by (standard, version). */
35
+ async getLibraryTaxonomy(graphId, identifier, options) {
36
+ return this.gqlQuery(graphId, graphql_1.GetLibraryTaxonomyDocument, {
37
+ id: identifier.id ?? null,
38
+ standard: identifier.standard ?? null,
39
+ version: identifier.version ?? null,
40
+ includeElementCount: options?.includeElementCount ?? false,
41
+ }, 'Get library taxonomy', (data) => data.libraryTaxonomy);
42
+ }
43
+ // ── Elements ────────────────────────────────────────────────────────
44
+ /** List library elements with filters + pagination. */
45
+ async listLibraryElements(graphId, options) {
46
+ return this.gqlQuery(graphId, graphql_1.ListLibraryElementsDocument, {
47
+ taxonomyId: options?.taxonomyId ?? null,
48
+ source: options?.source ?? null,
49
+ classification: options?.classification ?? null,
50
+ activityType: options?.activityType ?? null,
51
+ elementType: options?.elementType ?? null,
52
+ isAbstract: options?.isAbstract ?? null,
53
+ limit: options?.limit ?? 50,
54
+ offset: options?.offset ?? 0,
55
+ includeLabels: options?.includeLabels ?? false,
56
+ includeReferences: options?.includeReferences ?? false,
57
+ }, 'List library elements', (data) => data.libraryElements);
58
+ }
59
+ /**
60
+ * Substring search across qname, name, and standard label text.
61
+ * Always includes labels + references inline — search UIs render them.
62
+ */
63
+ async searchLibraryElements(graphId, query, options) {
64
+ return this.gqlQuery(graphId, graphql_1.SearchLibraryElementsDocument, {
65
+ query,
66
+ source: options?.source ?? null,
67
+ limit: options?.limit ?? 50,
68
+ }, 'Search library elements', (data) => data.searchLibraryElements);
69
+ }
70
+ /**
71
+ * Get a single element by id or by qname. Returns null when neither
72
+ * identifier is supplied or neither resolves.
73
+ */
74
+ async getLibraryElement(graphId, identifier) {
75
+ return this.gqlQuery(graphId, graphql_1.GetLibraryElementDocument, {
76
+ id: identifier.id ?? null,
77
+ qname: identifier.qname ?? null,
78
+ }, 'Get library element', (data) => data.libraryElement);
79
+ }
80
+ // ── Arcs / Equivalence ──────────────────────────────────────────────
81
+ /**
82
+ * All arcs contributed by a taxonomy, plus their total count, in one
83
+ * round-trip. For mapping taxonomies (fac-to-rs-gaap, sfac6-to-fac,
84
+ * type-subtype) this is the primary browse view.
85
+ */
86
+ async listLibraryTaxonomyArcs(graphId, taxonomyId, options) {
87
+ return this.gqlQuery(graphId, graphql_1.ListLibraryTaxonomyArcsDocument, {
88
+ taxonomyId,
89
+ associationType: options?.associationType ?? null,
90
+ limit: options?.limit ?? 200,
91
+ offset: options?.offset ?? 0,
92
+ }, 'List library taxonomy arcs', (data) => ({
93
+ arcs: data.libraryTaxonomyArcs,
94
+ count: data.libraryTaxonomyArcCount,
95
+ }));
96
+ }
97
+ /**
98
+ * All mapping arcs where this element is source or target. Covers
99
+ * every `taxonomy_type='mapping'` bridge — equivalence,
100
+ * general-special, type-subtype.
101
+ */
102
+ async getLibraryElementArcs(graphId, id) {
103
+ return this.gqlQuery(graphId, graphql_1.GetLibraryElementArcsDocument, { id }, 'Get library element arcs', (data) => data.libraryElementArcs);
104
+ }
105
+ /** All classification traits (category + identifier) assigned to this element. */
106
+ async getLibraryElementClassifications(graphId, id) {
107
+ return this.gqlQuery(graphId, graphql_1.GetLibraryElementClassificationsDocument, { id }, 'Get library element classifications', (data) => data.libraryElementClassifications);
108
+ }
109
+ /** Equivalence fan-out (FAC ↔ us-gaap collapse). */
110
+ async getLibraryElementEquivalents(graphId, id) {
111
+ return this.gqlQuery(graphId, graphql_1.GetLibraryElementEquivalentsDocument, { id }, 'Get library element equivalents', (data) => data.libraryElementEquivalents);
112
+ }
113
+ // ── Internal helpers ────────────────────────────────────────────────
114
+ async gqlQuery(graphId, document, variables, label, pick) {
115
+ try {
116
+ const client = this.gql.get(graphId);
117
+ const raw = client.request;
118
+ // graphql-request's overloads don't cleanly resolve for generic
119
+ // helpers wrapping codegen's `Exact<>` var types, so we bypass
120
+ // the typed overload with a narrow cast of `request` itself.
121
+ const data = (await raw.call(client, document, variables));
122
+ return pick(data);
123
+ }
124
+ catch (err) {
125
+ if (err instanceof graphql_request_1.ClientError) {
126
+ throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`);
127
+ }
128
+ throw err;
129
+ }
130
+ }
131
+ }
132
+ exports.LibraryClient = LibraryClient;
@@ -0,0 +1,358 @@
1
+ 'use client'
2
+
3
+ /**
4
+ * Library Client for RoboSystems API
5
+ *
6
+ * Read-only facade for the taxonomy library — the shared reference
7
+ * material (sfac6, fac, rs-gaap, …, mapping taxonomies) that lives
8
+ * in the extensions DB public schema.
9
+ *
10
+ * **Two access modes** — picked by the caller's `graphId`:
11
+ *
12
+ * - `"library"` (sentinel, default) → canonical browse of the public
13
+ * schema. Route: `POST /extensions/library/graphql`.
14
+ * - Any tenant `graph_id` (`"kg…"`) → tenant schema + public fallback
15
+ * via search_path. Returns the tenant's library copy plus any
16
+ * tenant extensions of library tables (CoA elements, anchor
17
+ * associations). Route: `POST /extensions/{graph_id}/graphql`.
18
+ *
19
+ * Every method takes the `graphId` explicitly so a single facade
20
+ * instance can serve both modes — the per-graph `GraphQLClientCache`
21
+ * handles endpoint resolution.
22
+ *
23
+ * **Read-only**: the library is immutable at the DB level (triggers
24
+ * block UPDATE/DELETE on rows whose `created_by='library-seeder'`),
25
+ * so there's no write surface here. Tenant-scope writes against
26
+ * tenant-owned rows go through `LedgerClient` (CoA commands).
27
+ */
28
+
29
+ import type { TypedDocumentNode } from '@graphql-typed-document-node/core'
30
+ import { ClientError } from 'graphql-request'
31
+ import type { TokenProvider } from './graphql/client'
32
+ import { GraphQLClientCache } from './graphql/client'
33
+ import {
34
+ GetLibraryElementArcsDocument,
35
+ GetLibraryElementClassificationsDocument,
36
+ GetLibraryElementDocument,
37
+ GetLibraryElementEquivalentsDocument,
38
+ GetLibraryTaxonomyDocument,
39
+ ListLibraryElementsDocument,
40
+ ListLibraryTaxonomiesDocument,
41
+ ListLibraryTaxonomyArcsDocument,
42
+ SearchLibraryElementsDocument,
43
+ type GetLibraryElementArcsQuery,
44
+ type GetLibraryElementClassificationsQuery,
45
+ type GetLibraryElementEquivalentsQuery,
46
+ type GetLibraryElementQuery,
47
+ type GetLibraryTaxonomyQuery,
48
+ type ListLibraryElementsQuery,
49
+ type ListLibraryTaxonomiesQuery,
50
+ type ListLibraryTaxonomyArcsQuery,
51
+ type SearchLibraryElementsQuery,
52
+ } from './graphql/generated/graphql'
53
+
54
+ // ── Friendly types derived from GraphQL codegen ────────────────────────
55
+ //
56
+ // These are the single source of truth for library payload shapes —
57
+ // consumers should import them from here rather than redeclaring.
58
+
59
+ export type LibraryTaxonomy = ListLibraryTaxonomiesQuery['libraryTaxonomies'][number]
60
+ export type LibraryTaxonomyDetail = NonNullable<GetLibraryTaxonomyQuery['libraryTaxonomy']>
61
+
62
+ export type LibraryElement = ListLibraryElementsQuery['libraryElements'][number]
63
+ export type LibraryElementDetail = NonNullable<GetLibraryElementQuery['libraryElement']>
64
+ export type LibrarySearchResult = SearchLibraryElementsQuery['searchLibraryElements'][number]
65
+
66
+ export type LibraryLabel = LibraryElementDetail['labels'][number]
67
+ export type LibraryReference = LibraryElementDetail['references'][number]
68
+
69
+ export type LibraryArc = ListLibraryTaxonomyArcsQuery['libraryTaxonomyArcs'][number]
70
+ export type LibraryElementArc = GetLibraryElementArcsQuery['libraryElementArcs'][number]
71
+ export type LibraryElementClassification =
72
+ GetLibraryElementClassificationsQuery['libraryElementClassifications'][number]
73
+ export type LibraryEquivalence = NonNullable<
74
+ GetLibraryElementEquivalentsQuery['libraryElementEquivalents']
75
+ >
76
+
77
+ // ── Caller-facing option shapes ────────────────────────────────────────
78
+
79
+ export interface ListLibraryElementsOptions {
80
+ taxonomyId?: string
81
+ source?: string
82
+ /** FASB elementsOfFinancialStatements axis (asset | liability | equity | revenue | expense | …). */
83
+ classification?: string
84
+ /** Cash-flow activity axis (operatingActivity | investingActivity | financingActivity). */
85
+ activityType?: string
86
+ elementType?: string
87
+ /** `true` → abstract only; `false` → concrete only; omit for both. */
88
+ isAbstract?: boolean | null
89
+ limit?: number
90
+ offset?: number
91
+ includeLabels?: boolean
92
+ includeReferences?: boolean
93
+ }
94
+
95
+ export interface SearchLibraryElementsOptions {
96
+ source?: string
97
+ limit?: number
98
+ }
99
+
100
+ export interface ListLibraryTaxonomyArcsOptions {
101
+ associationType?: string
102
+ limit?: number
103
+ offset?: number
104
+ }
105
+
106
+ export interface ListLibraryTaxonomyArcsResult {
107
+ arcs: LibraryArc[]
108
+ count: number
109
+ }
110
+
111
+ export interface GetLibraryElementIdentifier {
112
+ id?: string
113
+ qname?: string
114
+ }
115
+
116
+ // ── Client ──────────────────────────────────────────────────────────────
117
+
118
+ /**
119
+ * Sentinel graph_id for the canonical library read surface. Passing
120
+ * this to any LibraryClient method routes the GraphQL request to
121
+ * `/extensions/library/graphql` and reads from the public schema only.
122
+ */
123
+ export const LIBRARY_GRAPH_ID = 'library'
124
+
125
+ interface LibraryClientConfig {
126
+ baseUrl: string
127
+ credentials?: 'include' | 'same-origin' | 'omit'
128
+ headers?: Record<string, string>
129
+ /** Static credential — use `tokenProvider` instead if the JWT rotates. */
130
+ token?: string
131
+ /**
132
+ * Dynamic credential callback. When set, invoked on every GraphQL
133
+ * request so refreshes flow through automatically.
134
+ */
135
+ tokenProvider?: TokenProvider
136
+ }
137
+
138
+ export class LibraryClient {
139
+ private config: LibraryClientConfig
140
+ private gql: GraphQLClientCache
141
+
142
+ constructor(config: LibraryClientConfig) {
143
+ this.config = config
144
+ this.gql = new GraphQLClientCache(config)
145
+ }
146
+
147
+ // ── Taxonomies ──────────────────────────────────────────────────────
148
+
149
+ /**
150
+ * List every taxonomy visible at this graph_id.
151
+ *
152
+ * On the `"library"` sentinel this is the canonical set (sfac6,
153
+ * fac, rs-gaap, …). On a tenant graph_id this also includes the
154
+ * tenant's own CoA and any custom taxonomies they've created.
155
+ */
156
+ async listLibraryTaxonomies(
157
+ graphId: string,
158
+ options?: { standard?: string; includeElementCount?: boolean }
159
+ ): Promise<LibraryTaxonomy[]> {
160
+ return this.gqlQuery(
161
+ graphId,
162
+ ListLibraryTaxonomiesDocument,
163
+ {
164
+ standard: options?.standard ?? null,
165
+ includeElementCount: options?.includeElementCount ?? false,
166
+ },
167
+ 'List library taxonomies',
168
+ (data) => data.libraryTaxonomies
169
+ )
170
+ }
171
+
172
+ /** Fetch one taxonomy by id or by (standard, version). */
173
+ async getLibraryTaxonomy(
174
+ graphId: string,
175
+ identifier: { id?: string; standard?: string; version?: string },
176
+ options?: { includeElementCount?: boolean }
177
+ ): Promise<LibraryTaxonomyDetail | null> {
178
+ return this.gqlQuery(
179
+ graphId,
180
+ GetLibraryTaxonomyDocument,
181
+ {
182
+ id: identifier.id ?? null,
183
+ standard: identifier.standard ?? null,
184
+ version: identifier.version ?? null,
185
+ includeElementCount: options?.includeElementCount ?? false,
186
+ },
187
+ 'Get library taxonomy',
188
+ (data) => data.libraryTaxonomy
189
+ )
190
+ }
191
+
192
+ // ── Elements ────────────────────────────────────────────────────────
193
+
194
+ /** List library elements with filters + pagination. */
195
+ async listLibraryElements(
196
+ graphId: string,
197
+ options?: ListLibraryElementsOptions
198
+ ): Promise<LibraryElement[]> {
199
+ return this.gqlQuery(
200
+ graphId,
201
+ ListLibraryElementsDocument,
202
+ {
203
+ taxonomyId: options?.taxonomyId ?? null,
204
+ source: options?.source ?? null,
205
+ classification: options?.classification ?? null,
206
+ activityType: options?.activityType ?? null,
207
+ elementType: options?.elementType ?? null,
208
+ isAbstract: options?.isAbstract ?? null,
209
+ limit: options?.limit ?? 50,
210
+ offset: options?.offset ?? 0,
211
+ includeLabels: options?.includeLabels ?? false,
212
+ includeReferences: options?.includeReferences ?? false,
213
+ },
214
+ 'List library elements',
215
+ (data) => data.libraryElements
216
+ )
217
+ }
218
+
219
+ /**
220
+ * Substring search across qname, name, and standard label text.
221
+ * Always includes labels + references inline — search UIs render them.
222
+ */
223
+ async searchLibraryElements(
224
+ graphId: string,
225
+ query: string,
226
+ options?: SearchLibraryElementsOptions
227
+ ): Promise<LibrarySearchResult[]> {
228
+ return this.gqlQuery(
229
+ graphId,
230
+ SearchLibraryElementsDocument,
231
+ {
232
+ query,
233
+ source: options?.source ?? null,
234
+ limit: options?.limit ?? 50,
235
+ },
236
+ 'Search library elements',
237
+ (data) => data.searchLibraryElements
238
+ )
239
+ }
240
+
241
+ /**
242
+ * Get a single element by id or by qname. Returns null when neither
243
+ * identifier is supplied or neither resolves.
244
+ */
245
+ async getLibraryElement(
246
+ graphId: string,
247
+ identifier: GetLibraryElementIdentifier
248
+ ): Promise<LibraryElementDetail | null> {
249
+ return this.gqlQuery(
250
+ graphId,
251
+ GetLibraryElementDocument,
252
+ {
253
+ id: identifier.id ?? null,
254
+ qname: identifier.qname ?? null,
255
+ },
256
+ 'Get library element',
257
+ (data) => data.libraryElement
258
+ )
259
+ }
260
+
261
+ // ── Arcs / Equivalence ──────────────────────────────────────────────
262
+
263
+ /**
264
+ * All arcs contributed by a taxonomy, plus their total count, in one
265
+ * round-trip. For mapping taxonomies (fac-to-rs-gaap, sfac6-to-fac,
266
+ * type-subtype) this is the primary browse view.
267
+ */
268
+ async listLibraryTaxonomyArcs(
269
+ graphId: string,
270
+ taxonomyId: string,
271
+ options?: ListLibraryTaxonomyArcsOptions
272
+ ): Promise<ListLibraryTaxonomyArcsResult> {
273
+ return this.gqlQuery(
274
+ graphId,
275
+ ListLibraryTaxonomyArcsDocument,
276
+ {
277
+ taxonomyId,
278
+ associationType: options?.associationType ?? null,
279
+ limit: options?.limit ?? 200,
280
+ offset: options?.offset ?? 0,
281
+ },
282
+ 'List library taxonomy arcs',
283
+ (data) => ({
284
+ arcs: data.libraryTaxonomyArcs,
285
+ count: data.libraryTaxonomyArcCount,
286
+ })
287
+ )
288
+ }
289
+
290
+ /**
291
+ * All mapping arcs where this element is source or target. Covers
292
+ * every `taxonomy_type='mapping'` bridge — equivalence,
293
+ * general-special, type-subtype.
294
+ */
295
+ async getLibraryElementArcs(graphId: string, id: string): Promise<LibraryElementArc[]> {
296
+ return this.gqlQuery(
297
+ graphId,
298
+ GetLibraryElementArcsDocument,
299
+ { id },
300
+ 'Get library element arcs',
301
+ (data) => data.libraryElementArcs
302
+ )
303
+ }
304
+
305
+ /** All classification traits (category + identifier) assigned to this element. */
306
+ async getLibraryElementClassifications(
307
+ graphId: string,
308
+ id: string
309
+ ): Promise<LibraryElementClassification[]> {
310
+ return this.gqlQuery(
311
+ graphId,
312
+ GetLibraryElementClassificationsDocument,
313
+ { id },
314
+ 'Get library element classifications',
315
+ (data) => data.libraryElementClassifications
316
+ )
317
+ }
318
+
319
+ /** Equivalence fan-out (FAC ↔ us-gaap collapse). */
320
+ async getLibraryElementEquivalents(
321
+ graphId: string,
322
+ id: string
323
+ ): Promise<LibraryEquivalence | null> {
324
+ return this.gqlQuery(
325
+ graphId,
326
+ GetLibraryElementEquivalentsDocument,
327
+ { id },
328
+ 'Get library element equivalents',
329
+ (data) => data.libraryElementEquivalents
330
+ )
331
+ }
332
+
333
+ // ── Internal helpers ────────────────────────────────────────────────
334
+
335
+ private async gqlQuery<TData, TVars extends object, TResult>(
336
+ graphId: string,
337
+ document: TypedDocumentNode<TData, TVars>,
338
+ variables: TVars | undefined,
339
+ label: string,
340
+ pick: (data: TData) => TResult
341
+ ): Promise<TResult> {
342
+ try {
343
+ const client = this.gql.get(graphId)
344
+
345
+ const raw = client.request as (doc: unknown, vars?: unknown) => Promise<any>
346
+ // graphql-request's overloads don't cleanly resolve for generic
347
+ // helpers wrapping codegen's `Exact<>` var types, so we bypass
348
+ // the typed overload with a narrow cast of `request` itself.
349
+ const data = (await raw.call(client, document, variables)) as TData
350
+ return pick(data)
351
+ } catch (err) {
352
+ if (err instanceof ClientError) {
353
+ throw new Error(`${label} failed: ${JSON.stringify(err.response.errors ?? err.message)}`)
354
+ }
355
+ throw err
356
+ }
357
+ }
358
+ }