@calimero-network/mero-js 1.1.0 → 1.2.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/dist/admin-api/admin-client.d.ts +29 -27
- package/dist/admin-api/admin-client.d.ts.map +1 -1
- package/dist/admin-api/admin-client.js +70 -58
- package/dist/admin-api/admin-client.js.map +1 -1
- package/dist/admin-api/admin-types.d.ts +57 -159
- package/dist/admin-api/admin-types.d.ts.map +1 -1
- package/dist/admin-api/admin-types.js +1 -1
- package/dist/admin-api/admin-types.js.map +1 -1
- package/dist/auth/index.d.ts +26 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +51 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/events/index.d.ts +5 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +3 -0
- package/dist/events/index.js.map +1 -0
- package/dist/events/sse.d.ts +41 -0
- package/dist/events/sse.d.ts.map +1 -0
- package/dist/events/sse.js +237 -0
- package/dist/events/sse.js.map +1 -0
- package/dist/events/ws.d.ts +42 -0
- package/dist/events/ws.d.ts.map +1 -0
- package/dist/events/ws.js +178 -0
- package/dist/events/ws.js.map +1 -0
- package/dist/http-client/web-client.d.ts.map +1 -1
- package/dist/http-client/web-client.js +2 -4
- package/dist/http-client/web-client.js.map +1 -1
- package/dist/index.browser.mjs +2 -1
- package/dist/index.browser.mjs.map +4 -4
- package/dist/index.cjs +705 -88
- package/dist/index.cjs.map +3 -3
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +705 -88
- package/dist/index.mjs.map +3 -3
- package/dist/mero-js.d.ts +47 -1
- package/dist/mero-js.d.ts.map +1 -1
- package/dist/mero-js.js +132 -16
- package/dist/mero-js.js.map +1 -1
- package/dist/rpc/index.d.ts +21 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/rpc/index.js +39 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/token-store/index.d.ts +20 -0
- package/dist/token-store/index.d.ts.map +1 -0
- package/dist/token-store/index.js +62 -0
- package/dist/token-store/index.js.map +1 -0
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -197,8 +197,7 @@ var WebHttpClient = class {
|
|
|
197
197
|
bodyText
|
|
198
198
|
);
|
|
199
199
|
const userAborted = init?.signal?.aborted === true;
|
|
200
|
-
if (response.status === 401 && this.transport.refreshToken && response.headers.get("x-auth-error") === "token_expired" && retryCount < MAX_RETRY_ATTEMPTS && !isStreamBody &&
|
|
201
|
-
!userAborted) {
|
|
200
|
+
if (response.status === 401 && this.transport.refreshToken && response.headers.get("x-auth-error") === "token_expired" && retryCount < MAX_RETRY_ATTEMPTS && !isStreamBody && !userAborted) {
|
|
202
201
|
try {
|
|
203
202
|
let refreshPromise = this.refreshTokenPromise;
|
|
204
203
|
if (!refreshPromise) {
|
|
@@ -636,122 +635,117 @@ function createAuthApiClientFromHttpClient(httpClient, _config) {
|
|
|
636
635
|
}
|
|
637
636
|
|
|
638
637
|
// src/admin-api/admin-client.ts
|
|
638
|
+
function unwrap(response) {
|
|
639
|
+
return response.data;
|
|
640
|
+
}
|
|
639
641
|
var AdminApiClient = class {
|
|
640
642
|
constructor(httpClient) {
|
|
641
643
|
this.httpClient = httpClient;
|
|
642
644
|
}
|
|
643
|
-
// Health and Status
|
|
645
|
+
// ---- Health and Status (public, no auth) ----
|
|
644
646
|
async healthCheck() {
|
|
645
|
-
|
|
646
|
-
if (!response.data) {
|
|
647
|
-
throw new Error("Health response data is null");
|
|
648
|
-
}
|
|
649
|
-
return response.data;
|
|
647
|
+
return unwrap(await this.httpClient.get("/admin-api/health"));
|
|
650
648
|
}
|
|
651
649
|
async isAuthed() {
|
|
652
|
-
return this.httpClient.get("/is-authed");
|
|
650
|
+
return this.httpClient.get("/admin-api/is-authed");
|
|
653
651
|
}
|
|
654
|
-
// Application Management
|
|
652
|
+
// ---- Application Management ----
|
|
655
653
|
async installApplication(request) {
|
|
656
|
-
return this.httpClient.post(
|
|
657
|
-
"/install-application",
|
|
658
|
-
request
|
|
659
|
-
);
|
|
654
|
+
return unwrap(await this.httpClient.post("/admin-api/install-application", request));
|
|
660
655
|
}
|
|
661
656
|
async installDevApplication(request) {
|
|
662
|
-
return this.httpClient.post(
|
|
663
|
-
"/install-dev-application",
|
|
664
|
-
request
|
|
665
|
-
);
|
|
657
|
+
return unwrap(await this.httpClient.post("/admin-api/install-dev-application", request));
|
|
666
658
|
}
|
|
667
659
|
async uninstallApplication(appId) {
|
|
668
|
-
return this.httpClient.delete(
|
|
669
|
-
`/applications/${appId}`
|
|
670
|
-
);
|
|
660
|
+
return unwrap(await this.httpClient.delete(`/admin-api/applications/${appId}`));
|
|
671
661
|
}
|
|
672
662
|
async listApplications() {
|
|
673
|
-
return this.httpClient.get("/applications");
|
|
663
|
+
return unwrap(await this.httpClient.get("/admin-api/applications"));
|
|
674
664
|
}
|
|
675
665
|
async getApplication(appId) {
|
|
666
|
+
return unwrap(await this.httpClient.get(`/admin-api/applications/${appId}`));
|
|
667
|
+
}
|
|
668
|
+
// ---- Package Management ----
|
|
669
|
+
async getLatestPackageVersion(packageName) {
|
|
676
670
|
return this.httpClient.get(
|
|
677
|
-
`/
|
|
671
|
+
`/admin-api/packages/${encodeURIComponent(packageName)}/latest`
|
|
678
672
|
);
|
|
679
673
|
}
|
|
680
|
-
// Context Management
|
|
674
|
+
// ---- Context Management ----
|
|
681
675
|
async createContext(request) {
|
|
682
|
-
return this.httpClient.post("/contexts", request);
|
|
676
|
+
return unwrap(await this.httpClient.post("/admin-api/contexts", request));
|
|
683
677
|
}
|
|
684
678
|
async deleteContext(contextId) {
|
|
685
|
-
return this.httpClient.delete(
|
|
686
|
-
`/contexts/${contextId}`
|
|
687
|
-
);
|
|
679
|
+
return unwrap(await this.httpClient.delete(`/admin-api/contexts/${contextId}`));
|
|
688
680
|
}
|
|
689
681
|
async getContexts() {
|
|
690
|
-
return this.httpClient.get("/contexts");
|
|
682
|
+
return unwrap(await this.httpClient.get("/admin-api/contexts"));
|
|
691
683
|
}
|
|
692
684
|
async getContext(contextId) {
|
|
693
|
-
return this.httpClient.get(`/contexts/${contextId}`);
|
|
685
|
+
return unwrap(await this.httpClient.get(`/admin-api/contexts/${contextId}`));
|
|
694
686
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
return this.httpClient.post("/blobs", request);
|
|
687
|
+
async getContextsForApplication(applicationId) {
|
|
688
|
+
return unwrap(await this.httpClient.get(`/admin-api/contexts/for-application/${applicationId}`));
|
|
698
689
|
}
|
|
699
|
-
|
|
700
|
-
|
|
690
|
+
// ---- Context Identity ----
|
|
691
|
+
async generateContextIdentity() {
|
|
692
|
+
return unwrap(await this.httpClient.post("/admin-api/identity/context", {}));
|
|
701
693
|
}
|
|
702
|
-
async
|
|
703
|
-
return this.httpClient.get(
|
|
694
|
+
async getContextIdentities(contextId) {
|
|
695
|
+
return unwrap(await this.httpClient.get(`/admin-api/contexts/${contextId}/identities`));
|
|
704
696
|
}
|
|
705
|
-
async
|
|
706
|
-
return this.httpClient.get(`/
|
|
697
|
+
async getContextIdentitiesOwned(contextId) {
|
|
698
|
+
return unwrap(await this.httpClient.get(`/admin-api/contexts/${contextId}/identities-owned`));
|
|
707
699
|
}
|
|
708
|
-
//
|
|
709
|
-
async
|
|
710
|
-
return this.httpClient.post("/
|
|
700
|
+
// ---- Context Invite / Join ----
|
|
701
|
+
async inviteToContext(request) {
|
|
702
|
+
return unwrap(await this.httpClient.post("/admin-api/contexts/invite", request));
|
|
711
703
|
}
|
|
712
|
-
async
|
|
713
|
-
return this.httpClient.
|
|
704
|
+
async joinContext(request) {
|
|
705
|
+
return unwrap(await this.httpClient.post("/admin-api/contexts/join", request));
|
|
714
706
|
}
|
|
715
|
-
|
|
716
|
-
|
|
707
|
+
// ---- Blob Management ----
|
|
708
|
+
async uploadBlob(data) {
|
|
709
|
+
return unwrap(await this.httpClient.put("/admin-api/blobs", data));
|
|
717
710
|
}
|
|
718
|
-
async
|
|
719
|
-
return this.httpClient.
|
|
711
|
+
async deleteBlob(blobId) {
|
|
712
|
+
return unwrap(await this.httpClient.delete(`/admin-api/blobs/${blobId}`));
|
|
720
713
|
}
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
return this.httpClient.get("/network/peers");
|
|
714
|
+
async listBlobs() {
|
|
715
|
+
return unwrap(await this.httpClient.get("/admin-api/blobs"));
|
|
724
716
|
}
|
|
725
|
-
async
|
|
726
|
-
return this.httpClient.get(
|
|
717
|
+
async getBlob(blobId) {
|
|
718
|
+
return unwrap(await this.httpClient.get(`/admin-api/blobs/${blobId}`));
|
|
727
719
|
}
|
|
728
|
-
|
|
729
|
-
|
|
720
|
+
// ---- Alias Management ----
|
|
721
|
+
// Server uses type-specific alias routes: /admin-api/alias/{create,lookup,delete,list}/{context,application}
|
|
722
|
+
async createContextAlias(request) {
|
|
723
|
+
return this.httpClient.post("/admin-api/alias/create/context", request);
|
|
730
724
|
}
|
|
731
|
-
async
|
|
732
|
-
return this.httpClient.
|
|
733
|
-
"/network/config",
|
|
734
|
-
request
|
|
735
|
-
);
|
|
725
|
+
async createApplicationAlias(request) {
|
|
726
|
+
return this.httpClient.post("/admin-api/alias/create/application", request);
|
|
736
727
|
}
|
|
737
|
-
async
|
|
738
|
-
return this.httpClient.
|
|
728
|
+
async lookupContextAlias(name) {
|
|
729
|
+
return this.httpClient.post(`/admin-api/alias/lookup/context/${encodeURIComponent(name)}`, {});
|
|
730
|
+
}
|
|
731
|
+
async lookupApplicationAlias(name) {
|
|
732
|
+
return this.httpClient.post(`/admin-api/alias/lookup/application/${encodeURIComponent(name)}`, {});
|
|
739
733
|
}
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
return this.httpClient.get("/system/info");
|
|
734
|
+
async deleteContextAlias(name) {
|
|
735
|
+
return this.httpClient.post(`/admin-api/alias/delete/context/${encodeURIComponent(name)}`, {});
|
|
743
736
|
}
|
|
744
|
-
async
|
|
745
|
-
return this.httpClient.
|
|
737
|
+
async deleteApplicationAlias(name) {
|
|
738
|
+
return this.httpClient.post(`/admin-api/alias/delete/application/${encodeURIComponent(name)}`, {});
|
|
746
739
|
}
|
|
747
|
-
async
|
|
748
|
-
return this.httpClient.get("/
|
|
740
|
+
async listContextAliases() {
|
|
741
|
+
return unwrap(await this.httpClient.get("/admin-api/alias/list/context"));
|
|
749
742
|
}
|
|
750
|
-
async
|
|
751
|
-
return this.httpClient.
|
|
743
|
+
async listApplicationAliases() {
|
|
744
|
+
return unwrap(await this.httpClient.get("/admin-api/alias/list/application"));
|
|
752
745
|
}
|
|
753
|
-
|
|
754
|
-
|
|
746
|
+
// ---- Network ----
|
|
747
|
+
async getPeersCount() {
|
|
748
|
+
return this.httpClient.get("/admin-api/peers");
|
|
755
749
|
}
|
|
756
750
|
};
|
|
757
751
|
|
|
@@ -809,15 +803,495 @@ function createAdminApiClientFromHttpClient(httpClient, _config) {
|
|
|
809
803
|
return new AdminApiClient(httpClient);
|
|
810
804
|
}
|
|
811
805
|
|
|
806
|
+
// src/auth/index.ts
|
|
807
|
+
function parseAuthCallback(url) {
|
|
808
|
+
try {
|
|
809
|
+
const hashIndex = url.indexOf("#");
|
|
810
|
+
if (hashIndex === -1) return null;
|
|
811
|
+
const hash = url.substring(hashIndex + 1);
|
|
812
|
+
const params = new URLSearchParams(hash);
|
|
813
|
+
const accessToken = params.get("access_token");
|
|
814
|
+
if (!accessToken) return null;
|
|
815
|
+
return {
|
|
816
|
+
accessToken,
|
|
817
|
+
refreshToken: params.get("refresh_token") ?? "",
|
|
818
|
+
applicationId: params.get("application_id") ?? "",
|
|
819
|
+
contextId: params.get("context_id") ?? "",
|
|
820
|
+
contextIdentity: params.get("context_identity") ?? "",
|
|
821
|
+
nodeUrl: params.get("node_url") ?? ""
|
|
822
|
+
};
|
|
823
|
+
} catch {
|
|
824
|
+
return null;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
function buildAuthLoginUrl(nodeUrl, opts) {
|
|
828
|
+
const params = new URLSearchParams();
|
|
829
|
+
params.set("callback-url", opts.callbackUrl);
|
|
830
|
+
if (opts.permissions && opts.permissions.length > 0) {
|
|
831
|
+
params.set("permissions", opts.permissions.join(","));
|
|
832
|
+
}
|
|
833
|
+
params.set("mode", opts.mode);
|
|
834
|
+
if (opts.packageName) {
|
|
835
|
+
params.set("package-name", opts.packageName);
|
|
836
|
+
if (opts.packageVersion) {
|
|
837
|
+
params.set("package-version", opts.packageVersion);
|
|
838
|
+
}
|
|
839
|
+
if (opts.registryUrl) {
|
|
840
|
+
params.set("registry-url", opts.registryUrl);
|
|
841
|
+
}
|
|
842
|
+
}
|
|
843
|
+
const base = nodeUrl.replace(/\/+$/, "");
|
|
844
|
+
return `${base}/auth/login?${params.toString()}`;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
// src/rpc/index.ts
|
|
848
|
+
var RpcError = class extends Error {
|
|
849
|
+
constructor(code, message, data, type) {
|
|
850
|
+
super(message);
|
|
851
|
+
this.name = "RpcError";
|
|
852
|
+
this.code = code;
|
|
853
|
+
this.data = data;
|
|
854
|
+
this.type = type;
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
var RpcClient = class {
|
|
858
|
+
constructor(opts) {
|
|
859
|
+
this.httpClient = opts.httpClient;
|
|
860
|
+
}
|
|
861
|
+
async execute(params) {
|
|
862
|
+
const body = {
|
|
863
|
+
jsonrpc: "2.0",
|
|
864
|
+
id: 1,
|
|
865
|
+
method: "execute",
|
|
866
|
+
params: {
|
|
867
|
+
contextId: params.contextId,
|
|
868
|
+
method: params.method,
|
|
869
|
+
argsJson: params.argsJson ?? {},
|
|
870
|
+
executorPublicKey: params.executorPublicKey
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
const response = await this.httpClient.post(
|
|
874
|
+
"/jsonrpc",
|
|
875
|
+
body
|
|
876
|
+
);
|
|
877
|
+
if (response.error) {
|
|
878
|
+
const err = response.error;
|
|
879
|
+
const code = err.code ?? -1;
|
|
880
|
+
const message = err.message ?? err.type ?? "RPC error";
|
|
881
|
+
throw new RpcError(code, message, err.data, err.type);
|
|
882
|
+
}
|
|
883
|
+
if (response.result && "output" in response.result) {
|
|
884
|
+
return response.result.output;
|
|
885
|
+
}
|
|
886
|
+
return response.result;
|
|
887
|
+
}
|
|
888
|
+
};
|
|
889
|
+
|
|
890
|
+
// src/events/sse.ts
|
|
891
|
+
var SseClient = class {
|
|
892
|
+
constructor(opts) {
|
|
893
|
+
this.sessionId = null;
|
|
894
|
+
this.abortController = null;
|
|
895
|
+
this.reconnectTimer = null;
|
|
896
|
+
this.subscribedContextIds = /* @__PURE__ */ new Set();
|
|
897
|
+
this.closed = false;
|
|
898
|
+
this.listeners = { connect: [], event: [], error: [] };
|
|
899
|
+
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
900
|
+
this.getAuthToken = opts.getAuthToken;
|
|
901
|
+
this.reconnectDelayMs = opts.reconnectDelayMs ?? 3e3;
|
|
902
|
+
}
|
|
903
|
+
on(event, handler) {
|
|
904
|
+
const key = event;
|
|
905
|
+
if (key in this.listeners) {
|
|
906
|
+
const arr = this.listeners[key];
|
|
907
|
+
if (!arr.includes(handler)) arr.push(handler);
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
off(event, handler) {
|
|
911
|
+
const key = event;
|
|
912
|
+
if (key in this.listeners) {
|
|
913
|
+
const arr = this.listeners[key];
|
|
914
|
+
const idx = arr.indexOf(handler);
|
|
915
|
+
if (idx !== -1) arr.splice(idx, 1);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
emit(event, arg) {
|
|
919
|
+
const key = event;
|
|
920
|
+
if (key in this.listeners) {
|
|
921
|
+
for (const handler of this.listeners[key]) {
|
|
922
|
+
try {
|
|
923
|
+
handler(arg);
|
|
924
|
+
} catch {
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
async connect() {
|
|
930
|
+
if (this.abortController && !this.closed) {
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
this.closed = false;
|
|
934
|
+
this.abortController = new AbortController();
|
|
935
|
+
try {
|
|
936
|
+
const token = await this.getAuthToken();
|
|
937
|
+
const response = await fetch(`${this.baseUrl}/sse`, {
|
|
938
|
+
headers: {
|
|
939
|
+
"Authorization": `Bearer ${token}`,
|
|
940
|
+
"Accept": "text/event-stream"
|
|
941
|
+
},
|
|
942
|
+
signal: this.abortController.signal
|
|
943
|
+
});
|
|
944
|
+
if (!response.ok) {
|
|
945
|
+
throw new Error(`SSE connection failed: ${response.status}`);
|
|
946
|
+
}
|
|
947
|
+
if (!response.body) {
|
|
948
|
+
throw new Error("SSE response has no body");
|
|
949
|
+
}
|
|
950
|
+
this.readStream(response.body).catch((err) => {
|
|
951
|
+
if (this.closed) return;
|
|
952
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
953
|
+
this.emit("error", error);
|
|
954
|
+
this.scheduleReconnect();
|
|
955
|
+
});
|
|
956
|
+
} catch (err) {
|
|
957
|
+
if (this.closed) return;
|
|
958
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
959
|
+
this.emit("error", error);
|
|
960
|
+
this.scheduleReconnect();
|
|
961
|
+
}
|
|
962
|
+
}
|
|
963
|
+
async readStream(body) {
|
|
964
|
+
const reader = body.getReader();
|
|
965
|
+
const decoder = new TextDecoder();
|
|
966
|
+
let buffer = "";
|
|
967
|
+
try {
|
|
968
|
+
for (; ; ) {
|
|
969
|
+
const { done, value } = await reader.read();
|
|
970
|
+
if (done) break;
|
|
971
|
+
buffer += decoder.decode(value, { stream: true });
|
|
972
|
+
const lines = buffer.split("\n");
|
|
973
|
+
buffer = lines.pop() ?? "";
|
|
974
|
+
for (const line of lines) {
|
|
975
|
+
if (line.startsWith("data:")) {
|
|
976
|
+
const jsonStr = line.slice(5).trim();
|
|
977
|
+
if (jsonStr) {
|
|
978
|
+
this.handleMessage(jsonStr);
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
buffer += decoder.decode();
|
|
984
|
+
if (buffer.startsWith("data:")) {
|
|
985
|
+
const jsonStr = buffer.slice(5).trim();
|
|
986
|
+
if (jsonStr) {
|
|
987
|
+
this.handleMessage(jsonStr);
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
} catch (err) {
|
|
991
|
+
if (this.closed) return;
|
|
992
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
993
|
+
this.emit("error", error);
|
|
994
|
+
}
|
|
995
|
+
if (!this.closed) {
|
|
996
|
+
this.scheduleReconnect();
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
handleMessage(jsonStr) {
|
|
1000
|
+
try {
|
|
1001
|
+
const msg = JSON.parse(jsonStr);
|
|
1002
|
+
if (msg.type === "connect" && msg.session_id) {
|
|
1003
|
+
this.sessionId = msg.session_id;
|
|
1004
|
+
this.emit("connect", msg.session_id);
|
|
1005
|
+
if (this.subscribedContextIds.size > 0) {
|
|
1006
|
+
this.sendSubscription("subscribe", [...this.subscribedContextIds]);
|
|
1007
|
+
}
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
if (msg.result && msg.result.contextId) {
|
|
1011
|
+
let eventData = msg.result.data;
|
|
1012
|
+
if (Array.isArray(eventData)) {
|
|
1013
|
+
try {
|
|
1014
|
+
const bytes = new Uint8Array(eventData);
|
|
1015
|
+
const text = new TextDecoder().decode(bytes);
|
|
1016
|
+
eventData = JSON.parse(text);
|
|
1017
|
+
} catch {
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
this.emit("event", {
|
|
1021
|
+
contextId: msg.result.contextId,
|
|
1022
|
+
data: eventData
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
} catch {
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
async subscribe(contextIds) {
|
|
1029
|
+
const newIds = contextIds.filter((id) => !this.subscribedContextIds.has(id));
|
|
1030
|
+
for (const id of contextIds) {
|
|
1031
|
+
this.subscribedContextIds.add(id);
|
|
1032
|
+
}
|
|
1033
|
+
if (newIds.length > 0 && this.sessionId) {
|
|
1034
|
+
await this.sendSubscription("subscribe", newIds);
|
|
1035
|
+
}
|
|
1036
|
+
}
|
|
1037
|
+
async unsubscribe(contextIds) {
|
|
1038
|
+
const hadIds = contextIds.filter((id) => this.subscribedContextIds.has(id));
|
|
1039
|
+
for (const id of contextIds) {
|
|
1040
|
+
this.subscribedContextIds.delete(id);
|
|
1041
|
+
}
|
|
1042
|
+
if (hadIds.length > 0 && this.sessionId) {
|
|
1043
|
+
await this.sendSubscription("unsubscribe", hadIds);
|
|
1044
|
+
}
|
|
1045
|
+
}
|
|
1046
|
+
async sendSubscription(method, contextIds) {
|
|
1047
|
+
try {
|
|
1048
|
+
const token = await this.getAuthToken();
|
|
1049
|
+
const response = await fetch(`${this.baseUrl}/sse/subscription`, {
|
|
1050
|
+
method: "POST",
|
|
1051
|
+
headers: {
|
|
1052
|
+
"Authorization": `Bearer ${token}`,
|
|
1053
|
+
"Content-Type": "application/json"
|
|
1054
|
+
},
|
|
1055
|
+
body: JSON.stringify({
|
|
1056
|
+
id: this.sessionId,
|
|
1057
|
+
method,
|
|
1058
|
+
params: { contextIds }
|
|
1059
|
+
})
|
|
1060
|
+
});
|
|
1061
|
+
if (!response.ok) {
|
|
1062
|
+
this.emit("error", new Error(`SSE ${method} failed: ${response.status}`));
|
|
1063
|
+
}
|
|
1064
|
+
} catch (err) {
|
|
1065
|
+
this.emit("error", err instanceof Error ? err : new Error(`SSE ${method} failed`));
|
|
1066
|
+
}
|
|
1067
|
+
}
|
|
1068
|
+
forceReconnect() {
|
|
1069
|
+
if (this.abortController) {
|
|
1070
|
+
this.abortController.abort();
|
|
1071
|
+
this.abortController = null;
|
|
1072
|
+
}
|
|
1073
|
+
this.sessionId = null;
|
|
1074
|
+
this.connect();
|
|
1075
|
+
}
|
|
1076
|
+
scheduleReconnect() {
|
|
1077
|
+
if (this.closed) return;
|
|
1078
|
+
if (this.reconnectTimer) {
|
|
1079
|
+
clearTimeout(this.reconnectTimer);
|
|
1080
|
+
}
|
|
1081
|
+
this.reconnectTimer = setTimeout(() => {
|
|
1082
|
+
this.reconnectTimer = null;
|
|
1083
|
+
this.forceReconnect();
|
|
1084
|
+
}, this.reconnectDelayMs);
|
|
1085
|
+
}
|
|
1086
|
+
close() {
|
|
1087
|
+
this.closed = true;
|
|
1088
|
+
if (this.abortController) {
|
|
1089
|
+
this.abortController.abort();
|
|
1090
|
+
this.abortController = null;
|
|
1091
|
+
}
|
|
1092
|
+
if (this.reconnectTimer) {
|
|
1093
|
+
clearTimeout(this.reconnectTimer);
|
|
1094
|
+
this.reconnectTimer = null;
|
|
1095
|
+
}
|
|
1096
|
+
this.sessionId = null;
|
|
1097
|
+
this.subscribedContextIds.clear();
|
|
1098
|
+
}
|
|
1099
|
+
};
|
|
1100
|
+
|
|
1101
|
+
// src/events/ws.ts
|
|
1102
|
+
var _WsClient = class _WsClient {
|
|
1103
|
+
constructor(opts) {
|
|
1104
|
+
this.ws = null;
|
|
1105
|
+
this.closed = false;
|
|
1106
|
+
this.reconnectAttempt = 0;
|
|
1107
|
+
this.reconnectTimer = null;
|
|
1108
|
+
this.subscribedContextIds = /* @__PURE__ */ new Set();
|
|
1109
|
+
this.listeners = { connect: [], event: [], error: [] };
|
|
1110
|
+
this.baseUrl = opts.baseUrl.replace(/\/+$/, "");
|
|
1111
|
+
this.getAuthToken = opts.getAuthToken;
|
|
1112
|
+
}
|
|
1113
|
+
on(event, handler) {
|
|
1114
|
+
const key = event;
|
|
1115
|
+
if (key in this.listeners) {
|
|
1116
|
+
const arr = this.listeners[key];
|
|
1117
|
+
if (!arr.includes(handler)) arr.push(handler);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
off(event, handler) {
|
|
1121
|
+
const key = event;
|
|
1122
|
+
if (key in this.listeners) {
|
|
1123
|
+
const arr = this.listeners[key];
|
|
1124
|
+
const idx = arr.indexOf(handler);
|
|
1125
|
+
if (idx !== -1) arr.splice(idx, 1);
|
|
1126
|
+
}
|
|
1127
|
+
}
|
|
1128
|
+
emit(event, arg) {
|
|
1129
|
+
const key = event;
|
|
1130
|
+
if (key in this.listeners) {
|
|
1131
|
+
for (const handler of this.listeners[key]) {
|
|
1132
|
+
try {
|
|
1133
|
+
handler(arg);
|
|
1134
|
+
} catch {
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
}
|
|
1138
|
+
}
|
|
1139
|
+
async connect() {
|
|
1140
|
+
if (this.ws && (this.ws.readyState === WebSocket.CONNECTING || this.ws.readyState === WebSocket.OPEN)) {
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
this.closed = false;
|
|
1144
|
+
try {
|
|
1145
|
+
const token = await this.getAuthToken();
|
|
1146
|
+
if (!token) {
|
|
1147
|
+
throw new Error("No authentication token available for WebSocket connection");
|
|
1148
|
+
}
|
|
1149
|
+
const wsUrl = this.baseUrl.replace(/^http/, "ws");
|
|
1150
|
+
this.ws = new WebSocket(`${wsUrl}/ws?token=${encodeURIComponent(token)}`);
|
|
1151
|
+
this.ws.onopen = () => {
|
|
1152
|
+
this.reconnectAttempt = 0;
|
|
1153
|
+
this.emit("connect");
|
|
1154
|
+
if (this.subscribedContextIds.size > 0) {
|
|
1155
|
+
this.sendMessage({
|
|
1156
|
+
id: null,
|
|
1157
|
+
method: "subscribe",
|
|
1158
|
+
params: { contextIds: [...this.subscribedContextIds] }
|
|
1159
|
+
});
|
|
1160
|
+
}
|
|
1161
|
+
};
|
|
1162
|
+
this.ws.onmessage = (event) => {
|
|
1163
|
+
this.handleMessage(event.data);
|
|
1164
|
+
};
|
|
1165
|
+
this.ws.onerror = () => {
|
|
1166
|
+
this.emit("error", new Error("WebSocket error"));
|
|
1167
|
+
};
|
|
1168
|
+
this.ws.onclose = () => {
|
|
1169
|
+
if (!this.closed) {
|
|
1170
|
+
this.scheduleReconnect();
|
|
1171
|
+
}
|
|
1172
|
+
};
|
|
1173
|
+
} catch (err) {
|
|
1174
|
+
if (this.closed) return;
|
|
1175
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
1176
|
+
this.emit("error", error);
|
|
1177
|
+
this.scheduleReconnect();
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
handleMessage(raw) {
|
|
1181
|
+
if (typeof raw !== "string") return;
|
|
1182
|
+
try {
|
|
1183
|
+
const msg = JSON.parse(raw);
|
|
1184
|
+
if (msg.result && msg.result.contextId) {
|
|
1185
|
+
let eventData = msg.result.data;
|
|
1186
|
+
if (Array.isArray(eventData)) {
|
|
1187
|
+
try {
|
|
1188
|
+
const bytes = new Uint8Array(eventData);
|
|
1189
|
+
const text = new TextDecoder().decode(bytes);
|
|
1190
|
+
eventData = JSON.parse(text);
|
|
1191
|
+
} catch {
|
|
1192
|
+
}
|
|
1193
|
+
}
|
|
1194
|
+
this.emit("event", {
|
|
1195
|
+
contextId: msg.result.contextId,
|
|
1196
|
+
data: eventData
|
|
1197
|
+
});
|
|
1198
|
+
}
|
|
1199
|
+
} catch {
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
subscribe(contextIds) {
|
|
1203
|
+
for (const id of contextIds) {
|
|
1204
|
+
this.subscribedContextIds.add(id);
|
|
1205
|
+
}
|
|
1206
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
1207
|
+
this.sendMessage({
|
|
1208
|
+
id: null,
|
|
1209
|
+
method: "subscribe",
|
|
1210
|
+
params: { contextIds }
|
|
1211
|
+
});
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
unsubscribe(contextIds) {
|
|
1215
|
+
for (const id of contextIds) {
|
|
1216
|
+
this.subscribedContextIds.delete(id);
|
|
1217
|
+
}
|
|
1218
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
1219
|
+
this.sendMessage({
|
|
1220
|
+
id: null,
|
|
1221
|
+
method: "unsubscribe",
|
|
1222
|
+
params: { contextIds }
|
|
1223
|
+
});
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
sendMessage(msg) {
|
|
1227
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
1228
|
+
this.ws.send(JSON.stringify(msg));
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
scheduleReconnect() {
|
|
1232
|
+
if (this.closed) return;
|
|
1233
|
+
if (this.reconnectTimer) {
|
|
1234
|
+
clearTimeout(this.reconnectTimer);
|
|
1235
|
+
}
|
|
1236
|
+
const delay = Math.min(
|
|
1237
|
+
1e3 * Math.pow(2, this.reconnectAttempt),
|
|
1238
|
+
_WsClient.MAX_BACKOFF_MS
|
|
1239
|
+
);
|
|
1240
|
+
this.reconnectAttempt++;
|
|
1241
|
+
this.reconnectTimer = setTimeout(() => {
|
|
1242
|
+
this.reconnectTimer = null;
|
|
1243
|
+
this.connect();
|
|
1244
|
+
}, delay);
|
|
1245
|
+
}
|
|
1246
|
+
close() {
|
|
1247
|
+
this.closed = true;
|
|
1248
|
+
if (this.reconnectTimer) {
|
|
1249
|
+
clearTimeout(this.reconnectTimer);
|
|
1250
|
+
this.reconnectTimer = null;
|
|
1251
|
+
}
|
|
1252
|
+
if (this.ws) {
|
|
1253
|
+
this.ws.onclose = null;
|
|
1254
|
+
this.ws.close();
|
|
1255
|
+
this.ws = null;
|
|
1256
|
+
}
|
|
1257
|
+
this.subscribedContextIds.clear();
|
|
1258
|
+
}
|
|
1259
|
+
};
|
|
1260
|
+
_WsClient.MAX_BACKOFF_MS = 3e4;
|
|
1261
|
+
var WsClient = _WsClient;
|
|
1262
|
+
|
|
812
1263
|
// src/mero-js.ts
|
|
1264
|
+
function expiresAtFromJwt(token, fallbackMs) {
|
|
1265
|
+
try {
|
|
1266
|
+
const parts = token.split(".");
|
|
1267
|
+
if (parts.length === 3) {
|
|
1268
|
+
let b64 = parts[1].replace(/-/g, "+").replace(/_/g, "/");
|
|
1269
|
+
while (b64.length % 4) b64 += "=";
|
|
1270
|
+
const payload = JSON.parse(atob(b64));
|
|
1271
|
+
if (typeof payload.exp === "number") {
|
|
1272
|
+
return payload.exp * 1e3;
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
} catch {
|
|
1276
|
+
}
|
|
1277
|
+
return fallbackMs;
|
|
1278
|
+
}
|
|
813
1279
|
var MeroJs = class {
|
|
814
1280
|
constructor(config) {
|
|
815
1281
|
this.tokenData = null;
|
|
816
1282
|
this.refreshPromise = null;
|
|
1283
|
+
this.rpcClient = null;
|
|
1284
|
+
this.sseClient = null;
|
|
1285
|
+
this.wsClient = null;
|
|
1286
|
+
this.wsWarned = false;
|
|
817
1287
|
this.config = {
|
|
818
1288
|
timeoutMs: 1e4,
|
|
819
1289
|
...config
|
|
820
1290
|
};
|
|
1291
|
+
this.tokenStore = config.tokenStore ?? null;
|
|
1292
|
+
if (this.tokenStore) {
|
|
1293
|
+
this.tokenData = this.tokenStore.getTokens();
|
|
1294
|
+
}
|
|
821
1295
|
const isTauri = typeof window !== "undefined" && "__TAURI_INTERNALS__" in window;
|
|
822
1296
|
this.httpClient = createBrowserHttpClient({
|
|
823
1297
|
baseUrl: this.config.baseUrl,
|
|
@@ -825,6 +1299,16 @@ var MeroJs = class {
|
|
|
825
1299
|
const token = await this.getValidToken();
|
|
826
1300
|
return token?.access_token || "";
|
|
827
1301
|
},
|
|
1302
|
+
refreshToken: async () => {
|
|
1303
|
+
const refreshed = await this.performTokenRefresh();
|
|
1304
|
+
return refreshed.access_token;
|
|
1305
|
+
},
|
|
1306
|
+
onTokenRefresh: async (newToken) => {
|
|
1307
|
+
if (this.tokenData) {
|
|
1308
|
+
this.tokenData.access_token = newToken;
|
|
1309
|
+
this.tokenStore?.setTokens(this.tokenData);
|
|
1310
|
+
}
|
|
1311
|
+
},
|
|
828
1312
|
timeoutMs: this.config.timeoutMs,
|
|
829
1313
|
credentials: this.config.requestCredentials ?? (isTauri ? "omit" : void 0)
|
|
830
1314
|
});
|
|
@@ -857,6 +1341,50 @@ var MeroJs = class {
|
|
|
857
1341
|
get admin() {
|
|
858
1342
|
return this.adminClient;
|
|
859
1343
|
}
|
|
1344
|
+
/**
|
|
1345
|
+
* Get the RPC client (lazy initialized)
|
|
1346
|
+
*/
|
|
1347
|
+
get rpc() {
|
|
1348
|
+
if (!this.rpcClient) {
|
|
1349
|
+
this.rpcClient = new RpcClient({ httpClient: this.httpClient });
|
|
1350
|
+
}
|
|
1351
|
+
return this.rpcClient;
|
|
1352
|
+
}
|
|
1353
|
+
/**
|
|
1354
|
+
* Get the SSE event client (lazy initialized)
|
|
1355
|
+
*/
|
|
1356
|
+
get events() {
|
|
1357
|
+
if (!this.sseClient) {
|
|
1358
|
+
this.sseClient = new SseClient({
|
|
1359
|
+
baseUrl: this.config.baseUrl,
|
|
1360
|
+
getAuthToken: async () => {
|
|
1361
|
+
const token = await this.getValidToken();
|
|
1362
|
+
return token?.access_token || "";
|
|
1363
|
+
}
|
|
1364
|
+
});
|
|
1365
|
+
}
|
|
1366
|
+
return this.sseClient;
|
|
1367
|
+
}
|
|
1368
|
+
/**
|
|
1369
|
+
* Get the WebSocket event client (lazy initialized).
|
|
1370
|
+
* @experimental Use `events` (SSE) for production. WsClient is experimental.
|
|
1371
|
+
*/
|
|
1372
|
+
get ws() {
|
|
1373
|
+
if (!this.wsWarned) {
|
|
1374
|
+
this.wsWarned = true;
|
|
1375
|
+
console.warn("[mero-js] WsClient is experimental. Use mero.events (SSE) for production.");
|
|
1376
|
+
}
|
|
1377
|
+
if (!this.wsClient) {
|
|
1378
|
+
this.wsClient = new WsClient({
|
|
1379
|
+
baseUrl: this.config.baseUrl,
|
|
1380
|
+
getAuthToken: async () => {
|
|
1381
|
+
const token = await this.getValidToken();
|
|
1382
|
+
return token?.access_token || "";
|
|
1383
|
+
}
|
|
1384
|
+
});
|
|
1385
|
+
}
|
|
1386
|
+
return this.wsClient;
|
|
1387
|
+
}
|
|
860
1388
|
/**
|
|
861
1389
|
* Authenticate with the provided credentials
|
|
862
1390
|
* This will create the root key on first use
|
|
@@ -879,12 +1407,13 @@ var MeroJs = class {
|
|
|
879
1407
|
}
|
|
880
1408
|
};
|
|
881
1409
|
const response = await this.authClient.generateTokens(requestBody);
|
|
1410
|
+
const accessToken = response.data.access_token;
|
|
882
1411
|
this.tokenData = {
|
|
883
|
-
access_token:
|
|
1412
|
+
access_token: accessToken,
|
|
884
1413
|
refresh_token: response.data.refresh_token,
|
|
885
|
-
expires_at: Date.now() +
|
|
886
|
-
// Default to 24 hours
|
|
1414
|
+
expires_at: expiresAtFromJwt(accessToken, Date.now() + 36e5)
|
|
887
1415
|
};
|
|
1416
|
+
this.tokenStore?.setTokens(this.tokenData);
|
|
888
1417
|
return this.tokenData;
|
|
889
1418
|
} catch (error) {
|
|
890
1419
|
throw new Error(
|
|
@@ -893,16 +1422,12 @@ var MeroJs = class {
|
|
|
893
1422
|
}
|
|
894
1423
|
}
|
|
895
1424
|
/**
|
|
896
|
-
* Get a valid token
|
|
1425
|
+
* Get a valid token. Returns the current token as-is.
|
|
1426
|
+
* The server rejects refresh attempts while the access token is still valid,
|
|
1427
|
+
* so we never proactively refresh. Instead, the WebHttpClient handles 401
|
|
1428
|
+
* responses reactively via the refreshToken transport hook.
|
|
897
1429
|
*/
|
|
898
1430
|
async getValidToken() {
|
|
899
|
-
if (!this.tokenData) {
|
|
900
|
-
return null;
|
|
901
|
-
}
|
|
902
|
-
const bufferTime = 5 * 60 * 1e3;
|
|
903
|
-
if (Date.now() >= this.tokenData.expires_at - bufferTime) {
|
|
904
|
-
return await this.refreshToken();
|
|
905
|
-
}
|
|
906
1431
|
return this.tokenData;
|
|
907
1432
|
}
|
|
908
1433
|
/**
|
|
@@ -935,15 +1460,15 @@ var MeroJs = class {
|
|
|
935
1460
|
access_token: this.tokenData.access_token,
|
|
936
1461
|
refresh_token: this.tokenData.refresh_token
|
|
937
1462
|
});
|
|
1463
|
+
const accessToken = response.data.access_token;
|
|
938
1464
|
this.tokenData = {
|
|
939
|
-
access_token:
|
|
1465
|
+
access_token: accessToken,
|
|
940
1466
|
refresh_token: response.data.refresh_token,
|
|
941
|
-
expires_at: Date.now() +
|
|
942
|
-
// Default to 24 hours
|
|
1467
|
+
expires_at: expiresAtFromJwt(accessToken, Date.now() + 36e5)
|
|
943
1468
|
};
|
|
1469
|
+
this.tokenStore?.setTokens(this.tokenData);
|
|
944
1470
|
return this.tokenData;
|
|
945
1471
|
} catch (error) {
|
|
946
|
-
this.clearToken();
|
|
947
1472
|
throw new Error(
|
|
948
1473
|
`Token refresh failed: ${error instanceof Error ? error.message : "Unknown error"}`
|
|
949
1474
|
);
|
|
@@ -954,6 +1479,7 @@ var MeroJs = class {
|
|
|
954
1479
|
*/
|
|
955
1480
|
clearToken() {
|
|
956
1481
|
this.tokenData = null;
|
|
1482
|
+
this.tokenStore?.clear();
|
|
957
1483
|
}
|
|
958
1484
|
/**
|
|
959
1485
|
* Check if the SDK is authenticated
|
|
@@ -961,22 +1487,112 @@ var MeroJs = class {
|
|
|
961
1487
|
isAuthenticated() {
|
|
962
1488
|
return this.tokenData !== null;
|
|
963
1489
|
}
|
|
1490
|
+
/**
|
|
1491
|
+
* Set token data directly (e.g., from auth callback).
|
|
1492
|
+
* If `expires_at` is missing or 0, attempts to parse the JWT exp claim,
|
|
1493
|
+
* falling back to 1 hour from now.
|
|
1494
|
+
*/
|
|
1495
|
+
setTokenData(data) {
|
|
1496
|
+
const expiresAt = data.expires_at || expiresAtFromJwt(data.access_token, Date.now() + 36e5);
|
|
1497
|
+
this.tokenData = { ...data, expires_at: expiresAt };
|
|
1498
|
+
this.tokenStore?.setTokens(this.tokenData);
|
|
1499
|
+
}
|
|
964
1500
|
/**
|
|
965
1501
|
* Get the current token data (for debugging)
|
|
966
1502
|
*/
|
|
967
1503
|
getTokenData() {
|
|
968
1504
|
return this.tokenData;
|
|
969
1505
|
}
|
|
1506
|
+
/**
|
|
1507
|
+
* Close all event connections and clean up resources
|
|
1508
|
+
*/
|
|
1509
|
+
close() {
|
|
1510
|
+
this.sseClient?.close();
|
|
1511
|
+
this.wsClient?.close();
|
|
1512
|
+
}
|
|
1513
|
+
/**
|
|
1514
|
+
* Parse an auth callback URL hash fragment (static utility)
|
|
1515
|
+
*/
|
|
1516
|
+
static parseAuthCallback(url) {
|
|
1517
|
+
return parseAuthCallback(url);
|
|
1518
|
+
}
|
|
1519
|
+
/**
|
|
1520
|
+
* Build an auth login URL (static utility)
|
|
1521
|
+
*/
|
|
1522
|
+
static buildAuthLoginUrl(nodeUrl, opts) {
|
|
1523
|
+
return buildAuthLoginUrl(nodeUrl, opts);
|
|
1524
|
+
}
|
|
970
1525
|
};
|
|
971
1526
|
function createMeroJs(config) {
|
|
972
1527
|
return new MeroJs(config);
|
|
973
1528
|
}
|
|
1529
|
+
|
|
1530
|
+
// src/token-store/index.ts
|
|
1531
|
+
var MemoryTokenStore = class {
|
|
1532
|
+
constructor() {
|
|
1533
|
+
this.tokens = null;
|
|
1534
|
+
}
|
|
1535
|
+
getTokens() {
|
|
1536
|
+
return this.tokens;
|
|
1537
|
+
}
|
|
1538
|
+
setTokens(data) {
|
|
1539
|
+
this.tokens = data;
|
|
1540
|
+
}
|
|
1541
|
+
clear() {
|
|
1542
|
+
this.tokens = null;
|
|
1543
|
+
}
|
|
1544
|
+
};
|
|
1545
|
+
var STORAGE_KEY = "mero-tokens";
|
|
1546
|
+
var LocalStorageTokenStore = class {
|
|
1547
|
+
constructor(key = STORAGE_KEY) {
|
|
1548
|
+
this.key = key;
|
|
1549
|
+
}
|
|
1550
|
+
getTokens() {
|
|
1551
|
+
try {
|
|
1552
|
+
if (typeof localStorage === "undefined") return null;
|
|
1553
|
+
const raw = localStorage.getItem(this.key);
|
|
1554
|
+
if (!raw) return null;
|
|
1555
|
+
const parsed = JSON.parse(raw);
|
|
1556
|
+
if (parsed && parsed.access_token && parsed.refresh_token) {
|
|
1557
|
+
return {
|
|
1558
|
+
access_token: parsed.access_token,
|
|
1559
|
+
refresh_token: parsed.refresh_token,
|
|
1560
|
+
expires_at: typeof parsed.expires_at === "number" ? parsed.expires_at : Date.now() + 36e5
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
return null;
|
|
1564
|
+
} catch {
|
|
1565
|
+
return null;
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
setTokens(data) {
|
|
1569
|
+
try {
|
|
1570
|
+
if (typeof localStorage === "undefined") return;
|
|
1571
|
+
localStorage.setItem(this.key, JSON.stringify(data));
|
|
1572
|
+
} catch {
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
clear() {
|
|
1576
|
+
try {
|
|
1577
|
+
if (typeof localStorage === "undefined") return;
|
|
1578
|
+
localStorage.removeItem(this.key);
|
|
1579
|
+
} catch {
|
|
1580
|
+
}
|
|
1581
|
+
}
|
|
1582
|
+
};
|
|
974
1583
|
export {
|
|
975
1584
|
AdminApiClient,
|
|
976
1585
|
AuthApiClient,
|
|
977
1586
|
HTTPError,
|
|
1587
|
+
LocalStorageTokenStore,
|
|
1588
|
+
MemoryTokenStore,
|
|
978
1589
|
MeroJs,
|
|
1590
|
+
RpcClient,
|
|
1591
|
+
RpcError,
|
|
1592
|
+
SseClient,
|
|
979
1593
|
WebHttpClient,
|
|
1594
|
+
WsClient,
|
|
1595
|
+
buildAuthLoginUrl,
|
|
980
1596
|
combineSignals,
|
|
981
1597
|
createAdminApiClient,
|
|
982
1598
|
createAdminApiClientFromHttpClient,
|
|
@@ -993,6 +1609,7 @@ export {
|
|
|
993
1609
|
createRetryableMethod,
|
|
994
1610
|
createTimeoutSignal,
|
|
995
1611
|
createUniversalHttpClient,
|
|
1612
|
+
parseAuthCallback,
|
|
996
1613
|
withRetry
|
|
997
1614
|
};
|
|
998
1615
|
//# sourceMappingURL=index.mjs.map
|