@semiont/api-client 0.4.7 → 0.4.10
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 +2 -0
- package/dist/index.d.ts +234 -30
- package/dist/index.js +604 -171
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -143,6 +143,8 @@ const client = new SemiontApiClient({
|
|
|
143
143
|
|
|
144
144
|
🛠️ **[Utilities Guide](./docs/Utilities.md)** - Text encoding, fuzzy anchoring, SVG utilities
|
|
145
145
|
|
|
146
|
+
🗄️ **[Observable Stores](./docs/STORES.md)** - Reactive resource and annotation caches, EventBus-driven invalidation, React integration
|
|
147
|
+
|
|
146
148
|
## Key Features
|
|
147
149
|
|
|
148
150
|
- **Two clients** - HTTP (`SemiontApiClient`) and EventBus (`EventBusClient`) for the same operations
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as _semiont_core from '@semiont/core';
|
|
2
|
-
import { EntityType,
|
|
2
|
+
import { EntityType, BaseUrl, Logger, ResourceId, AccessToken, AnnotationId, components, EventBus, paths, Email, RefreshToken, GoogleCredential, ContentFormat, SearchQuery, CloneToken, Motivation, UserDID, JobId, UserId } from '@semiont/core';
|
|
3
3
|
export { Logger, Selector, getFragmentSelector, getSvgSelector, getTextPositionSelector, validateSvgMarkup } from '@semiont/core';
|
|
4
|
+
import { Subscription, Observable } from 'rxjs';
|
|
4
5
|
export { BoundingBox, ContentCache, FragmentSelector, JWTTokenSchema, LOCALES, LocaleInfo, MatchQuality, Point, SvgSelector, TextPosition, TextPositionSelector, TextQuoteSelector, ValidatedAnnotation, ValidationFailure, ValidationResult, ValidationSuccess, buildContentCache, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getTargetSelector, getTargetSource, getTextQuoteSelector, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isReference, isResolvedReference, isStubReference, isTag, isValidEmail, normalizeCoordinates, normalizeText, parseSvgSelector, scaleSvgToNative, validateAndCorrectOffsets, validateData, verifyPosition } from './utils/index.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -203,14 +204,9 @@ type GatherAnnotationStreamRequest = components['schemas']['GatherAnnotationStre
|
|
|
203
204
|
*/
|
|
204
205
|
type BindAnnotationStreamRequest = components['schemas']['BindAnnotationStreamRequest'];
|
|
205
206
|
/**
|
|
206
|
-
* Request body for
|
|
207
|
+
* Request body for match search stream
|
|
207
208
|
*/
|
|
208
|
-
|
|
209
|
-
referenceId: string;
|
|
210
|
-
context: GatheredContext;
|
|
211
|
-
limit?: number;
|
|
212
|
-
useSemanticScoring?: boolean;
|
|
213
|
-
}
|
|
209
|
+
type MatchSearchStreamRequest = components['schemas']['MatchSearchStreamRequest'];
|
|
214
210
|
/**
|
|
215
211
|
* SSE Client configuration
|
|
216
212
|
*/
|
|
@@ -532,7 +528,7 @@ declare class SSEClient {
|
|
|
532
528
|
* @param options - Request options (auth token, eventBus)
|
|
533
529
|
* @returns SSE stream controller
|
|
534
530
|
*/
|
|
535
|
-
|
|
531
|
+
matchSearch(resourceId: ResourceId, request: MatchSearchStreamRequest, options: SSERequestOptions): SSEStream;
|
|
536
532
|
/**
|
|
537
533
|
* Subscribe to resource events (long-lived stream)
|
|
538
534
|
*
|
|
@@ -614,6 +610,208 @@ declare class SSEClient {
|
|
|
614
610
|
}): SSEStream;
|
|
615
611
|
}
|
|
616
612
|
|
|
613
|
+
/**
|
|
614
|
+
* FlowEngine — framework-agnostic flow orchestration
|
|
615
|
+
*
|
|
616
|
+
* Owns the subscription/SSE-bridge logic that was previously scattered across
|
|
617
|
+
* React hooks (useBindFlow, useYieldFlow, useMarkFlow, useContextGatherFlow,
|
|
618
|
+
* useResourceEvents, useAttentionStream).
|
|
619
|
+
*
|
|
620
|
+
* Each method accepts a `getToken` function called at event-handling time so
|
|
621
|
+
* the token is always fresh (the client is stateless; tokens rotate).
|
|
622
|
+
*
|
|
623
|
+
* Each method returns an RxJS Subscription. The caller is responsible for
|
|
624
|
+
* calling .unsubscribe() when the flow is no longer needed (e.g. in a
|
|
625
|
+
* React useEffect cleanup or on workspace teardown).
|
|
626
|
+
*
|
|
627
|
+
* No React imports. No DOM imports. Pure RxJS + EventBus.
|
|
628
|
+
*/
|
|
629
|
+
|
|
630
|
+
type TokenGetter$2 = () => AccessToken | undefined;
|
|
631
|
+
declare class FlowEngine {
|
|
632
|
+
private readonly eventBus;
|
|
633
|
+
private readonly sse;
|
|
634
|
+
private readonly http;
|
|
635
|
+
constructor(eventBus: EventBus, sse: SSEClient, http: SemiontApiClient);
|
|
636
|
+
/**
|
|
637
|
+
* Activate the bind flow for a resource.
|
|
638
|
+
*
|
|
639
|
+
* @subscribes bind:update-body — calls SSE bindAnnotation
|
|
640
|
+
* @subscribes match:search-requested — calls SSE bindSearch
|
|
641
|
+
* @emits bind:body-updated, bind:body-update-failed
|
|
642
|
+
*/
|
|
643
|
+
bind(rUri: ResourceId, getToken: TokenGetter$2): Subscription;
|
|
644
|
+
/**
|
|
645
|
+
* Activate the yield (generation) flow for a resource.
|
|
646
|
+
*
|
|
647
|
+
* @subscribes yield:request — calls SSE yieldResource
|
|
648
|
+
* @subscribes yield:finished — links generated resource back to the reference annotation via bind:update-body
|
|
649
|
+
* @subscribes job:cancel-requested (generation) — aborts in-flight stream
|
|
650
|
+
*/
|
|
651
|
+
yield(_rUri: ResourceId, getToken: TokenGetter$2): Subscription;
|
|
652
|
+
/**
|
|
653
|
+
* Activate the mark (annotation CRUD + assist) flow for a resource.
|
|
654
|
+
*
|
|
655
|
+
* @subscribes mark:submit — HTTP markAnnotation
|
|
656
|
+
* @subscribes mark:delete — HTTP deleteAnnotation
|
|
657
|
+
* @subscribes mark:assist-request — SSE mark* (by motivation)
|
|
658
|
+
* @subscribes job:cancel-requested (annotation) — aborts in-flight assist
|
|
659
|
+
* @emits mark:created, mark:create-failed, mark:deleted, mark:delete-failed
|
|
660
|
+
*/
|
|
661
|
+
mark(rUri: ResourceId, getToken: TokenGetter$2): Subscription;
|
|
662
|
+
/**
|
|
663
|
+
* Activate the gather-context flow for a resource.
|
|
664
|
+
*
|
|
665
|
+
* @subscribes gather:requested — calls SSE gatherAnnotation, threads correlationId
|
|
666
|
+
* @emits gather:complete (re-emitted from SSE gather:annotation-finished)
|
|
667
|
+
*/
|
|
668
|
+
gatherContext(rUri: ResourceId, getToken: TokenGetter$2): Subscription;
|
|
669
|
+
/**
|
|
670
|
+
* Open the long-lived resource-events SSE stream.
|
|
671
|
+
* Returns a Subscription whose teardown closes the stream.
|
|
672
|
+
*/
|
|
673
|
+
resourceEvents(rUri: ResourceId, getToken: TokenGetter$2): Subscription;
|
|
674
|
+
/**
|
|
675
|
+
* Open the long-lived participant attention SSE stream.
|
|
676
|
+
* Returns a Subscription whose teardown closes the stream.
|
|
677
|
+
*/
|
|
678
|
+
attentionStream(getToken: TokenGetter$2): Subscription;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
/**
|
|
682
|
+
* ResourceStore — per-workspace observable resource cache
|
|
683
|
+
*
|
|
684
|
+
* BehaviorSubject-backed store that:
|
|
685
|
+
* - Populates lazily on first subscribe (no up-front fetch)
|
|
686
|
+
* - Updates reactively when EventBus events arrive (no manual invalidation)
|
|
687
|
+
* - Is readable from outside React
|
|
688
|
+
*
|
|
689
|
+
* EventBus events handled:
|
|
690
|
+
* - yield:created → fetch new resource into map, invalidate lists
|
|
691
|
+
* - mark:archived → invalidate resource detail + lists
|
|
692
|
+
* - mark:unarchived → invalidate resource detail + lists
|
|
693
|
+
* - mark:entity-tag-added / mark:entity-tag-removed → invalidate resource detail
|
|
694
|
+
*
|
|
695
|
+
* Token: mutable — call setTokenGetter() from the React layer when auth changes.
|
|
696
|
+
*/
|
|
697
|
+
|
|
698
|
+
type ResponseContent$2<T> = T extends {
|
|
699
|
+
responses: {
|
|
700
|
+
200: {
|
|
701
|
+
content: {
|
|
702
|
+
'application/json': infer R;
|
|
703
|
+
};
|
|
704
|
+
};
|
|
705
|
+
};
|
|
706
|
+
} ? R : never;
|
|
707
|
+
type ResourceDetail = ResponseContent$2<paths['/resources/{id}']['get']>;
|
|
708
|
+
type ResourceListResponse = ResponseContent$2<paths['/resources']['get']>;
|
|
709
|
+
type TokenGetter$1 = () => AccessToken | undefined;
|
|
710
|
+
declare class ResourceStore {
|
|
711
|
+
private readonly http;
|
|
712
|
+
/** Cache of individual resource details, keyed by ResourceId */
|
|
713
|
+
private readonly detail$;
|
|
714
|
+
/** Cache of list responses, keyed by a serialized options string */
|
|
715
|
+
private readonly list$;
|
|
716
|
+
/** Track in-flight fetches to avoid duplicate requests */
|
|
717
|
+
private readonly fetchingDetail;
|
|
718
|
+
private readonly fetchingList;
|
|
719
|
+
/** Memoized Observables — same instance returned for the same key */
|
|
720
|
+
private readonly detailObs$;
|
|
721
|
+
private readonly listObs$;
|
|
722
|
+
/** Mutable token getter — updated from the React layer when auth changes */
|
|
723
|
+
private getToken;
|
|
724
|
+
/** Update the token getter (called from React when auth token changes) */
|
|
725
|
+
setTokenGetter(getter: TokenGetter$1): void;
|
|
726
|
+
constructor(http: SemiontApiClient, eventBus: EventBus);
|
|
727
|
+
/**
|
|
728
|
+
* Get a single resource by ID as an Observable.
|
|
729
|
+
* Triggers a fetch if not cached.
|
|
730
|
+
*/
|
|
731
|
+
get(id: ResourceId): Observable<ResourceDetail | undefined>;
|
|
732
|
+
/**
|
|
733
|
+
* List resources as an Observable.
|
|
734
|
+
* Triggers a fetch if not cached.
|
|
735
|
+
*/
|
|
736
|
+
list(options?: {
|
|
737
|
+
limit?: number;
|
|
738
|
+
archived?: boolean;
|
|
739
|
+
}): Observable<ResourceListResponse | undefined>;
|
|
740
|
+
/** Invalidate and re-fetch a specific resource detail */
|
|
741
|
+
invalidateDetail(id: ResourceId): void;
|
|
742
|
+
/** Remove all list caches (triggers re-fetch on next subscribe) */
|
|
743
|
+
invalidateLists(): void;
|
|
744
|
+
private fetchDetail;
|
|
745
|
+
private fetchList;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
/**
|
|
749
|
+
* AnnotationStore — per-workspace observable annotation cache
|
|
750
|
+
*
|
|
751
|
+
* BehaviorSubject-backed store that:
|
|
752
|
+
* - Populates lazily on first subscribe (no up-front fetch)
|
|
753
|
+
* - Updates reactively when EventBus events arrive (no manual invalidation)
|
|
754
|
+
* - Is readable from outside React
|
|
755
|
+
*
|
|
756
|
+
* EventBus events handled:
|
|
757
|
+
* - mark:deleted → remove from detail cache
|
|
758
|
+
* - mark:added → invalidate annotation list (SSE domain event; resourceId on BaseEvent)
|
|
759
|
+
* - mark:removed → invalidate annotation list + detail (SSE domain event)
|
|
760
|
+
* - mark:body-updated → invalidate annotation list + detail (SSE domain event)
|
|
761
|
+
* - mark:entity-tag-added / mark:entity-tag-removed → invalidate list for resource
|
|
762
|
+
*
|
|
763
|
+
* Token: mutable — call setTokenGetter() from the React layer when auth changes.
|
|
764
|
+
*/
|
|
765
|
+
|
|
766
|
+
type ResponseContent$1<T> = T extends {
|
|
767
|
+
responses: {
|
|
768
|
+
200: {
|
|
769
|
+
content: {
|
|
770
|
+
'application/json': infer R;
|
|
771
|
+
};
|
|
772
|
+
};
|
|
773
|
+
};
|
|
774
|
+
} ? R : never;
|
|
775
|
+
type AnnotationsListResponse = ResponseContent$1<paths['/resources/{id}/annotations']['get']>;
|
|
776
|
+
type AnnotationDetail = ResponseContent$1<paths['/resources/{resourceId}/annotations/{annotationId}']['get']>;
|
|
777
|
+
type TokenGetter = () => AccessToken | undefined;
|
|
778
|
+
declare class AnnotationStore {
|
|
779
|
+
private readonly http;
|
|
780
|
+
/** Annotation list responses keyed by ResourceId */
|
|
781
|
+
private readonly list$;
|
|
782
|
+
/** Individual annotation details keyed by AnnotationId */
|
|
783
|
+
private readonly detail$;
|
|
784
|
+
/** Track in-flight fetches */
|
|
785
|
+
private readonly fetchingList;
|
|
786
|
+
private readonly fetchingDetail;
|
|
787
|
+
/** Memoized Observables — same instance returned for the same key */
|
|
788
|
+
private readonly listObs$;
|
|
789
|
+
private readonly detailObs$;
|
|
790
|
+
/** Mutable token getter — updated from the React layer when auth changes */
|
|
791
|
+
private getToken;
|
|
792
|
+
/** Update the token getter (called from React when auth token changes) */
|
|
793
|
+
setTokenGetter(getter: TokenGetter): void;
|
|
794
|
+
constructor(http: SemiontApiClient, eventBus: EventBus);
|
|
795
|
+
/**
|
|
796
|
+
* Get annotations for a resource as an Observable.
|
|
797
|
+
* Triggers a fetch if not cached.
|
|
798
|
+
*/
|
|
799
|
+
listForResource(resourceId: ResourceId): Observable<AnnotationsListResponse | undefined>;
|
|
800
|
+
/**
|
|
801
|
+
* Get a single annotation detail as an Observable.
|
|
802
|
+
* Triggers a fetch if not cached.
|
|
803
|
+
*/
|
|
804
|
+
get(resourceId: ResourceId, annotationId: AnnotationId): Observable<AnnotationDetail | undefined>;
|
|
805
|
+
/** Invalidate and re-fetch a resource's annotation list */
|
|
806
|
+
invalidateList(resourceId: ResourceId): void;
|
|
807
|
+
/** Invalidate a single annotation detail (re-fetched on next subscribe) */
|
|
808
|
+
invalidateDetail(annotationId: AnnotationId): void;
|
|
809
|
+
/** Remove an annotation from the detail cache without re-fetching */
|
|
810
|
+
private removeFromDetailCache;
|
|
811
|
+
private fetchList;
|
|
812
|
+
private fetchDetail;
|
|
813
|
+
}
|
|
814
|
+
|
|
617
815
|
/**
|
|
618
816
|
* Common API client for Semiont backend
|
|
619
817
|
*
|
|
@@ -657,6 +855,8 @@ declare class APIError extends Error {
|
|
|
657
855
|
}
|
|
658
856
|
interface SemiontApiClientConfig {
|
|
659
857
|
baseUrl: BaseUrl;
|
|
858
|
+
/** Per-workspace EventBus. Required — one bus per workspace, constructed externally. */
|
|
859
|
+
eventBus: EventBus;
|
|
660
860
|
timeout?: number;
|
|
661
861
|
retry?: number;
|
|
662
862
|
logger?: Logger;
|
|
@@ -676,33 +876,40 @@ interface RequestOptions {
|
|
|
676
876
|
*/
|
|
677
877
|
declare class SemiontApiClient {
|
|
678
878
|
private http;
|
|
679
|
-
|
|
879
|
+
readonly baseUrl: BaseUrl;
|
|
880
|
+
/** The workspace-scoped EventBus this client was constructed with. */
|
|
881
|
+
readonly eventBus: EventBus;
|
|
680
882
|
private logger?;
|
|
681
883
|
/**
|
|
682
884
|
* SSE streaming client for real-time operations
|
|
683
885
|
*
|
|
684
886
|
* Separate from the main HTTP client to clearly mark streaming endpoints.
|
|
685
887
|
* Uses native fetch() instead of ky for SSE support.
|
|
686
|
-
*
|
|
687
|
-
* @example
|
|
688
|
-
* ```typescript
|
|
689
|
-
* const stream = client.sse.detectAnnotations(
|
|
690
|
-
* resourceId,
|
|
691
|
-
* { entityTypes: ['Person', 'Organization'] },
|
|
692
|
-
* { auth: accessToken }
|
|
693
|
-
* );
|
|
694
|
-
*
|
|
695
|
-
* stream.onProgress((p) => console.log(p.message));
|
|
696
|
-
* stream.onComplete((r) => console.log(`Found ${r.foundCount} entities`));
|
|
697
|
-
* stream.close();
|
|
698
|
-
* ```
|
|
699
888
|
*/
|
|
700
889
|
readonly sse: SSEClient;
|
|
890
|
+
/**
|
|
891
|
+
* Framework-agnostic flow orchestration.
|
|
892
|
+
* Each method returns a Subscription; call .unsubscribe() to tear down.
|
|
893
|
+
*/
|
|
894
|
+
readonly flows: FlowEngine;
|
|
895
|
+
/**
|
|
896
|
+
* Per-workspace observable stores for entity data.
|
|
897
|
+
* Call stores.resources.setTokenGetter() / stores.annotations.setTokenGetter()
|
|
898
|
+
* from the React layer when the auth token changes.
|
|
899
|
+
*/
|
|
900
|
+
readonly stores: {
|
|
901
|
+
resources: ResourceStore;
|
|
902
|
+
annotations: AnnotationStore;
|
|
903
|
+
};
|
|
701
904
|
constructor(config: SemiontApiClientConfig);
|
|
905
|
+
private authHeaders;
|
|
702
906
|
authenticatePassword(email: Email, password: string, options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/password']['post']>>;
|
|
703
907
|
refreshToken(token: RefreshToken, options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/refresh']['post']>>;
|
|
704
908
|
authenticateGoogle(credential: GoogleCredential, options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/google']['post']>>;
|
|
705
909
|
generateMCPToken(options?: RequestOptions): Promise<ResponseContent<paths['/api/tokens/mcp-generate']['post']>>;
|
|
910
|
+
getMediaToken(resourceId: ResourceId, options?: RequestOptions): Promise<{
|
|
911
|
+
token: string;
|
|
912
|
+
}>;
|
|
706
913
|
getMe(options?: RequestOptions): Promise<ResponseContent<paths['/api/users/me']['get']>>;
|
|
707
914
|
acceptTerms(options?: RequestOptions): Promise<ResponseContent<paths['/api/users/accept-terms']['post']>>;
|
|
708
915
|
logout(options?: RequestOptions): Promise<ResponseContent<paths['/api/users/logout']['post']>>;
|
|
@@ -808,12 +1015,8 @@ declare class SemiontApiClient {
|
|
|
808
1015
|
}>;
|
|
809
1016
|
browseResources(limit?: number, archived?: boolean, query?: SearchQuery, options?: RequestOptions): Promise<ResponseContent<paths['/resources']['get']>>;
|
|
810
1017
|
updateResource(id: ResourceId, data: RequestContent<paths['/resources/{id}']['patch']>, options?: RequestOptions): Promise<void>;
|
|
811
|
-
getResourceEvents(id: ResourceId, options?: RequestOptions): Promise<{
|
|
812
|
-
|
|
813
|
-
}>;
|
|
814
|
-
browseReferences(id: ResourceId, options?: RequestOptions): Promise<{
|
|
815
|
-
referencedBy: any[];
|
|
816
|
-
}>;
|
|
1018
|
+
getResourceEvents(id: ResourceId, options?: RequestOptions): Promise<ResponseContent<paths['/resources/{id}/events']['get']>>;
|
|
1019
|
+
browseReferences(id: ResourceId, options?: RequestOptions): Promise<ResponseContent<paths['/resources/{id}/referenced-by']['get']>>;
|
|
817
1020
|
generateCloneToken(id: ResourceId, options?: RequestOptions): Promise<ResponseContent<paths['/resources/{id}/clone-with-token']['post']>>;
|
|
818
1021
|
getResourceByToken(token: CloneToken, options?: RequestOptions): Promise<ResponseContent<paths['/api/clone-tokens/{token}']['get']>>;
|
|
819
1022
|
createResourceFromToken(data: RequestContent<paths['/api/clone-tokens/create-resource']['post']>, options?: RequestOptions): Promise<{
|
|
@@ -882,6 +1085,7 @@ declare class SemiontApiClient {
|
|
|
882
1085
|
message?: string;
|
|
883
1086
|
result?: Record<string, unknown>;
|
|
884
1087
|
}>;
|
|
1088
|
+
private parseSSEStream;
|
|
885
1089
|
getJobStatus(id: JobId, options?: RequestOptions): Promise<ResponseContent<paths['/api/jobs/{id}']['get']>>;
|
|
886
1090
|
/**
|
|
887
1091
|
* Poll a job until it completes or fails
|
|
@@ -1009,4 +1213,4 @@ declare function isPdfMimeType(mimeType: string): boolean;
|
|
|
1009
1213
|
type MimeCategory = 'text' | 'image' | 'unsupported';
|
|
1010
1214
|
declare function getMimeCategory(mimeType: string): MimeCategory;
|
|
1011
1215
|
|
|
1012
|
-
export { APIError, type AnnotateReferencesStreamRequest, type
|
|
1216
|
+
export { APIError, type AnnotateReferencesStreamRequest, type AnnotationDetail, AnnotationStore, type AnnotationsListResponse, EventBusClient, FlowEngine, type MatchSearchStreamRequest, type MimeCategory, type ReferenceDetectionProgress, type RequestOptions, type ResourceDetail, type ResourceListResponse, ResourceStore, SSEClient, type SSEClientConfig, type SSEStream, type SSEStreamConnected, SSE_STREAM_CONNECTED, SemiontApiClient, type SemiontApiClientConfig, type YieldProgress, type YieldResourceStreamRequest, getExtensionForMimeType, getMimeCategory, isImageMimeType, isPdfMimeType, isTextMimeType };
|