@themoltnet/legreffier 0.1.0 → 0.2.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 +16 -17
- package/dist/index.js +1225 -384
- package/package.json +4 -4
package/dist/index.js
CHANGED
|
@@ -2,13 +2,12 @@
|
|
|
2
2
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
3
3
|
import { parseArgs } from "node:util";
|
|
4
4
|
import { useInput, Box, Text, useApp, render } from "ink";
|
|
5
|
-
import { join
|
|
5
|
+
import { join } from "node:path";
|
|
6
6
|
import { useState, useEffect, useReducer, useRef } from "react";
|
|
7
7
|
import figlet from "figlet";
|
|
8
|
-
import { readFile,
|
|
8
|
+
import { readFile, mkdir, writeFile, chmod, rm } from "node:fs/promises";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
|
-
import { randomBytes as randomBytes$1
|
|
11
|
-
import { execSync } from "node:child_process";
|
|
10
|
+
import { createHash, randomBytes as randomBytes$1 } from "crypto";
|
|
12
11
|
import open from "open";
|
|
13
12
|
const colors = {
|
|
14
13
|
// Primary — teal/cyan (The Network)
|
|
@@ -350,13 +349,13 @@ function CliSummaryBox({
|
|
|
350
349
|
}
|
|
351
350
|
) });
|
|
352
351
|
}
|
|
353
|
-
const jsonBodySerializer = {
|
|
352
|
+
const jsonBodySerializer$1 = {
|
|
354
353
|
bodySerializer: (body) => JSON.stringify(
|
|
355
354
|
body,
|
|
356
355
|
(_key, value) => typeof value === "bigint" ? value.toString() : value
|
|
357
356
|
)
|
|
358
357
|
};
|
|
359
|
-
const createSseClient = ({
|
|
358
|
+
const createSseClient$1 = ({
|
|
360
359
|
onRequest,
|
|
361
360
|
onSseError,
|
|
362
361
|
onSseEvent,
|
|
@@ -490,7 +489,7 @@ const createSseClient = ({
|
|
|
490
489
|
const stream = createStream();
|
|
491
490
|
return { stream };
|
|
492
491
|
};
|
|
493
|
-
const separatorArrayExplode = (style) => {
|
|
492
|
+
const separatorArrayExplode$1 = (style) => {
|
|
494
493
|
switch (style) {
|
|
495
494
|
case "label":
|
|
496
495
|
return ".";
|
|
@@ -502,7 +501,7 @@ const separatorArrayExplode = (style) => {
|
|
|
502
501
|
return "&";
|
|
503
502
|
}
|
|
504
503
|
};
|
|
505
|
-
const separatorArrayNoExplode = (style) => {
|
|
504
|
+
const separatorArrayNoExplode$1 = (style) => {
|
|
506
505
|
switch (style) {
|
|
507
506
|
case "form":
|
|
508
507
|
return ",";
|
|
@@ -514,7 +513,7 @@ const separatorArrayNoExplode = (style) => {
|
|
|
514
513
|
return ",";
|
|
515
514
|
}
|
|
516
515
|
};
|
|
517
|
-
const separatorObjectExplode = (style) => {
|
|
516
|
+
const separatorObjectExplode$1 = (style) => {
|
|
518
517
|
switch (style) {
|
|
519
518
|
case "label":
|
|
520
519
|
return ".";
|
|
@@ -526,7 +525,7 @@ const separatorObjectExplode = (style) => {
|
|
|
526
525
|
return "&";
|
|
527
526
|
}
|
|
528
527
|
};
|
|
529
|
-
const serializeArrayParam = ({
|
|
528
|
+
const serializeArrayParam$1 = ({
|
|
530
529
|
allowReserved,
|
|
531
530
|
explode,
|
|
532
531
|
name: name2,
|
|
@@ -534,7 +533,7 @@ const serializeArrayParam = ({
|
|
|
534
533
|
value
|
|
535
534
|
}) => {
|
|
536
535
|
if (!explode) {
|
|
537
|
-
const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
|
|
536
|
+
const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode$1(style));
|
|
538
537
|
switch (style) {
|
|
539
538
|
case "label":
|
|
540
539
|
return `.${joinedValues2}`;
|
|
@@ -546,12 +545,12 @@ const serializeArrayParam = ({
|
|
|
546
545
|
return `${name2}=${joinedValues2}`;
|
|
547
546
|
}
|
|
548
547
|
}
|
|
549
|
-
const separator = separatorArrayExplode(style);
|
|
548
|
+
const separator = separatorArrayExplode$1(style);
|
|
550
549
|
const joinedValues = value.map((v) => {
|
|
551
550
|
if (style === "label" || style === "simple") {
|
|
552
551
|
return allowReserved ? v : encodeURIComponent(v);
|
|
553
552
|
}
|
|
554
|
-
return serializePrimitiveParam({
|
|
553
|
+
return serializePrimitiveParam$1({
|
|
555
554
|
allowReserved,
|
|
556
555
|
name: name2,
|
|
557
556
|
value: v
|
|
@@ -559,7 +558,7 @@ const serializeArrayParam = ({
|
|
|
559
558
|
}).join(separator);
|
|
560
559
|
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
561
560
|
};
|
|
562
|
-
const serializePrimitiveParam = ({
|
|
561
|
+
const serializePrimitiveParam$1 = ({
|
|
563
562
|
allowReserved,
|
|
564
563
|
name: name2,
|
|
565
564
|
value
|
|
@@ -574,7 +573,7 @@ const serializePrimitiveParam = ({
|
|
|
574
573
|
}
|
|
575
574
|
return `${name2}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
576
575
|
};
|
|
577
|
-
const serializeObjectParam = ({
|
|
576
|
+
const serializeObjectParam$1 = ({
|
|
578
577
|
allowReserved,
|
|
579
578
|
explode,
|
|
580
579
|
name: name2,
|
|
@@ -606,9 +605,9 @@ const serializeObjectParam = ({
|
|
|
606
605
|
return joinedValues2;
|
|
607
606
|
}
|
|
608
607
|
}
|
|
609
|
-
const separator = separatorObjectExplode(style);
|
|
608
|
+
const separator = separatorObjectExplode$1(style);
|
|
610
609
|
const joinedValues = Object.entries(value).map(
|
|
611
|
-
([key, v]) => serializePrimitiveParam({
|
|
610
|
+
([key, v]) => serializePrimitiveParam$1({
|
|
612
611
|
allowReserved,
|
|
613
612
|
name: style === "deepObject" ? `${name2}[${key}]` : key,
|
|
614
613
|
value: v
|
|
@@ -616,10 +615,10 @@ const serializeObjectParam = ({
|
|
|
616
615
|
).join(separator);
|
|
617
616
|
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
618
617
|
};
|
|
619
|
-
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
620
|
-
const defaultPathSerializer = ({ path, url: _url }) => {
|
|
618
|
+
const PATH_PARAM_RE$1 = /\{[^{}]+\}/g;
|
|
619
|
+
const defaultPathSerializer$1 = ({ path, url: _url }) => {
|
|
621
620
|
let url = _url;
|
|
622
|
-
const matches = _url.match(PATH_PARAM_RE);
|
|
621
|
+
const matches = _url.match(PATH_PARAM_RE$1);
|
|
623
622
|
if (matches) {
|
|
624
623
|
for (const match of matches) {
|
|
625
624
|
let explode = false;
|
|
@@ -643,14 +642,14 @@ const defaultPathSerializer = ({ path, url: _url }) => {
|
|
|
643
642
|
if (Array.isArray(value)) {
|
|
644
643
|
url = url.replace(
|
|
645
644
|
match,
|
|
646
|
-
serializeArrayParam({ explode, name: name2, style, value })
|
|
645
|
+
serializeArrayParam$1({ explode, name: name2, style, value })
|
|
647
646
|
);
|
|
648
647
|
continue;
|
|
649
648
|
}
|
|
650
649
|
if (typeof value === "object") {
|
|
651
650
|
url = url.replace(
|
|
652
651
|
match,
|
|
653
|
-
serializeObjectParam({
|
|
652
|
+
serializeObjectParam$1({
|
|
654
653
|
explode,
|
|
655
654
|
name: name2,
|
|
656
655
|
style,
|
|
@@ -663,7 +662,7 @@ const defaultPathSerializer = ({ path, url: _url }) => {
|
|
|
663
662
|
if (style === "matrix") {
|
|
664
663
|
url = url.replace(
|
|
665
664
|
match,
|
|
666
|
-
`;${serializePrimitiveParam({
|
|
665
|
+
`;${serializePrimitiveParam$1({
|
|
667
666
|
name: name2,
|
|
668
667
|
value
|
|
669
668
|
})}`
|
|
@@ -678,7 +677,7 @@ const defaultPathSerializer = ({ path, url: _url }) => {
|
|
|
678
677
|
}
|
|
679
678
|
return url;
|
|
680
679
|
};
|
|
681
|
-
const getUrl = ({
|
|
680
|
+
const getUrl$1 = ({
|
|
682
681
|
baseUrl,
|
|
683
682
|
path,
|
|
684
683
|
query,
|
|
@@ -688,7 +687,7 @@ const getUrl = ({
|
|
|
688
687
|
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
689
688
|
let url = (baseUrl ?? "") + pathUrl;
|
|
690
689
|
if (path) {
|
|
691
|
-
url = defaultPathSerializer({ path, url });
|
|
690
|
+
url = defaultPathSerializer$1({ path, url });
|
|
692
691
|
}
|
|
693
692
|
let search = query ? querySerializer(query) : "";
|
|
694
693
|
if (search.startsWith("?")) {
|
|
@@ -699,7 +698,7 @@ const getUrl = ({
|
|
|
699
698
|
}
|
|
700
699
|
return url;
|
|
701
700
|
};
|
|
702
|
-
function getValidRequestBody(options) {
|
|
701
|
+
function getValidRequestBody$1(options) {
|
|
703
702
|
const hasBody = options.body !== void 0;
|
|
704
703
|
const isSerializedBody = hasBody && options.bodySerializer;
|
|
705
704
|
if (isSerializedBody) {
|
|
@@ -714,7 +713,7 @@ function getValidRequestBody(options) {
|
|
|
714
713
|
}
|
|
715
714
|
return void 0;
|
|
716
715
|
}
|
|
717
|
-
const getAuthToken = async (auth, callback) => {
|
|
716
|
+
const getAuthToken$1 = async (auth, callback) => {
|
|
718
717
|
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
719
718
|
if (!token) {
|
|
720
719
|
return;
|
|
@@ -727,7 +726,7 @@ const getAuthToken = async (auth, callback) => {
|
|
|
727
726
|
}
|
|
728
727
|
return token;
|
|
729
728
|
};
|
|
730
|
-
const createQuerySerializer = ({
|
|
729
|
+
const createQuerySerializer$1 = ({
|
|
731
730
|
parameters = {},
|
|
732
731
|
...args
|
|
733
732
|
} = {}) => {
|
|
@@ -741,7 +740,7 @@ const createQuerySerializer = ({
|
|
|
741
740
|
}
|
|
742
741
|
const options = parameters[name2] || args;
|
|
743
742
|
if (Array.isArray(value)) {
|
|
744
|
-
const serializedArray = serializeArrayParam({
|
|
743
|
+
const serializedArray = serializeArrayParam$1({
|
|
745
744
|
allowReserved: options.allowReserved,
|
|
746
745
|
explode: true,
|
|
747
746
|
name: name2,
|
|
@@ -751,7 +750,7 @@ const createQuerySerializer = ({
|
|
|
751
750
|
});
|
|
752
751
|
if (serializedArray) search.push(serializedArray);
|
|
753
752
|
} else if (typeof value === "object") {
|
|
754
|
-
const serializedObject = serializeObjectParam({
|
|
753
|
+
const serializedObject = serializeObjectParam$1({
|
|
755
754
|
allowReserved: options.allowReserved,
|
|
756
755
|
explode: true,
|
|
757
756
|
name: name2,
|
|
@@ -761,7 +760,7 @@ const createQuerySerializer = ({
|
|
|
761
760
|
});
|
|
762
761
|
if (serializedObject) search.push(serializedObject);
|
|
763
762
|
} else {
|
|
764
|
-
const serializedPrimitive = serializePrimitiveParam({
|
|
763
|
+
const serializedPrimitive = serializePrimitiveParam$1({
|
|
765
764
|
allowReserved: options.allowReserved,
|
|
766
765
|
name: name2,
|
|
767
766
|
value
|
|
@@ -774,7 +773,7 @@ const createQuerySerializer = ({
|
|
|
774
773
|
};
|
|
775
774
|
return querySerializer;
|
|
776
775
|
};
|
|
777
|
-
const getParseAs = (contentType) => {
|
|
776
|
+
const getParseAs$1 = (contentType) => {
|
|
778
777
|
if (!contentType) {
|
|
779
778
|
return "stream";
|
|
780
779
|
}
|
|
@@ -798,7 +797,7 @@ const getParseAs = (contentType) => {
|
|
|
798
797
|
}
|
|
799
798
|
return;
|
|
800
799
|
};
|
|
801
|
-
const checkForExistence = (options, name2) => {
|
|
800
|
+
const checkForExistence$1 = (options, name2) => {
|
|
802
801
|
if (!name2) {
|
|
803
802
|
return false;
|
|
804
803
|
}
|
|
@@ -807,15 +806,15 @@ const checkForExistence = (options, name2) => {
|
|
|
807
806
|
}
|
|
808
807
|
return false;
|
|
809
808
|
};
|
|
810
|
-
const setAuthParams = async ({
|
|
809
|
+
const setAuthParams$1 = async ({
|
|
811
810
|
security,
|
|
812
811
|
...options
|
|
813
812
|
}) => {
|
|
814
813
|
for (const auth of security) {
|
|
815
|
-
if (checkForExistence(options, auth.name)) {
|
|
814
|
+
if (checkForExistence$1(options, auth.name)) {
|
|
816
815
|
continue;
|
|
817
816
|
}
|
|
818
|
-
const token = await getAuthToken(auth, options.auth);
|
|
817
|
+
const token = await getAuthToken$1(auth, options.auth);
|
|
819
818
|
if (!token) {
|
|
820
819
|
continue;
|
|
821
820
|
}
|
|
@@ -837,35 +836,35 @@ const setAuthParams = async ({
|
|
|
837
836
|
}
|
|
838
837
|
}
|
|
839
838
|
};
|
|
840
|
-
const buildUrl = (options) => getUrl({
|
|
839
|
+
const buildUrl$1 = (options) => getUrl$1({
|
|
841
840
|
baseUrl: options.baseUrl,
|
|
842
841
|
path: options.path,
|
|
843
842
|
query: options.query,
|
|
844
|
-
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
|
|
843
|
+
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer$1(options.querySerializer),
|
|
845
844
|
url: options.url
|
|
846
845
|
});
|
|
847
|
-
const mergeConfigs = (a, b) => {
|
|
846
|
+
const mergeConfigs$1 = (a, b) => {
|
|
848
847
|
const config = { ...a, ...b };
|
|
849
848
|
if (config.baseUrl?.endsWith("/")) {
|
|
850
849
|
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
|
851
850
|
}
|
|
852
|
-
config.headers = mergeHeaders(a.headers, b.headers);
|
|
851
|
+
config.headers = mergeHeaders$1(a.headers, b.headers);
|
|
853
852
|
return config;
|
|
854
853
|
};
|
|
855
|
-
const headersEntries = (headers) => {
|
|
854
|
+
const headersEntries$1 = (headers) => {
|
|
856
855
|
const entries = [];
|
|
857
856
|
headers.forEach((value, key) => {
|
|
858
857
|
entries.push([key, value]);
|
|
859
858
|
});
|
|
860
859
|
return entries;
|
|
861
860
|
};
|
|
862
|
-
const mergeHeaders = (...headers) => {
|
|
861
|
+
const mergeHeaders$1 = (...headers) => {
|
|
863
862
|
const mergedHeaders = new Headers();
|
|
864
863
|
for (const header of headers) {
|
|
865
864
|
if (!header) {
|
|
866
865
|
continue;
|
|
867
866
|
}
|
|
868
|
-
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
|
867
|
+
const iterator = header instanceof Headers ? headersEntries$1(header) : Object.entries(header);
|
|
869
868
|
for (const [key, value] of iterator) {
|
|
870
869
|
if (value === null) {
|
|
871
870
|
mergedHeaders.delete(key);
|
|
@@ -883,7 +882,7 @@ const mergeHeaders = (...headers) => {
|
|
|
883
882
|
}
|
|
884
883
|
return mergedHeaders;
|
|
885
884
|
};
|
|
886
|
-
class Interceptors {
|
|
885
|
+
let Interceptors$1 = class Interceptors {
|
|
887
886
|
fns = [];
|
|
888
887
|
clear() {
|
|
889
888
|
this.fns = [];
|
|
@@ -916,13 +915,13 @@ class Interceptors {
|
|
|
916
915
|
this.fns.push(fn);
|
|
917
916
|
return this.fns.length - 1;
|
|
918
917
|
}
|
|
919
|
-
}
|
|
920
|
-
const createInterceptors = () => ({
|
|
921
|
-
error: new Interceptors(),
|
|
922
|
-
request: new Interceptors(),
|
|
923
|
-
response: new Interceptors()
|
|
918
|
+
};
|
|
919
|
+
const createInterceptors$1 = () => ({
|
|
920
|
+
error: new Interceptors$1(),
|
|
921
|
+
request: new Interceptors$1(),
|
|
922
|
+
response: new Interceptors$1()
|
|
924
923
|
});
|
|
925
|
-
const defaultQuerySerializer = createQuerySerializer({
|
|
924
|
+
const defaultQuerySerializer$1 = createQuerySerializer$1({
|
|
926
925
|
allowReserved: false,
|
|
927
926
|
array: {
|
|
928
927
|
explode: true,
|
|
@@ -933,34 +932,34 @@ const defaultQuerySerializer = createQuerySerializer({
|
|
|
933
932
|
style: "deepObject"
|
|
934
933
|
}
|
|
935
934
|
});
|
|
936
|
-
const defaultHeaders = {
|
|
935
|
+
const defaultHeaders$1 = {
|
|
937
936
|
"Content-Type": "application/json"
|
|
938
937
|
};
|
|
939
|
-
const createConfig = (override = {}) => ({
|
|
940
|
-
...jsonBodySerializer,
|
|
941
|
-
headers: defaultHeaders,
|
|
938
|
+
const createConfig$1 = (override = {}) => ({
|
|
939
|
+
...jsonBodySerializer$1,
|
|
940
|
+
headers: defaultHeaders$1,
|
|
942
941
|
parseAs: "auto",
|
|
943
|
-
querySerializer: defaultQuerySerializer,
|
|
942
|
+
querySerializer: defaultQuerySerializer$1,
|
|
944
943
|
...override
|
|
945
944
|
});
|
|
946
|
-
const createClient = (config = {}) => {
|
|
947
|
-
let _config = mergeConfigs(createConfig(), config);
|
|
945
|
+
const createClient$1 = (config = {}) => {
|
|
946
|
+
let _config = mergeConfigs$1(createConfig$1(), config);
|
|
948
947
|
const getConfig = () => ({ ..._config });
|
|
949
948
|
const setConfig = (config2) => {
|
|
950
|
-
_config = mergeConfigs(_config, config2);
|
|
949
|
+
_config = mergeConfigs$1(_config, config2);
|
|
951
950
|
return getConfig();
|
|
952
951
|
};
|
|
953
|
-
const interceptors = createInterceptors();
|
|
952
|
+
const interceptors = createInterceptors$1();
|
|
954
953
|
const beforeRequest = async (options) => {
|
|
955
954
|
const opts = {
|
|
956
955
|
..._config,
|
|
957
956
|
...options,
|
|
958
957
|
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
959
|
-
headers: mergeHeaders(_config.headers, options.headers),
|
|
958
|
+
headers: mergeHeaders$1(_config.headers, options.headers),
|
|
960
959
|
serializedBody: void 0
|
|
961
960
|
};
|
|
962
961
|
if (opts.security) {
|
|
963
|
-
await setAuthParams({
|
|
962
|
+
await setAuthParams$1({
|
|
964
963
|
...opts,
|
|
965
964
|
security: opts.security
|
|
966
965
|
});
|
|
@@ -974,7 +973,7 @@ const createClient = (config = {}) => {
|
|
|
974
973
|
if (opts.body === void 0 || opts.serializedBody === "") {
|
|
975
974
|
opts.headers.delete("Content-Type");
|
|
976
975
|
}
|
|
977
|
-
const url = buildUrl(opts);
|
|
976
|
+
const url = buildUrl$1(opts);
|
|
978
977
|
return { opts, url };
|
|
979
978
|
};
|
|
980
979
|
const request = async (options) => {
|
|
@@ -982,7 +981,7 @@ const createClient = (config = {}) => {
|
|
|
982
981
|
const requestInit = {
|
|
983
982
|
redirect: "follow",
|
|
984
983
|
...opts,
|
|
985
|
-
body: getValidRequestBody(opts)
|
|
984
|
+
body: getValidRequestBody$1(opts)
|
|
986
985
|
};
|
|
987
986
|
let request2 = new Request(url, requestInit);
|
|
988
987
|
for (const fn of interceptors.request.fns) {
|
|
@@ -1026,7 +1025,7 @@ const createClient = (config = {}) => {
|
|
|
1026
1025
|
response
|
|
1027
1026
|
};
|
|
1028
1027
|
if (response.ok) {
|
|
1029
|
-
const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
1028
|
+
const parseAs = (opts.parseAs === "auto" ? getParseAs$1(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
1030
1029
|
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
1031
1030
|
let emptyData;
|
|
1032
1031
|
switch (parseAs) {
|
|
@@ -1104,7 +1103,7 @@ const createClient = (config = {}) => {
|
|
|
1104
1103
|
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
1105
1104
|
const makeSseFn = (method) => async (options) => {
|
|
1106
1105
|
const { opts, url } = await beforeRequest(options);
|
|
1107
|
-
return createSseClient({
|
|
1106
|
+
return createSseClient$1({
|
|
1108
1107
|
...opts,
|
|
1109
1108
|
body: opts.body,
|
|
1110
1109
|
headers: opts.headers,
|
|
@@ -1122,7 +1121,7 @@ const createClient = (config = {}) => {
|
|
|
1122
1121
|
});
|
|
1123
1122
|
};
|
|
1124
1123
|
return {
|
|
1125
|
-
buildUrl,
|
|
1124
|
+
buildUrl: buildUrl$1,
|
|
1126
1125
|
connect: makeMethodFn("CONNECT"),
|
|
1127
1126
|
delete: makeMethodFn("DELETE"),
|
|
1128
1127
|
get: makeMethodFn("GET"),
|
|
@@ -1149,8 +1148,8 @@ const createClient = (config = {}) => {
|
|
|
1149
1148
|
trace: makeMethodFn("TRACE")
|
|
1150
1149
|
};
|
|
1151
1150
|
};
|
|
1152
|
-
const client = createClient(
|
|
1153
|
-
createConfig({ baseUrl: "https://api.themolt.net" })
|
|
1151
|
+
const client = createClient$1(
|
|
1152
|
+
createConfig$1({ baseUrl: "https://api.themolt.net" })
|
|
1154
1153
|
);
|
|
1155
1154
|
const startLegreffierOnboarding = (options) => (options.client ?? client).post({
|
|
1156
1155
|
url: "/public/legreffier/start",
|
|
@@ -1161,85 +1160,6 @@ const startLegreffierOnboarding = (options) => (options.client ?? client).post({
|
|
|
1161
1160
|
}
|
|
1162
1161
|
});
|
|
1163
1162
|
const getLegreffierOnboardingStatus = (options) => (options.client ?? client).get({ url: "/public/legreffier/status/{workflowId}", ...options });
|
|
1164
|
-
class MoltNetError extends Error {
|
|
1165
|
-
code;
|
|
1166
|
-
statusCode;
|
|
1167
|
-
detail;
|
|
1168
|
-
constructor(message, options) {
|
|
1169
|
-
super(message);
|
|
1170
|
-
this.name = "MoltNetError";
|
|
1171
|
-
this.code = options.code;
|
|
1172
|
-
this.statusCode = options.statusCode;
|
|
1173
|
-
this.detail = options.detail;
|
|
1174
|
-
}
|
|
1175
|
-
}
|
|
1176
|
-
function problemToError(problem, statusCode) {
|
|
1177
|
-
return new MoltNetError(problem.title ?? "Request failed", {
|
|
1178
|
-
code: problem.type ?? problem.code ?? "UNKNOWN",
|
|
1179
|
-
statusCode,
|
|
1180
|
-
detail: problem.detail
|
|
1181
|
-
});
|
|
1182
|
-
}
|
|
1183
|
-
async function writeMcpConfig(mcpConfig, dir2) {
|
|
1184
|
-
const targetDir = dir2 ?? process.cwd();
|
|
1185
|
-
const filePath = join(targetDir, ".mcp.json");
|
|
1186
|
-
let existing = {};
|
|
1187
|
-
try {
|
|
1188
|
-
const content = await readFile(filePath, "utf-8");
|
|
1189
|
-
existing = JSON.parse(content);
|
|
1190
|
-
} catch {
|
|
1191
|
-
}
|
|
1192
|
-
const merged = {
|
|
1193
|
-
...existing,
|
|
1194
|
-
mcpServers: {
|
|
1195
|
-
...existing.mcpServers ?? {},
|
|
1196
|
-
...mcpConfig.mcpServers
|
|
1197
|
-
}
|
|
1198
|
-
};
|
|
1199
|
-
await writeFile(filePath, JSON.stringify(merged, null, 2) + "\n");
|
|
1200
|
-
return filePath;
|
|
1201
|
-
}
|
|
1202
|
-
function getConfigDir() {
|
|
1203
|
-
return join(homedir(), ".config", "moltnet");
|
|
1204
|
-
}
|
|
1205
|
-
function getConfigPath(configDir) {
|
|
1206
|
-
return join(configDir ?? getConfigDir(), "moltnet.json");
|
|
1207
|
-
}
|
|
1208
|
-
async function readConfig(configDir) {
|
|
1209
|
-
const dir2 = configDir ?? getConfigDir();
|
|
1210
|
-
try {
|
|
1211
|
-
const content = await readFile(join(dir2, "moltnet.json"), "utf-8");
|
|
1212
|
-
return JSON.parse(content);
|
|
1213
|
-
} catch {
|
|
1214
|
-
}
|
|
1215
|
-
try {
|
|
1216
|
-
const content = await readFile(join(dir2, "credentials.json"), "utf-8");
|
|
1217
|
-
console.warn("Warning: credentials.json is deprecated. New writes use moltnet.json. Support will be removed in 3 minor versions.");
|
|
1218
|
-
return JSON.parse(content);
|
|
1219
|
-
} catch {
|
|
1220
|
-
return null;
|
|
1221
|
-
}
|
|
1222
|
-
}
|
|
1223
|
-
async function writeConfig(config, configDir) {
|
|
1224
|
-
const dir2 = configDir ?? getConfigDir();
|
|
1225
|
-
await mkdir(dir2, { recursive: true });
|
|
1226
|
-
const filePath = join(dir2, "moltnet.json");
|
|
1227
|
-
await writeFile(filePath, JSON.stringify(config, null, 2) + "\n", {
|
|
1228
|
-
mode: 384
|
|
1229
|
-
});
|
|
1230
|
-
await chmod(filePath, 384);
|
|
1231
|
-
return filePath;
|
|
1232
|
-
}
|
|
1233
|
-
async function updateConfigSection(section, data, configDir) {
|
|
1234
|
-
const config = await readConfig(configDir);
|
|
1235
|
-
if (!config) {
|
|
1236
|
-
throw new Error("No config found — run `moltnet register` first");
|
|
1237
|
-
}
|
|
1238
|
-
const existing = config[section] ?? {};
|
|
1239
|
-
const updated = { ...existing, ...data };
|
|
1240
|
-
Object.assign(config, { [section]: updated });
|
|
1241
|
-
await writeConfig(config, configDir);
|
|
1242
|
-
}
|
|
1243
1163
|
/*! noble-ed25519 - MIT License (c) 2019 Paul Miller (paulmillr.com) */
|
|
1244
1164
|
const ed25519_CURVE = {
|
|
1245
1165
|
p: 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffedn,
|
|
@@ -1716,175 +1636,901 @@ const wNAF = (n) => {
|
|
|
1716
1636
|
}
|
|
1717
1637
|
return { p, f };
|
|
1718
1638
|
};
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1639
|
+
var __defProp = Object.defineProperty;
|
|
1640
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
1641
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
1642
|
+
const jsonBodySerializer = {
|
|
1643
|
+
bodySerializer: (body) => JSON.stringify(
|
|
1644
|
+
body,
|
|
1645
|
+
(_key, value) => typeof value === "bigint" ? value.toString() : value
|
|
1646
|
+
)
|
|
1723
1647
|
};
|
|
1724
|
-
const
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1648
|
+
const createSseClient = ({
|
|
1649
|
+
onRequest,
|
|
1650
|
+
onSseError,
|
|
1651
|
+
onSseEvent,
|
|
1652
|
+
responseTransformer,
|
|
1653
|
+
responseValidator,
|
|
1654
|
+
sseDefaultRetryDelay,
|
|
1655
|
+
sseMaxRetryAttempts,
|
|
1656
|
+
sseMaxRetryDelay,
|
|
1657
|
+
sseSleepFn,
|
|
1658
|
+
url,
|
|
1659
|
+
...options
|
|
1660
|
+
}) => {
|
|
1661
|
+
let lastEventId;
|
|
1662
|
+
const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
|
|
1663
|
+
const createStream = async function* () {
|
|
1664
|
+
let retryDelay = sseDefaultRetryDelay ?? 3e3;
|
|
1665
|
+
let attempt = 0;
|
|
1666
|
+
const signal = options.signal ?? new AbortController().signal;
|
|
1667
|
+
while (true) {
|
|
1668
|
+
if (signal.aborted) break;
|
|
1669
|
+
attempt++;
|
|
1670
|
+
const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
|
|
1671
|
+
if (lastEventId !== void 0) {
|
|
1672
|
+
headers.set("Last-Event-ID", lastEventId);
|
|
1673
|
+
}
|
|
1674
|
+
try {
|
|
1675
|
+
const requestInit = {
|
|
1676
|
+
redirect: "follow",
|
|
1677
|
+
...options,
|
|
1678
|
+
body: options.serializedBody,
|
|
1679
|
+
headers,
|
|
1680
|
+
signal
|
|
1681
|
+
};
|
|
1682
|
+
let request = new Request(url, requestInit);
|
|
1683
|
+
if (onRequest) {
|
|
1684
|
+
request = await onRequest(url, requestInit);
|
|
1685
|
+
}
|
|
1686
|
+
const _fetch = options.fetch ?? globalThis.fetch;
|
|
1687
|
+
const response = await _fetch(request);
|
|
1688
|
+
if (!response.ok)
|
|
1689
|
+
throw new Error(
|
|
1690
|
+
`SSE failed: ${response.status} ${response.statusText}`
|
|
1691
|
+
);
|
|
1692
|
+
if (!response.body) throw new Error("No body in SSE response");
|
|
1693
|
+
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
|
1694
|
+
let buffer = "";
|
|
1695
|
+
const abortHandler = () => {
|
|
1696
|
+
try {
|
|
1697
|
+
reader.cancel();
|
|
1698
|
+
} catch {
|
|
1699
|
+
}
|
|
1700
|
+
};
|
|
1701
|
+
signal.addEventListener("abort", abortHandler);
|
|
1702
|
+
try {
|
|
1703
|
+
while (true) {
|
|
1704
|
+
const { done, value } = await reader.read();
|
|
1705
|
+
if (done) break;
|
|
1706
|
+
buffer += value;
|
|
1707
|
+
buffer = buffer.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1708
|
+
const chunks = buffer.split("\n\n");
|
|
1709
|
+
buffer = chunks.pop() ?? "";
|
|
1710
|
+
for (const chunk of chunks) {
|
|
1711
|
+
const lines = chunk.split("\n");
|
|
1712
|
+
const dataLines = [];
|
|
1713
|
+
let eventName;
|
|
1714
|
+
for (const line of lines) {
|
|
1715
|
+
if (line.startsWith("data:")) {
|
|
1716
|
+
dataLines.push(line.replace(/^data:\s*/, ""));
|
|
1717
|
+
} else if (line.startsWith("event:")) {
|
|
1718
|
+
eventName = line.replace(/^event:\s*/, "");
|
|
1719
|
+
} else if (line.startsWith("id:")) {
|
|
1720
|
+
lastEventId = line.replace(/^id:\s*/, "");
|
|
1721
|
+
} else if (line.startsWith("retry:")) {
|
|
1722
|
+
const parsed = Number.parseInt(
|
|
1723
|
+
line.replace(/^retry:\s*/, ""),
|
|
1724
|
+
10
|
|
1725
|
+
);
|
|
1726
|
+
if (!Number.isNaN(parsed)) {
|
|
1727
|
+
retryDelay = parsed;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
}
|
|
1731
|
+
let data;
|
|
1732
|
+
let parsedJson = false;
|
|
1733
|
+
if (dataLines.length) {
|
|
1734
|
+
const rawData = dataLines.join("\n");
|
|
1735
|
+
try {
|
|
1736
|
+
data = JSON.parse(rawData);
|
|
1737
|
+
parsedJson = true;
|
|
1738
|
+
} catch {
|
|
1739
|
+
data = rawData;
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
if (parsedJson) {
|
|
1743
|
+
if (responseValidator) {
|
|
1744
|
+
await responseValidator(data);
|
|
1745
|
+
}
|
|
1746
|
+
if (responseTransformer) {
|
|
1747
|
+
data = await responseTransformer(data);
|
|
1748
|
+
}
|
|
1749
|
+
}
|
|
1750
|
+
onSseEvent == null ? void 0 : onSseEvent({
|
|
1751
|
+
data,
|
|
1752
|
+
event: eventName,
|
|
1753
|
+
id: lastEventId,
|
|
1754
|
+
retry: retryDelay
|
|
1755
|
+
});
|
|
1756
|
+
if (dataLines.length) {
|
|
1757
|
+
yield data;
|
|
1758
|
+
}
|
|
1759
|
+
}
|
|
1760
|
+
}
|
|
1761
|
+
} finally {
|
|
1762
|
+
signal.removeEventListener("abort", abortHandler);
|
|
1763
|
+
reader.releaseLock();
|
|
1764
|
+
}
|
|
1765
|
+
break;
|
|
1766
|
+
} catch (error) {
|
|
1767
|
+
onSseError == null ? void 0 : onSseError(error);
|
|
1768
|
+
if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
|
|
1769
|
+
break;
|
|
1770
|
+
}
|
|
1771
|
+
const backoff = Math.min(
|
|
1772
|
+
retryDelay * 2 ** (attempt - 1),
|
|
1773
|
+
sseMaxRetryDelay ?? 3e4
|
|
1774
|
+
);
|
|
1775
|
+
await sleep(backoff);
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
};
|
|
1779
|
+
const stream = createStream();
|
|
1780
|
+
return { stream };
|
|
1781
|
+
};
|
|
1782
|
+
const separatorArrayExplode = (style) => {
|
|
1783
|
+
switch (style) {
|
|
1784
|
+
case "label":
|
|
1785
|
+
return ".";
|
|
1786
|
+
case "matrix":
|
|
1787
|
+
return ";";
|
|
1788
|
+
case "simple":
|
|
1789
|
+
return ",";
|
|
1790
|
+
default:
|
|
1791
|
+
return "&";
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
const separatorArrayNoExplode = (style) => {
|
|
1795
|
+
switch (style) {
|
|
1796
|
+
case "form":
|
|
1797
|
+
return ",";
|
|
1798
|
+
case "pipeDelimited":
|
|
1799
|
+
return "|";
|
|
1800
|
+
case "spaceDelimited":
|
|
1801
|
+
return "%20";
|
|
1802
|
+
default:
|
|
1803
|
+
return ",";
|
|
1804
|
+
}
|
|
1805
|
+
};
|
|
1806
|
+
const separatorObjectExplode = (style) => {
|
|
1807
|
+
switch (style) {
|
|
1808
|
+
case "label":
|
|
1809
|
+
return ".";
|
|
1810
|
+
case "matrix":
|
|
1811
|
+
return ";";
|
|
1812
|
+
case "simple":
|
|
1813
|
+
return ",";
|
|
1814
|
+
default:
|
|
1815
|
+
return "&";
|
|
1816
|
+
}
|
|
1817
|
+
};
|
|
1818
|
+
const serializeArrayParam = ({
|
|
1819
|
+
allowReserved,
|
|
1820
|
+
explode,
|
|
1821
|
+
name: name2,
|
|
1822
|
+
style,
|
|
1823
|
+
value
|
|
1824
|
+
}) => {
|
|
1825
|
+
if (!explode) {
|
|
1826
|
+
const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
|
|
1827
|
+
switch (style) {
|
|
1828
|
+
case "label":
|
|
1829
|
+
return `.${joinedValues2}`;
|
|
1830
|
+
case "matrix":
|
|
1831
|
+
return `;${name2}=${joinedValues2}`;
|
|
1832
|
+
case "simple":
|
|
1833
|
+
return joinedValues2;
|
|
1834
|
+
default:
|
|
1835
|
+
return `${name2}=${joinedValues2}`;
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
const separator = separatorArrayExplode(style);
|
|
1839
|
+
const joinedValues = value.map((v) => {
|
|
1840
|
+
if (style === "label" || style === "simple") {
|
|
1841
|
+
return allowReserved ? v : encodeURIComponent(v);
|
|
1842
|
+
}
|
|
1843
|
+
return serializePrimitiveParam({
|
|
1844
|
+
allowReserved,
|
|
1845
|
+
name: name2,
|
|
1846
|
+
value: v
|
|
1847
|
+
});
|
|
1848
|
+
}).join(separator);
|
|
1849
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
1850
|
+
};
|
|
1851
|
+
const serializePrimitiveParam = ({
|
|
1852
|
+
allowReserved,
|
|
1853
|
+
name: name2,
|
|
1854
|
+
value
|
|
1855
|
+
}) => {
|
|
1856
|
+
if (value === void 0 || value === null) {
|
|
1857
|
+
return "";
|
|
1858
|
+
}
|
|
1859
|
+
if (typeof value === "object") {
|
|
1860
|
+
throw new Error(
|
|
1861
|
+
"Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these."
|
|
1850
1862
|
);
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
const
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1863
|
+
}
|
|
1864
|
+
return `${name2}=${allowReserved ? value : encodeURIComponent(value)}`;
|
|
1865
|
+
};
|
|
1866
|
+
const serializeObjectParam = ({
|
|
1867
|
+
allowReserved,
|
|
1868
|
+
explode,
|
|
1869
|
+
name: name2,
|
|
1870
|
+
style,
|
|
1871
|
+
value,
|
|
1872
|
+
valueOnly
|
|
1873
|
+
}) => {
|
|
1874
|
+
if (value instanceof Date) {
|
|
1875
|
+
return valueOnly ? value.toISOString() : `${name2}=${value.toISOString()}`;
|
|
1876
|
+
}
|
|
1877
|
+
if (style !== "deepObject" && !explode) {
|
|
1878
|
+
let values2 = [];
|
|
1879
|
+
Object.entries(value).forEach(([key, v]) => {
|
|
1880
|
+
values2 = [
|
|
1881
|
+
...values2,
|
|
1882
|
+
key,
|
|
1883
|
+
allowReserved ? v : encodeURIComponent(v)
|
|
1884
|
+
];
|
|
1885
|
+
});
|
|
1886
|
+
const joinedValues2 = values2.join(",");
|
|
1887
|
+
switch (style) {
|
|
1888
|
+
case "form":
|
|
1889
|
+
return `${name2}=${joinedValues2}`;
|
|
1890
|
+
case "label":
|
|
1891
|
+
return `.${joinedValues2}`;
|
|
1892
|
+
case "matrix":
|
|
1893
|
+
return `;${name2}=${joinedValues2}`;
|
|
1894
|
+
default:
|
|
1895
|
+
return joinedValues2;
|
|
1896
|
+
}
|
|
1897
|
+
}
|
|
1898
|
+
const separator = separatorObjectExplode(style);
|
|
1899
|
+
const joinedValues = Object.entries(value).map(
|
|
1900
|
+
([key, v]) => serializePrimitiveParam({
|
|
1901
|
+
allowReserved,
|
|
1902
|
+
name: style === "deepObject" ? `${name2}[${key}]` : key,
|
|
1903
|
+
value: v
|
|
1904
|
+
})
|
|
1905
|
+
).join(separator);
|
|
1906
|
+
return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
|
|
1907
|
+
};
|
|
1908
|
+
const PATH_PARAM_RE = /\{[^{}]+\}/g;
|
|
1909
|
+
const defaultPathSerializer = ({ path, url: _url }) => {
|
|
1910
|
+
let url = _url;
|
|
1911
|
+
const matches = _url.match(PATH_PARAM_RE);
|
|
1912
|
+
if (matches) {
|
|
1913
|
+
for (const match of matches) {
|
|
1914
|
+
let explode = false;
|
|
1915
|
+
let name2 = match.substring(1, match.length - 1);
|
|
1916
|
+
let style = "simple";
|
|
1917
|
+
if (name2.endsWith("*")) {
|
|
1918
|
+
explode = true;
|
|
1919
|
+
name2 = name2.substring(0, name2.length - 1);
|
|
1920
|
+
}
|
|
1921
|
+
if (name2.startsWith(".")) {
|
|
1922
|
+
name2 = name2.substring(1);
|
|
1923
|
+
style = "label";
|
|
1924
|
+
} else if (name2.startsWith(";")) {
|
|
1925
|
+
name2 = name2.substring(1);
|
|
1926
|
+
style = "matrix";
|
|
1927
|
+
}
|
|
1928
|
+
const value = path[name2];
|
|
1929
|
+
if (value === void 0 || value === null) {
|
|
1930
|
+
continue;
|
|
1931
|
+
}
|
|
1932
|
+
if (Array.isArray(value)) {
|
|
1933
|
+
url = url.replace(
|
|
1934
|
+
match,
|
|
1935
|
+
serializeArrayParam({ explode, name: name2, style, value })
|
|
1936
|
+
);
|
|
1937
|
+
continue;
|
|
1938
|
+
}
|
|
1939
|
+
if (typeof value === "object") {
|
|
1940
|
+
url = url.replace(
|
|
1941
|
+
match,
|
|
1942
|
+
serializeObjectParam({
|
|
1943
|
+
explode,
|
|
1944
|
+
name: name2,
|
|
1945
|
+
style,
|
|
1946
|
+
value,
|
|
1947
|
+
valueOnly: true
|
|
1948
|
+
})
|
|
1949
|
+
);
|
|
1950
|
+
continue;
|
|
1951
|
+
}
|
|
1952
|
+
if (style === "matrix") {
|
|
1953
|
+
url = url.replace(
|
|
1954
|
+
match,
|
|
1955
|
+
`;${serializePrimitiveParam({
|
|
1956
|
+
name: name2,
|
|
1957
|
+
value
|
|
1958
|
+
})}`
|
|
1959
|
+
);
|
|
1960
|
+
continue;
|
|
1961
|
+
}
|
|
1962
|
+
const replaceValue = encodeURIComponent(
|
|
1963
|
+
style === "label" ? `.${value}` : value
|
|
1964
|
+
);
|
|
1965
|
+
url = url.replace(match, replaceValue);
|
|
1966
|
+
}
|
|
1967
|
+
}
|
|
1968
|
+
return url;
|
|
1969
|
+
};
|
|
1970
|
+
const getUrl = ({
|
|
1971
|
+
baseUrl,
|
|
1972
|
+
path,
|
|
1973
|
+
query,
|
|
1974
|
+
querySerializer,
|
|
1975
|
+
url: _url
|
|
1976
|
+
}) => {
|
|
1977
|
+
const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
|
|
1978
|
+
let url = (baseUrl ?? "") + pathUrl;
|
|
1979
|
+
if (path) {
|
|
1980
|
+
url = defaultPathSerializer({ path, url });
|
|
1981
|
+
}
|
|
1982
|
+
let search = query ? querySerializer(query) : "";
|
|
1983
|
+
if (search.startsWith("?")) {
|
|
1984
|
+
search = search.substring(1);
|
|
1985
|
+
}
|
|
1986
|
+
if (search) {
|
|
1987
|
+
url += `?${search}`;
|
|
1988
|
+
}
|
|
1989
|
+
return url;
|
|
1990
|
+
};
|
|
1991
|
+
function getValidRequestBody(options) {
|
|
1992
|
+
const hasBody = options.body !== void 0;
|
|
1993
|
+
const isSerializedBody = hasBody && options.bodySerializer;
|
|
1994
|
+
if (isSerializedBody) {
|
|
1995
|
+
if ("serializedBody" in options) {
|
|
1996
|
+
const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
|
|
1997
|
+
return hasSerializedBody ? options.serializedBody : null;
|
|
1998
|
+
}
|
|
1999
|
+
return options.body !== "" ? options.body : null;
|
|
2000
|
+
}
|
|
2001
|
+
if (hasBody) {
|
|
2002
|
+
return options.body;
|
|
2003
|
+
}
|
|
2004
|
+
return void 0;
|
|
2005
|
+
}
|
|
2006
|
+
const getAuthToken = async (auth, callback) => {
|
|
2007
|
+
const token = typeof callback === "function" ? await callback(auth) : callback;
|
|
2008
|
+
if (!token) {
|
|
2009
|
+
return;
|
|
2010
|
+
}
|
|
2011
|
+
if (auth.scheme === "bearer") {
|
|
2012
|
+
return `Bearer ${token}`;
|
|
2013
|
+
}
|
|
2014
|
+
if (auth.scheme === "basic") {
|
|
2015
|
+
return `Basic ${btoa(token)}`;
|
|
2016
|
+
}
|
|
2017
|
+
return token;
|
|
2018
|
+
};
|
|
2019
|
+
const createQuerySerializer = ({
|
|
2020
|
+
parameters = {},
|
|
2021
|
+
...args
|
|
2022
|
+
} = {}) => {
|
|
2023
|
+
const querySerializer = (queryParams) => {
|
|
2024
|
+
const search = [];
|
|
2025
|
+
if (queryParams && typeof queryParams === "object") {
|
|
2026
|
+
for (const name2 in queryParams) {
|
|
2027
|
+
const value = queryParams[name2];
|
|
2028
|
+
if (value === void 0 || value === null) {
|
|
2029
|
+
continue;
|
|
2030
|
+
}
|
|
2031
|
+
const options = parameters[name2] || args;
|
|
2032
|
+
if (Array.isArray(value)) {
|
|
2033
|
+
const serializedArray = serializeArrayParam({
|
|
2034
|
+
allowReserved: options.allowReserved,
|
|
2035
|
+
explode: true,
|
|
2036
|
+
name: name2,
|
|
2037
|
+
style: "form",
|
|
2038
|
+
value,
|
|
2039
|
+
...options.array
|
|
2040
|
+
});
|
|
2041
|
+
if (serializedArray) search.push(serializedArray);
|
|
2042
|
+
} else if (typeof value === "object") {
|
|
2043
|
+
const serializedObject = serializeObjectParam({
|
|
2044
|
+
allowReserved: options.allowReserved,
|
|
2045
|
+
explode: true,
|
|
2046
|
+
name: name2,
|
|
2047
|
+
style: "deepObject",
|
|
2048
|
+
value,
|
|
2049
|
+
...options.object
|
|
2050
|
+
});
|
|
2051
|
+
if (serializedObject) search.push(serializedObject);
|
|
2052
|
+
} else {
|
|
2053
|
+
const serializedPrimitive = serializePrimitiveParam({
|
|
2054
|
+
allowReserved: options.allowReserved,
|
|
2055
|
+
name: name2,
|
|
2056
|
+
value
|
|
2057
|
+
});
|
|
2058
|
+
if (serializedPrimitive) search.push(serializedPrimitive);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
return search.join("&");
|
|
2063
|
+
};
|
|
2064
|
+
return querySerializer;
|
|
2065
|
+
};
|
|
2066
|
+
const getParseAs = (contentType) => {
|
|
2067
|
+
var _a2;
|
|
2068
|
+
if (!contentType) {
|
|
2069
|
+
return "stream";
|
|
2070
|
+
}
|
|
2071
|
+
const cleanContent = (_a2 = contentType.split(";")[0]) == null ? void 0 : _a2.trim();
|
|
2072
|
+
if (!cleanContent) {
|
|
2073
|
+
return;
|
|
2074
|
+
}
|
|
2075
|
+
if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
|
|
2076
|
+
return "json";
|
|
2077
|
+
}
|
|
2078
|
+
if (cleanContent === "multipart/form-data") {
|
|
2079
|
+
return "formData";
|
|
2080
|
+
}
|
|
2081
|
+
if (["application/", "audio/", "image/", "video/"].some(
|
|
2082
|
+
(type) => cleanContent.startsWith(type)
|
|
2083
|
+
)) {
|
|
2084
|
+
return "blob";
|
|
2085
|
+
}
|
|
2086
|
+
if (cleanContent.startsWith("text/")) {
|
|
2087
|
+
return "text";
|
|
2088
|
+
}
|
|
2089
|
+
return;
|
|
2090
|
+
};
|
|
2091
|
+
const checkForExistence = (options, name2) => {
|
|
2092
|
+
var _a2, _b;
|
|
2093
|
+
if (!name2) {
|
|
2094
|
+
return false;
|
|
2095
|
+
}
|
|
2096
|
+
if (options.headers.has(name2) || ((_a2 = options.query) == null ? void 0 : _a2[name2]) || ((_b = options.headers.get("Cookie")) == null ? void 0 : _b.includes(`${name2}=`))) {
|
|
2097
|
+
return true;
|
|
2098
|
+
}
|
|
2099
|
+
return false;
|
|
2100
|
+
};
|
|
2101
|
+
const setAuthParams = async ({
|
|
2102
|
+
security,
|
|
2103
|
+
...options
|
|
2104
|
+
}) => {
|
|
2105
|
+
for (const auth of security) {
|
|
2106
|
+
if (checkForExistence(options, auth.name)) {
|
|
2107
|
+
continue;
|
|
2108
|
+
}
|
|
2109
|
+
const token = await getAuthToken(auth, options.auth);
|
|
2110
|
+
if (!token) {
|
|
2111
|
+
continue;
|
|
2112
|
+
}
|
|
2113
|
+
const name2 = auth.name ?? "Authorization";
|
|
2114
|
+
switch (auth.in) {
|
|
2115
|
+
case "query":
|
|
2116
|
+
if (!options.query) {
|
|
2117
|
+
options.query = {};
|
|
2118
|
+
}
|
|
2119
|
+
options.query[name2] = token;
|
|
2120
|
+
break;
|
|
2121
|
+
case "cookie":
|
|
2122
|
+
options.headers.append("Cookie", `${name2}=${token}`);
|
|
2123
|
+
break;
|
|
2124
|
+
case "header":
|
|
2125
|
+
default:
|
|
2126
|
+
options.headers.set(name2, token);
|
|
2127
|
+
break;
|
|
2128
|
+
}
|
|
2129
|
+
}
|
|
2130
|
+
};
|
|
2131
|
+
const buildUrl = (options) => getUrl({
|
|
2132
|
+
baseUrl: options.baseUrl,
|
|
2133
|
+
path: options.path,
|
|
2134
|
+
query: options.query,
|
|
2135
|
+
querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
|
|
2136
|
+
url: options.url
|
|
2137
|
+
});
|
|
2138
|
+
const mergeConfigs = (a, b) => {
|
|
2139
|
+
var _a2;
|
|
2140
|
+
const config = { ...a, ...b };
|
|
2141
|
+
if ((_a2 = config.baseUrl) == null ? void 0 : _a2.endsWith("/")) {
|
|
2142
|
+
config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
|
|
2143
|
+
}
|
|
2144
|
+
config.headers = mergeHeaders(a.headers, b.headers);
|
|
2145
|
+
return config;
|
|
2146
|
+
};
|
|
2147
|
+
const headersEntries = (headers) => {
|
|
2148
|
+
const entries = [];
|
|
2149
|
+
headers.forEach((value, key) => {
|
|
2150
|
+
entries.push([key, value]);
|
|
2151
|
+
});
|
|
2152
|
+
return entries;
|
|
2153
|
+
};
|
|
2154
|
+
const mergeHeaders = (...headers) => {
|
|
2155
|
+
const mergedHeaders = new Headers();
|
|
2156
|
+
for (const header of headers) {
|
|
2157
|
+
if (!header) {
|
|
2158
|
+
continue;
|
|
2159
|
+
}
|
|
2160
|
+
const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
|
|
2161
|
+
for (const [key, value] of iterator) {
|
|
2162
|
+
if (value === null) {
|
|
2163
|
+
mergedHeaders.delete(key);
|
|
2164
|
+
} else if (Array.isArray(value)) {
|
|
2165
|
+
for (const v of value) {
|
|
2166
|
+
mergedHeaders.append(key, v);
|
|
2167
|
+
}
|
|
2168
|
+
} else if (value !== void 0) {
|
|
2169
|
+
mergedHeaders.set(
|
|
2170
|
+
key,
|
|
2171
|
+
typeof value === "object" ? JSON.stringify(value) : value
|
|
2172
|
+
);
|
|
2173
|
+
}
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
return mergedHeaders;
|
|
2177
|
+
};
|
|
2178
|
+
class Interceptors2 {
|
|
2179
|
+
constructor() {
|
|
2180
|
+
__publicField(this, "fns", []);
|
|
2181
|
+
}
|
|
2182
|
+
clear() {
|
|
2183
|
+
this.fns = [];
|
|
2184
|
+
}
|
|
2185
|
+
eject(id) {
|
|
2186
|
+
const index = this.getInterceptorIndex(id);
|
|
2187
|
+
if (this.fns[index]) {
|
|
2188
|
+
this.fns[index] = null;
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
exists(id) {
|
|
2192
|
+
const index = this.getInterceptorIndex(id);
|
|
2193
|
+
return Boolean(this.fns[index]);
|
|
2194
|
+
}
|
|
2195
|
+
getInterceptorIndex(id) {
|
|
2196
|
+
if (typeof id === "number") {
|
|
2197
|
+
return this.fns[id] ? id : -1;
|
|
2198
|
+
}
|
|
2199
|
+
return this.fns.indexOf(id);
|
|
2200
|
+
}
|
|
2201
|
+
update(id, fn) {
|
|
2202
|
+
const index = this.getInterceptorIndex(id);
|
|
2203
|
+
if (this.fns[index]) {
|
|
2204
|
+
this.fns[index] = fn;
|
|
2205
|
+
return id;
|
|
2206
|
+
}
|
|
2207
|
+
return false;
|
|
2208
|
+
}
|
|
2209
|
+
use(fn) {
|
|
2210
|
+
this.fns.push(fn);
|
|
2211
|
+
return this.fns.length - 1;
|
|
2212
|
+
}
|
|
2213
|
+
}
|
|
2214
|
+
const createInterceptors = () => ({
|
|
2215
|
+
error: new Interceptors2(),
|
|
2216
|
+
request: new Interceptors2(),
|
|
2217
|
+
response: new Interceptors2()
|
|
2218
|
+
});
|
|
2219
|
+
const defaultQuerySerializer = createQuerySerializer({
|
|
2220
|
+
allowReserved: false,
|
|
2221
|
+
array: {
|
|
2222
|
+
explode: true,
|
|
2223
|
+
style: "form"
|
|
2224
|
+
},
|
|
2225
|
+
object: {
|
|
2226
|
+
explode: true,
|
|
2227
|
+
style: "deepObject"
|
|
2228
|
+
}
|
|
2229
|
+
});
|
|
2230
|
+
const defaultHeaders = {
|
|
2231
|
+
"Content-Type": "application/json"
|
|
2232
|
+
};
|
|
2233
|
+
const createConfig = (override = {}) => ({
|
|
2234
|
+
...jsonBodySerializer,
|
|
2235
|
+
headers: defaultHeaders,
|
|
2236
|
+
parseAs: "auto",
|
|
2237
|
+
querySerializer: defaultQuerySerializer,
|
|
2238
|
+
...override
|
|
2239
|
+
});
|
|
2240
|
+
const createClient = (config = {}) => {
|
|
2241
|
+
let _config = mergeConfigs(createConfig(), config);
|
|
2242
|
+
const getConfig = () => ({ ..._config });
|
|
2243
|
+
const setConfig = (config2) => {
|
|
2244
|
+
_config = mergeConfigs(_config, config2);
|
|
2245
|
+
return getConfig();
|
|
2246
|
+
};
|
|
2247
|
+
const interceptors = createInterceptors();
|
|
2248
|
+
const beforeRequest = async (options) => {
|
|
2249
|
+
const opts = {
|
|
2250
|
+
..._config,
|
|
2251
|
+
...options,
|
|
2252
|
+
fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
|
|
2253
|
+
headers: mergeHeaders(_config.headers, options.headers),
|
|
2254
|
+
serializedBody: void 0
|
|
2255
|
+
};
|
|
2256
|
+
if (opts.security) {
|
|
2257
|
+
await setAuthParams({
|
|
2258
|
+
...opts,
|
|
2259
|
+
security: opts.security
|
|
2260
|
+
});
|
|
2261
|
+
}
|
|
2262
|
+
if (opts.requestValidator) {
|
|
2263
|
+
await opts.requestValidator(opts);
|
|
2264
|
+
}
|
|
2265
|
+
if (opts.body !== void 0 && opts.bodySerializer) {
|
|
2266
|
+
opts.serializedBody = opts.bodySerializer(opts.body);
|
|
2267
|
+
}
|
|
2268
|
+
if (opts.body === void 0 || opts.serializedBody === "") {
|
|
2269
|
+
opts.headers.delete("Content-Type");
|
|
2270
|
+
}
|
|
2271
|
+
const url = buildUrl(opts);
|
|
2272
|
+
return { opts, url };
|
|
2273
|
+
};
|
|
2274
|
+
const request = async (options) => {
|
|
2275
|
+
const { opts, url } = await beforeRequest(options);
|
|
2276
|
+
const requestInit = {
|
|
2277
|
+
redirect: "follow",
|
|
2278
|
+
...opts,
|
|
2279
|
+
body: getValidRequestBody(opts)
|
|
2280
|
+
};
|
|
2281
|
+
let request2 = new Request(url, requestInit);
|
|
2282
|
+
for (const fn of interceptors.request.fns) {
|
|
2283
|
+
if (fn) {
|
|
2284
|
+
request2 = await fn(request2, opts);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
const _fetch = opts.fetch;
|
|
2288
|
+
let response;
|
|
2289
|
+
try {
|
|
2290
|
+
response = await _fetch(request2);
|
|
2291
|
+
} catch (error2) {
|
|
2292
|
+
let finalError2 = error2;
|
|
2293
|
+
for (const fn of interceptors.error.fns) {
|
|
2294
|
+
if (fn) {
|
|
2295
|
+
finalError2 = await fn(
|
|
2296
|
+
error2,
|
|
2297
|
+
void 0,
|
|
2298
|
+
request2,
|
|
2299
|
+
opts
|
|
2300
|
+
);
|
|
2301
|
+
}
|
|
2302
|
+
}
|
|
2303
|
+
finalError2 = finalError2 || {};
|
|
2304
|
+
if (opts.throwOnError) {
|
|
2305
|
+
throw finalError2;
|
|
2306
|
+
}
|
|
2307
|
+
return opts.responseStyle === "data" ? void 0 : {
|
|
2308
|
+
error: finalError2,
|
|
2309
|
+
request: request2,
|
|
2310
|
+
response: void 0
|
|
2311
|
+
};
|
|
2312
|
+
}
|
|
2313
|
+
for (const fn of interceptors.response.fns) {
|
|
2314
|
+
if (fn) {
|
|
2315
|
+
response = await fn(response, request2, opts);
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
const result = {
|
|
2319
|
+
request: request2,
|
|
2320
|
+
response
|
|
2321
|
+
};
|
|
2322
|
+
if (response.ok) {
|
|
2323
|
+
const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
|
|
2324
|
+
if (response.status === 204 || response.headers.get("Content-Length") === "0") {
|
|
2325
|
+
let emptyData;
|
|
2326
|
+
switch (parseAs) {
|
|
2327
|
+
case "arrayBuffer":
|
|
2328
|
+
case "blob":
|
|
2329
|
+
case "text":
|
|
2330
|
+
emptyData = await response[parseAs]();
|
|
2331
|
+
break;
|
|
2332
|
+
case "formData":
|
|
2333
|
+
emptyData = new FormData();
|
|
2334
|
+
break;
|
|
2335
|
+
case "stream":
|
|
2336
|
+
emptyData = response.body;
|
|
2337
|
+
break;
|
|
2338
|
+
case "json":
|
|
2339
|
+
default:
|
|
2340
|
+
emptyData = {};
|
|
2341
|
+
break;
|
|
2342
|
+
}
|
|
2343
|
+
return opts.responseStyle === "data" ? emptyData : {
|
|
2344
|
+
data: emptyData,
|
|
2345
|
+
...result
|
|
2346
|
+
};
|
|
2347
|
+
}
|
|
2348
|
+
let data;
|
|
2349
|
+
switch (parseAs) {
|
|
2350
|
+
case "arrayBuffer":
|
|
2351
|
+
case "blob":
|
|
2352
|
+
case "formData":
|
|
2353
|
+
case "json":
|
|
2354
|
+
case "text":
|
|
2355
|
+
data = await response[parseAs]();
|
|
2356
|
+
break;
|
|
2357
|
+
case "stream":
|
|
2358
|
+
return opts.responseStyle === "data" ? response.body : {
|
|
2359
|
+
data: response.body,
|
|
2360
|
+
...result
|
|
2361
|
+
};
|
|
2362
|
+
}
|
|
2363
|
+
if (parseAs === "json") {
|
|
2364
|
+
if (opts.responseValidator) {
|
|
2365
|
+
await opts.responseValidator(data);
|
|
2366
|
+
}
|
|
2367
|
+
if (opts.responseTransformer) {
|
|
2368
|
+
data = await opts.responseTransformer(data);
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
return opts.responseStyle === "data" ? data : {
|
|
2372
|
+
data,
|
|
2373
|
+
...result
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
const textError = await response.text();
|
|
2377
|
+
let jsonError;
|
|
2378
|
+
try {
|
|
2379
|
+
jsonError = JSON.parse(textError);
|
|
2380
|
+
} catch {
|
|
2381
|
+
}
|
|
2382
|
+
const error = jsonError ?? textError;
|
|
2383
|
+
let finalError = error;
|
|
2384
|
+
for (const fn of interceptors.error.fns) {
|
|
2385
|
+
if (fn) {
|
|
2386
|
+
finalError = await fn(error, response, request2, opts);
|
|
2387
|
+
}
|
|
2388
|
+
}
|
|
2389
|
+
finalError = finalError || {};
|
|
2390
|
+
if (opts.throwOnError) {
|
|
2391
|
+
throw finalError;
|
|
2392
|
+
}
|
|
2393
|
+
return opts.responseStyle === "data" ? void 0 : {
|
|
2394
|
+
error: finalError,
|
|
2395
|
+
...result
|
|
2396
|
+
};
|
|
2397
|
+
};
|
|
2398
|
+
const makeMethodFn = (method) => (options) => request({ ...options, method });
|
|
2399
|
+
const makeSseFn = (method) => async (options) => {
|
|
2400
|
+
const { opts, url } = await beforeRequest(options);
|
|
2401
|
+
return createSseClient({
|
|
2402
|
+
...opts,
|
|
2403
|
+
body: opts.body,
|
|
2404
|
+
headers: opts.headers,
|
|
2405
|
+
method,
|
|
2406
|
+
onRequest: async (url2, init) => {
|
|
2407
|
+
let request2 = new Request(url2, init);
|
|
2408
|
+
for (const fn of interceptors.request.fns) {
|
|
2409
|
+
if (fn) {
|
|
2410
|
+
request2 = await fn(request2, opts);
|
|
2411
|
+
}
|
|
2412
|
+
}
|
|
2413
|
+
return request2;
|
|
2414
|
+
},
|
|
2415
|
+
url
|
|
2416
|
+
});
|
|
2417
|
+
};
|
|
2418
|
+
return {
|
|
2419
|
+
buildUrl,
|
|
2420
|
+
connect: makeMethodFn("CONNECT"),
|
|
2421
|
+
delete: makeMethodFn("DELETE"),
|
|
2422
|
+
get: makeMethodFn("GET"),
|
|
2423
|
+
getConfig,
|
|
2424
|
+
head: makeMethodFn("HEAD"),
|
|
2425
|
+
interceptors,
|
|
2426
|
+
options: makeMethodFn("OPTIONS"),
|
|
2427
|
+
patch: makeMethodFn("PATCH"),
|
|
2428
|
+
post: makeMethodFn("POST"),
|
|
2429
|
+
put: makeMethodFn("PUT"),
|
|
2430
|
+
request,
|
|
2431
|
+
setConfig,
|
|
2432
|
+
sse: {
|
|
2433
|
+
connect: makeSseFn("CONNECT"),
|
|
2434
|
+
delete: makeSseFn("DELETE"),
|
|
2435
|
+
get: makeSseFn("GET"),
|
|
2436
|
+
head: makeSseFn("HEAD"),
|
|
2437
|
+
options: makeSseFn("OPTIONS"),
|
|
2438
|
+
patch: makeSseFn("PATCH"),
|
|
2439
|
+
post: makeSseFn("POST"),
|
|
2440
|
+
put: makeSseFn("PUT"),
|
|
2441
|
+
trace: makeSseFn("TRACE")
|
|
2442
|
+
},
|
|
2443
|
+
trace: makeMethodFn("TRACE")
|
|
2444
|
+
};
|
|
2445
|
+
};
|
|
2446
|
+
createClient(
|
|
2447
|
+
createConfig({ baseUrl: "https://api.themolt.net" })
|
|
2448
|
+
);
|
|
2449
|
+
class MoltNetError extends Error {
|
|
2450
|
+
constructor(message, options) {
|
|
2451
|
+
super(message);
|
|
2452
|
+
__publicField(this, "code");
|
|
2453
|
+
__publicField(this, "statusCode");
|
|
2454
|
+
__publicField(this, "detail");
|
|
2455
|
+
this.name = "MoltNetError";
|
|
2456
|
+
this.code = options.code;
|
|
2457
|
+
this.statusCode = options.statusCode;
|
|
2458
|
+
this.detail = options.detail;
|
|
2459
|
+
}
|
|
2460
|
+
}
|
|
2461
|
+
function problemToError(problem, statusCode) {
|
|
2462
|
+
return new MoltNetError(problem.title ?? "Request failed", {
|
|
2463
|
+
code: problem.type ?? problem.code ?? "UNKNOWN",
|
|
2464
|
+
statusCode,
|
|
2465
|
+
detail: problem.detail
|
|
2466
|
+
});
|
|
2467
|
+
}
|
|
2468
|
+
async function writeMcpConfig(mcpConfig, dir2) {
|
|
2469
|
+
const targetDir = dir2 ?? process.cwd();
|
|
2470
|
+
const filePath = join(targetDir, ".mcp.json");
|
|
2471
|
+
let existing = {};
|
|
2472
|
+
try {
|
|
2473
|
+
const content = await readFile(filePath, "utf-8");
|
|
2474
|
+
existing = JSON.parse(content);
|
|
2475
|
+
} catch {
|
|
2476
|
+
}
|
|
2477
|
+
const merged = {
|
|
2478
|
+
...existing,
|
|
2479
|
+
mcpServers: {
|
|
2480
|
+
...existing.mcpServers ?? {},
|
|
2481
|
+
...mcpConfig.mcpServers
|
|
2482
|
+
}
|
|
2483
|
+
};
|
|
2484
|
+
await writeFile(filePath, JSON.stringify(merged, null, 2) + "\n");
|
|
2485
|
+
return filePath;
|
|
2486
|
+
}
|
|
2487
|
+
function getConfigDir() {
|
|
2488
|
+
return join(homedir(), ".config", "moltnet");
|
|
2489
|
+
}
|
|
2490
|
+
function getConfigPath(configDir) {
|
|
2491
|
+
return join(configDir ?? getConfigDir(), "moltnet.json");
|
|
2492
|
+
}
|
|
2493
|
+
async function readConfig(configDir) {
|
|
2494
|
+
const dir2 = configDir ?? getConfigDir();
|
|
2495
|
+
try {
|
|
2496
|
+
const content = await readFile(join(dir2, "moltnet.json"), "utf-8");
|
|
2497
|
+
return JSON.parse(content);
|
|
2498
|
+
} catch {
|
|
2499
|
+
}
|
|
2500
|
+
try {
|
|
2501
|
+
const content = await readFile(join(dir2, "credentials.json"), "utf-8");
|
|
2502
|
+
console.warn(
|
|
2503
|
+
"Warning: credentials.json is deprecated. New writes use moltnet.json. Support will be removed in 3 minor versions."
|
|
1878
2504
|
);
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
2505
|
+
return JSON.parse(content);
|
|
2506
|
+
} catch {
|
|
2507
|
+
return null;
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
async function writeConfig(config, configDir) {
|
|
2511
|
+
const dir2 = configDir ?? getConfigDir();
|
|
2512
|
+
await mkdir(dir2, { recursive: true });
|
|
2513
|
+
const filePath = join(dir2, "moltnet.json");
|
|
2514
|
+
await writeFile(filePath, JSON.stringify(config, null, 2) + "\n", {
|
|
2515
|
+
mode: 384
|
|
2516
|
+
});
|
|
2517
|
+
await chmod(filePath, 384);
|
|
2518
|
+
return filePath;
|
|
2519
|
+
}
|
|
2520
|
+
async function updateConfigSection(section, data, configDir) {
|
|
2521
|
+
const config = await readConfig(configDir);
|
|
2522
|
+
if (!config) {
|
|
2523
|
+
throw new Error("No config found — run `moltnet register` first");
|
|
1887
2524
|
}
|
|
2525
|
+
const existing = config[section] ?? {};
|
|
2526
|
+
const updated = { ...existing, ...data };
|
|
2527
|
+
Object.assign(config, { [section]: updated });
|
|
2528
|
+
await writeConfig(config, configDir);
|
|
2529
|
+
}
|
|
2530
|
+
etc.sha512Sync = (...m) => {
|
|
2531
|
+
const hash = createHash("sha512");
|
|
2532
|
+
m.forEach((msg) => hash.update(msg));
|
|
2533
|
+
return hash.digest();
|
|
1888
2534
|
};
|
|
1889
2535
|
if (!etc.sha512Sync) {
|
|
1890
2536
|
etc.sha512Sync = (...m) => {
|
|
@@ -1990,19 +2636,25 @@ function toSSHPrivateKey(seedBase64) {
|
|
|
1990
2636
|
].join("\n");
|
|
1991
2637
|
}
|
|
1992
2638
|
async function exportSSHKey(opts) {
|
|
1993
|
-
const config = await readConfig(opts
|
|
2639
|
+
const config = await readConfig(opts == null ? void 0 : opts.configDir);
|
|
1994
2640
|
if (!config) {
|
|
1995
|
-
throw new Error(
|
|
2641
|
+
throw new Error(
|
|
2642
|
+
`No config found at ${getConfigPath(opts == null ? void 0 : opts.configDir)} — run \`moltnet register\` first`
|
|
2643
|
+
);
|
|
1996
2644
|
}
|
|
1997
2645
|
const privateKeySSH = toSSHPrivateKey(config.keys.private_key);
|
|
1998
2646
|
const publicKeySSH = toSSHPublicKey(config.keys.public_key);
|
|
1999
|
-
const outputDir = opts
|
|
2647
|
+
const outputDir = (opts == null ? void 0 : opts.outputDir) ?? join((opts == null ? void 0 : opts.configDir) ?? getConfigDir(), "ssh");
|
|
2000
2648
|
await mkdir(outputDir, { recursive: true });
|
|
2001
2649
|
const privatePath = join(outputDir, "id_ed25519");
|
|
2002
2650
|
const publicPath = join(outputDir, "id_ed25519.pub");
|
|
2003
2651
|
await writeFile(privatePath, privateKeySSH, { mode: 384 });
|
|
2004
2652
|
await writeFile(publicPath, publicKeySSH, { mode: 420 });
|
|
2005
|
-
await updateConfigSection(
|
|
2653
|
+
await updateConfigSection(
|
|
2654
|
+
"ssh",
|
|
2655
|
+
{ private_key_path: privatePath, public_key_path: publicPath },
|
|
2656
|
+
opts == null ? void 0 : opts.configDir
|
|
2657
|
+
);
|
|
2006
2658
|
return { privatePath, publicPath };
|
|
2007
2659
|
}
|
|
2008
2660
|
const POLL_INTERVAL_MS = 5e3;
|
|
@@ -2020,7 +2672,7 @@ function toErrorMessage(err2) {
|
|
|
2020
2672
|
}
|
|
2021
2673
|
const POLL_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
2022
2674
|
function makeClient(baseUrl) {
|
|
2023
|
-
return createClient({ baseUrl });
|
|
2675
|
+
return createClient$1({ baseUrl });
|
|
2024
2676
|
}
|
|
2025
2677
|
async function startOnboarding(baseUrl, body) {
|
|
2026
2678
|
const client2 = makeClient(baseUrl);
|
|
@@ -2067,24 +2719,49 @@ async function pollUntil(baseUrl, workflowId, targetStatuses, onTick) {
|
|
|
2067
2719
|
`Timed out waiting for status: ${targetStatuses.join(" or ")}`
|
|
2068
2720
|
);
|
|
2069
2721
|
}
|
|
2722
|
+
const SKILL_DIRS = {
|
|
2723
|
+
claude: ".claude/skills"
|
|
2724
|
+
// codex: '.agents/skills',
|
|
2725
|
+
};
|
|
2726
|
+
const SKILL_VERSION = "legreffier-v0.1.0";
|
|
2070
2727
|
const SKILLS = [
|
|
2071
2728
|
{
|
|
2072
2729
|
name: "legreffier",
|
|
2073
|
-
url:
|
|
2730
|
+
url: `https://raw.githubusercontent.com/getlarge/themoltnet/${SKILL_VERSION}/.claude/skills/legreffier/SKILL.md`
|
|
2074
2731
|
}
|
|
2075
2732
|
];
|
|
2076
|
-
async function downloadSkills(repoDir) {
|
|
2733
|
+
async function downloadSkills(repoDir, agentTypes) {
|
|
2734
|
+
const dirs = agentTypes.map((t) => SKILL_DIRS[t]).filter((d) => !!d);
|
|
2735
|
+
if (dirs.length === 0) return;
|
|
2077
2736
|
for (const skill of SKILLS) {
|
|
2078
|
-
const dir2 = join(repoDir, ".claude", "skills", skill.name);
|
|
2079
|
-
await mkdir(dir2, { recursive: true });
|
|
2080
2737
|
const res = await fetch(skill.url);
|
|
2081
2738
|
if (!res.ok) {
|
|
2082
2739
|
throw new Error(`Failed to download skill ${skill.name} (${res.status})`);
|
|
2083
2740
|
}
|
|
2084
2741
|
const content = await res.text();
|
|
2085
|
-
|
|
2742
|
+
for (const skillDir of dirs) {
|
|
2743
|
+
const destDir = join(repoDir, skillDir, skill.name);
|
|
2744
|
+
await mkdir(destDir, { recursive: true });
|
|
2745
|
+
await writeFile(join(destDir, "SKILL.md"), content, "utf-8");
|
|
2746
|
+
}
|
|
2086
2747
|
}
|
|
2087
2748
|
}
|
|
2749
|
+
function buildPermissions(agentName) {
|
|
2750
|
+
return [
|
|
2751
|
+
// Read-only git commands used by session activation & commit workflow
|
|
2752
|
+
"Bash(git config *)",
|
|
2753
|
+
"Bash(git diff *)",
|
|
2754
|
+
"Bash(git log *)",
|
|
2755
|
+
"Bash(git rev-parse *)",
|
|
2756
|
+
"Bash(git worktree list)",
|
|
2757
|
+
// Signing CLI
|
|
2758
|
+
"Bash(moltnet sign *)",
|
|
2759
|
+
// Worktree symlink creation
|
|
2760
|
+
"Bash(ln -s *)",
|
|
2761
|
+
// All MCP tools for this agent's server
|
|
2762
|
+
`mcp__${agentName}__*`
|
|
2763
|
+
];
|
|
2764
|
+
}
|
|
2088
2765
|
function toEnvPrefix(agentName) {
|
|
2089
2766
|
return agentName.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
2090
2767
|
}
|
|
@@ -2106,9 +2783,23 @@ async function writeSettingsLocal({
|
|
|
2106
2783
|
} catch {
|
|
2107
2784
|
}
|
|
2108
2785
|
const prefix = toEnvPrefix(agentName);
|
|
2786
|
+
const existingServers = Array.isArray(
|
|
2787
|
+
existing.enabledMcpjsonServers
|
|
2788
|
+
) ? existing.enabledMcpjsonServers : [];
|
|
2789
|
+
const enabledMcpjsonServers = existingServers.includes(agentName) ? existingServers : [...existingServers, agentName];
|
|
2790
|
+
const newPerms = buildPermissions(agentName);
|
|
2791
|
+
const existingAllow = Array.isArray(existing.permissions?.allow) ? existing.permissions.allow : [];
|
|
2792
|
+
const mergedAllow = [
|
|
2793
|
+
...existingAllow,
|
|
2794
|
+
...newPerms.filter((p) => !existingAllow.includes(p))
|
|
2795
|
+
];
|
|
2109
2796
|
const settings = {
|
|
2110
2797
|
...existing,
|
|
2111
|
-
|
|
2798
|
+
enabledMcpjsonServers,
|
|
2799
|
+
permissions: {
|
|
2800
|
+
...existing.permissions,
|
|
2801
|
+
allow: mergedAllow
|
|
2802
|
+
},
|
|
2112
2803
|
env: {
|
|
2113
2804
|
...existing.env,
|
|
2114
2805
|
[`${prefix}_GITHUB_APP_ID`]: appSlug,
|
|
@@ -2120,49 +2811,27 @@ async function writeSettingsLocal({
|
|
|
2120
2811
|
};
|
|
2121
2812
|
await writeFile(filePath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
2122
2813
|
}
|
|
2123
|
-
function
|
|
2124
|
-
|
|
2125
|
-
const origin = execSync("git remote get-url origin", {
|
|
2126
|
-
cwd,
|
|
2127
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
2128
|
-
}).toString().trim();
|
|
2129
|
-
const match = origin.match(/[:/]([^/]+\/[^/]+?)(?:\.git)?$/);
|
|
2130
|
-
if (match) {
|
|
2131
|
-
return match[1].replace("/", "-");
|
|
2132
|
-
}
|
|
2133
|
-
} catch {
|
|
2134
|
-
}
|
|
2135
|
-
return basename(cwd);
|
|
2136
|
-
}
|
|
2137
|
-
function getStatePath(projectSlug, agentName) {
|
|
2138
|
-
return join(
|
|
2139
|
-
homedir(),
|
|
2140
|
-
".config",
|
|
2141
|
-
"moltnet",
|
|
2142
|
-
projectSlug,
|
|
2143
|
-
`legreffier-init.${agentName}.state.json`
|
|
2144
|
-
);
|
|
2814
|
+
function getStatePath(configDir) {
|
|
2815
|
+
return join(configDir, "legreffier-init.state.json");
|
|
2145
2816
|
}
|
|
2146
|
-
async function readState(
|
|
2817
|
+
async function readState(configDir) {
|
|
2147
2818
|
try {
|
|
2148
|
-
const raw = await readFile(getStatePath(
|
|
2819
|
+
const raw = await readFile(getStatePath(configDir), "utf-8");
|
|
2149
2820
|
return JSON.parse(raw);
|
|
2150
2821
|
} catch {
|
|
2151
2822
|
return null;
|
|
2152
2823
|
}
|
|
2153
2824
|
}
|
|
2154
|
-
async function writeState(state,
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
recursive: true
|
|
2158
|
-
});
|
|
2825
|
+
async function writeState(state, configDir) {
|
|
2826
|
+
await mkdir(configDir, { recursive: true });
|
|
2827
|
+
const path = getStatePath(configDir);
|
|
2159
2828
|
await writeFile(path, JSON.stringify(state, null, 2) + "\n", {
|
|
2160
2829
|
mode: 384
|
|
2161
2830
|
});
|
|
2162
2831
|
}
|
|
2163
|
-
async function clearState(
|
|
2832
|
+
async function clearState(configDir) {
|
|
2164
2833
|
try {
|
|
2165
|
-
await rm(getStatePath(
|
|
2834
|
+
await rm(getStatePath(configDir));
|
|
2166
2835
|
} catch {
|
|
2167
2836
|
}
|
|
2168
2837
|
}
|
|
@@ -2172,6 +2841,7 @@ async function runAgentSetupPhase(opts) {
|
|
|
2172
2841
|
repoDir,
|
|
2173
2842
|
configDir,
|
|
2174
2843
|
agentName,
|
|
2844
|
+
agentTypes,
|
|
2175
2845
|
publicKey,
|
|
2176
2846
|
fingerprint,
|
|
2177
2847
|
appSlug,
|
|
@@ -2180,7 +2850,6 @@ async function runAgentSetupPhase(opts) {
|
|
|
2180
2850
|
identityId,
|
|
2181
2851
|
clientId,
|
|
2182
2852
|
clientSecret,
|
|
2183
|
-
projectSlug,
|
|
2184
2853
|
dispatch
|
|
2185
2854
|
} = opts;
|
|
2186
2855
|
dispatch({ type: "phase", phase: "agent_setup" });
|
|
@@ -2230,7 +2899,7 @@ async function runAgentSetupPhase(opts) {
|
|
|
2230
2899
|
);
|
|
2231
2900
|
}
|
|
2232
2901
|
dispatch({ type: "step", key: "skills", status: "running" });
|
|
2233
|
-
await downloadSkills(repoDir);
|
|
2902
|
+
await downloadSkills(repoDir, agentTypes);
|
|
2234
2903
|
dispatch({ type: "step", key: "skills", status: "done" });
|
|
2235
2904
|
dispatch({ type: "step", key: "settings", status: "running" });
|
|
2236
2905
|
await writeSettingsLocal({
|
|
@@ -2243,7 +2912,7 @@ async function runAgentSetupPhase(opts) {
|
|
|
2243
2912
|
clientSecret
|
|
2244
2913
|
});
|
|
2245
2914
|
dispatch({ type: "step", key: "settings", status: "done" });
|
|
2246
|
-
await clearState(
|
|
2915
|
+
await clearState(configDir);
|
|
2247
2916
|
}
|
|
2248
2917
|
async function exchangeManifestCode(code) {
|
|
2249
2918
|
const res = await fetch(
|
|
@@ -2326,10 +2995,9 @@ async function lookupBotUser(appSlug, { maxRetries = 5, baseDelayMs = 2e3 } = {}
|
|
|
2326
2995
|
}
|
|
2327
2996
|
throw new Error(`GitHub user lookup failed for app "${appSlug}"`);
|
|
2328
2997
|
}
|
|
2329
|
-
async function writePem(pem, appSlug,
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
const path = join(dir2, `${appSlug}.pem`);
|
|
2998
|
+
async function writePem(pem, appSlug, configDir) {
|
|
2999
|
+
await mkdir(configDir, { recursive: true });
|
|
3000
|
+
const path = join(configDir, `${appSlug}.pem`);
|
|
2333
3001
|
await writeFile(path, pem, { mode: 384 });
|
|
2334
3002
|
await chmod(path, 384);
|
|
2335
3003
|
return path;
|
|
@@ -2361,7 +3029,6 @@ async function runGithubAppPhase(opts) {
|
|
|
2361
3029
|
apiUrl: apiUrl2,
|
|
2362
3030
|
agentName,
|
|
2363
3031
|
configDir,
|
|
2364
|
-
projectSlug,
|
|
2365
3032
|
publicKey,
|
|
2366
3033
|
privateKey,
|
|
2367
3034
|
fingerprint,
|
|
@@ -2370,7 +3037,7 @@ async function runGithubAppPhase(opts) {
|
|
|
2370
3037
|
dispatch
|
|
2371
3038
|
} = opts;
|
|
2372
3039
|
const existingConfig = await readConfig(configDir);
|
|
2373
|
-
const existingState = await readState(
|
|
3040
|
+
const existingState = await readState(configDir);
|
|
2374
3041
|
if (existingConfig?.github?.app_id) {
|
|
2375
3042
|
dispatch({ type: "step", key: "githubApp", status: "skipped" });
|
|
2376
3043
|
dispatch({
|
|
@@ -2385,13 +3052,7 @@ async function runGithubAppPhase(opts) {
|
|
|
2385
3052
|
};
|
|
2386
3053
|
}
|
|
2387
3054
|
if (existingState?.appSlug && existingState?.appId) {
|
|
2388
|
-
const pemPath2 = join(
|
|
2389
|
-
homedir(),
|
|
2390
|
-
".config",
|
|
2391
|
-
"moltnet",
|
|
2392
|
-
projectSlug,
|
|
2393
|
-
`${existingState.appSlug}.pem`
|
|
2394
|
-
);
|
|
3055
|
+
const pemPath2 = join(configDir, `${existingState.appSlug}.pem`);
|
|
2395
3056
|
dispatch({ type: "step", key: "githubApp", status: "skipped" });
|
|
2396
3057
|
dispatch({ type: "appSlug", appSlug: existingState.appSlug });
|
|
2397
3058
|
return {
|
|
@@ -2416,7 +3077,7 @@ async function runGithubAppPhase(opts) {
|
|
|
2416
3077
|
}
|
|
2417
3078
|
const ghCreds = await exchangeManifestCode(codeResult.githubCode);
|
|
2418
3079
|
dispatch({ type: "appSlug", appSlug: ghCreds.appSlug });
|
|
2419
|
-
const pemPath = await writePem(ghCreds.pem, ghCreds.appSlug,
|
|
3080
|
+
const pemPath = await writePem(ghCreds.pem, ghCreds.appSlug, configDir);
|
|
2420
3081
|
await writeState(
|
|
2421
3082
|
{
|
|
2422
3083
|
workflowId,
|
|
@@ -2428,8 +3089,7 @@ async function runGithubAppPhase(opts) {
|
|
|
2428
3089
|
appId: ghCreds.appId,
|
|
2429
3090
|
appSlug: ghCreds.appSlug
|
|
2430
3091
|
},
|
|
2431
|
-
|
|
2432
|
-
agentName
|
|
3092
|
+
configDir
|
|
2433
3093
|
);
|
|
2434
3094
|
dispatch({ type: "step", key: "githubApp", status: "done" });
|
|
2435
3095
|
return {
|
|
@@ -2468,10 +3128,187 @@ async function runGitSetupPhase(opts) {
|
|
|
2468
3128
|
);
|
|
2469
3129
|
dispatch({ type: "step", key: "gitSetup", status: "done" });
|
|
2470
3130
|
}
|
|
3131
|
+
etc.sha512Sync = (...m) => {
|
|
3132
|
+
const hash = createHash("sha512");
|
|
3133
|
+
m.forEach((msg) => hash.update(msg));
|
|
3134
|
+
return hash.digest();
|
|
3135
|
+
};
|
|
3136
|
+
const DOMAIN_PREFIX = "moltnet:v1";
|
|
3137
|
+
function buildSigningBytes(message, nonce) {
|
|
3138
|
+
const msgHash = createHash("sha256").update(Buffer.from(message, "utf-8")).digest();
|
|
3139
|
+
const nonceBytes = Buffer.from(nonce, "utf-8");
|
|
3140
|
+
const prefix = Buffer.from(DOMAIN_PREFIX, "utf-8");
|
|
3141
|
+
const buf = Buffer.alloc(
|
|
3142
|
+
prefix.length + 4 + msgHash.length + 4 + nonceBytes.length
|
|
3143
|
+
);
|
|
3144
|
+
let offset = 0;
|
|
3145
|
+
prefix.copy(buf, offset);
|
|
3146
|
+
offset += prefix.length;
|
|
3147
|
+
buf.writeUInt32BE(msgHash.length, offset);
|
|
3148
|
+
offset += 4;
|
|
3149
|
+
msgHash.copy(buf, offset);
|
|
3150
|
+
offset += msgHash.length;
|
|
3151
|
+
buf.writeUInt32BE(nonceBytes.length, offset);
|
|
3152
|
+
offset += 4;
|
|
3153
|
+
nonceBytes.copy(buf, offset);
|
|
3154
|
+
return new Uint8Array(buf);
|
|
3155
|
+
}
|
|
3156
|
+
const cryptoService = {
|
|
3157
|
+
/**
|
|
3158
|
+
* Generate a new Ed25519 keypair
|
|
3159
|
+
*/
|
|
3160
|
+
async generateKeyPair() {
|
|
3161
|
+
const privateKeyBytes = utils.randomPrivateKey();
|
|
3162
|
+
const publicKeyBytes = await getPublicKeyAsync(privateKeyBytes);
|
|
3163
|
+
const privateKey = Buffer.from(privateKeyBytes).toString("base64");
|
|
3164
|
+
const publicKey = `ed25519:${Buffer.from(publicKeyBytes).toString("base64")}`;
|
|
3165
|
+
const fingerprint = this.generateFingerprint(publicKeyBytes);
|
|
3166
|
+
return { publicKey, privateKey, fingerprint };
|
|
3167
|
+
},
|
|
3168
|
+
/**
|
|
3169
|
+
* Generate human-readable fingerprint from public key
|
|
3170
|
+
* Format: A1B2-C3D4-E5F6-G7H8 (first 16 hex chars of SHA256)
|
|
3171
|
+
*/
|
|
3172
|
+
generateFingerprint(publicKeyBytes) {
|
|
3173
|
+
const hash = createHash("sha256").update(publicKeyBytes).digest("hex");
|
|
3174
|
+
const segments = hash.slice(0, 16).toUpperCase().match(/.{4}/g) ?? [];
|
|
3175
|
+
return segments.join("-");
|
|
3176
|
+
},
|
|
3177
|
+
/**
|
|
3178
|
+
* Parse public key from string format
|
|
3179
|
+
*/
|
|
3180
|
+
parsePublicKey(publicKey) {
|
|
3181
|
+
const base64 = publicKey.replace(/^ed25519:/, "");
|
|
3182
|
+
return new Uint8Array(Buffer.from(base64, "base64"));
|
|
3183
|
+
},
|
|
3184
|
+
/**
|
|
3185
|
+
* Sign a message with private key
|
|
3186
|
+
*/
|
|
3187
|
+
async sign(message, privateKeyBase64) {
|
|
3188
|
+
const privateKeyBytes = new Uint8Array(
|
|
3189
|
+
Buffer.from(privateKeyBase64, "base64")
|
|
3190
|
+
);
|
|
3191
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
3192
|
+
const signature = await signAsync(messageBytes, privateKeyBytes);
|
|
3193
|
+
return Buffer.from(signature).toString("base64");
|
|
3194
|
+
},
|
|
3195
|
+
/**
|
|
3196
|
+
* Verify a signature against a message and public key
|
|
3197
|
+
*/
|
|
3198
|
+
async verify(message, signature, publicKey) {
|
|
3199
|
+
try {
|
|
3200
|
+
const publicKeyBytes = this.parsePublicKey(publicKey);
|
|
3201
|
+
const signatureBytes = new Uint8Array(Buffer.from(signature, "base64"));
|
|
3202
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
3203
|
+
return await verifyAsync(signatureBytes, messageBytes, publicKeyBytes);
|
|
3204
|
+
} catch {
|
|
3205
|
+
return false;
|
|
3206
|
+
}
|
|
3207
|
+
},
|
|
3208
|
+
/**
|
|
3209
|
+
* Sign a (message, nonce) pair using deterministic pre-hash.
|
|
3210
|
+
* Uses buildSigningBytes for domain separation and canonical serialization.
|
|
3211
|
+
*/
|
|
3212
|
+
async signWithNonce(message, nonce, privateKeyBase64) {
|
|
3213
|
+
const privateKeyBytes = new Uint8Array(
|
|
3214
|
+
Buffer.from(privateKeyBase64, "base64")
|
|
3215
|
+
);
|
|
3216
|
+
const signingBytes = buildSigningBytes(message, nonce);
|
|
3217
|
+
const signature = await signAsync(signingBytes, privateKeyBytes);
|
|
3218
|
+
return Buffer.from(signature).toString("base64");
|
|
3219
|
+
},
|
|
3220
|
+
/**
|
|
3221
|
+
* Verify a signature produced by signWithNonce.
|
|
3222
|
+
*/
|
|
3223
|
+
async verifyWithNonce(message, nonce, signature, publicKey) {
|
|
3224
|
+
try {
|
|
3225
|
+
const publicKeyBytes = this.parsePublicKey(publicKey);
|
|
3226
|
+
const signatureBytes = new Uint8Array(Buffer.from(signature, "base64"));
|
|
3227
|
+
const signingBytes = buildSigningBytes(message, nonce);
|
|
3228
|
+
return await verifyAsync(signatureBytes, signingBytes, publicKeyBytes);
|
|
3229
|
+
} catch {
|
|
3230
|
+
return false;
|
|
3231
|
+
}
|
|
3232
|
+
},
|
|
3233
|
+
/**
|
|
3234
|
+
* Create a signed message object
|
|
3235
|
+
*/
|
|
3236
|
+
async createSignedMessage(message, privateKeyBase64, publicKey) {
|
|
3237
|
+
const signature = await this.sign(message, privateKeyBase64);
|
|
3238
|
+
return { message, signature, publicKey };
|
|
3239
|
+
},
|
|
3240
|
+
/**
|
|
3241
|
+
* Verify a signed message object
|
|
3242
|
+
*/
|
|
3243
|
+
async verifySignedMessage(signedMessage) {
|
|
3244
|
+
return this.verify(
|
|
3245
|
+
signedMessage.message,
|
|
3246
|
+
signedMessage.signature,
|
|
3247
|
+
signedMessage.publicKey
|
|
3248
|
+
);
|
|
3249
|
+
},
|
|
3250
|
+
/**
|
|
3251
|
+
* Generate a random challenge for authentication
|
|
3252
|
+
*/
|
|
3253
|
+
generateChallenge() {
|
|
3254
|
+
return `moltnet:challenge:${randomBytes$1(32).toString("hex")}:${Date.now()}`;
|
|
3255
|
+
},
|
|
3256
|
+
/**
|
|
3257
|
+
* Derive public key from private key
|
|
3258
|
+
*/
|
|
3259
|
+
async derivePublicKey(privateKeyBase64) {
|
|
3260
|
+
const privateKeyBytes = new Uint8Array(
|
|
3261
|
+
Buffer.from(privateKeyBase64, "base64")
|
|
3262
|
+
);
|
|
3263
|
+
const publicKeyBytes = await getPublicKeyAsync(privateKeyBytes);
|
|
3264
|
+
return `ed25519:${Buffer.from(publicKeyBytes).toString("base64")}`;
|
|
3265
|
+
},
|
|
3266
|
+
/**
|
|
3267
|
+
* Get fingerprint from public key string
|
|
3268
|
+
*/
|
|
3269
|
+
getFingerprintFromPublicKey(publicKey) {
|
|
3270
|
+
const publicKeyBytes = this.parsePublicKey(publicKey);
|
|
3271
|
+
return this.generateFingerprint(publicKeyBytes);
|
|
3272
|
+
},
|
|
3273
|
+
/**
|
|
3274
|
+
* Create a proof of identity ownership (for DCR metadata)
|
|
3275
|
+
*/
|
|
3276
|
+
async createIdentityProof(identityId, privateKeyBase64) {
|
|
3277
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
3278
|
+
const message = `moltnet:register:${identityId}:${timestamp}`;
|
|
3279
|
+
const signature = await this.sign(message, privateKeyBase64);
|
|
3280
|
+
return { message, signature, timestamp };
|
|
3281
|
+
},
|
|
3282
|
+
/**
|
|
3283
|
+
* Verify an identity proof
|
|
3284
|
+
*/
|
|
3285
|
+
async verifyIdentityProof(proof, publicKey, expectedIdentityId) {
|
|
3286
|
+
const isValid = await this.verify(
|
|
3287
|
+
proof.message,
|
|
3288
|
+
proof.signature,
|
|
3289
|
+
publicKey
|
|
3290
|
+
);
|
|
3291
|
+
if (!isValid) return false;
|
|
3292
|
+
const expectedPrefix = `moltnet:register:${expectedIdentityId}:`;
|
|
3293
|
+
if (!proof.message.startsWith(expectedPrefix)) return false;
|
|
3294
|
+
const proofTime = new Date(proof.timestamp).getTime();
|
|
3295
|
+
const now = Date.now();
|
|
3296
|
+
const fiveMinutes = 5 * 60 * 1e3;
|
|
3297
|
+
if (now - proofTime > fiveMinutes) return false;
|
|
3298
|
+
return true;
|
|
3299
|
+
}
|
|
3300
|
+
};
|
|
3301
|
+
if (!etc.sha512Sync) {
|
|
3302
|
+
etc.sha512Sync = (...m) => {
|
|
3303
|
+
const hash = createHash("sha512");
|
|
3304
|
+
m.forEach((msg) => hash.update(msg));
|
|
3305
|
+
return hash.digest();
|
|
3306
|
+
};
|
|
3307
|
+
}
|
|
2471
3308
|
async function runIdentityPhase(opts) {
|
|
2472
|
-
const { apiUrl: apiUrl2, agentName, configDir,
|
|
3309
|
+
const { apiUrl: apiUrl2, agentName, configDir, dispatch } = opts;
|
|
2473
3310
|
const existingConfig = await readConfig(configDir);
|
|
2474
|
-
const existingState = await readState(
|
|
3311
|
+
const existingState = await readState(configDir);
|
|
2475
3312
|
if (existingConfig?.keys?.public_key && existingConfig?.oauth2?.client_id) {
|
|
2476
3313
|
dispatch({ type: "step", key: "keypair", status: "skipped" });
|
|
2477
3314
|
dispatch({ type: "step", key: "register", status: "skipped" });
|
|
@@ -2527,7 +3364,7 @@ async function runIdentityPhase(opts) {
|
|
|
2527
3364
|
skipped: true
|
|
2528
3365
|
};
|
|
2529
3366
|
}
|
|
2530
|
-
await clearState(
|
|
3367
|
+
await clearState(configDir);
|
|
2531
3368
|
}
|
|
2532
3369
|
const available = await checkAppNameAvailable(agentName);
|
|
2533
3370
|
if (!available) {
|
|
@@ -2554,8 +3391,7 @@ async function runIdentityPhase(opts) {
|
|
|
2554
3391
|
agentName,
|
|
2555
3392
|
phase: "awaiting_github"
|
|
2556
3393
|
},
|
|
2557
|
-
|
|
2558
|
-
agentName
|
|
3394
|
+
configDir
|
|
2559
3395
|
);
|
|
2560
3396
|
await writeConfig(
|
|
2561
3397
|
{
|
|
@@ -2614,6 +3450,7 @@ async function runInstallationPhase(opts) {
|
|
|
2614
3450
|
clientSecret: result.clientSecret ?? ""
|
|
2615
3451
|
};
|
|
2616
3452
|
}
|
|
3453
|
+
const SUPPORTED_AGENTS = ["claude"];
|
|
2617
3454
|
const AGENTS = [
|
|
2618
3455
|
{
|
|
2619
3456
|
id: "claude",
|
|
@@ -2643,7 +3480,7 @@ function AgentSelect({ onSelect }) {
|
|
|
2643
3480
|
setSelected((i) => i < AGENTS.length - 1 ? i + 1 : i);
|
|
2644
3481
|
} else if (key.return) {
|
|
2645
3482
|
const agent2 = AGENTS[selected];
|
|
2646
|
-
if (agent2 && agent2.
|
|
3483
|
+
if (agent2?.available && SUPPORTED_AGENTS.includes(agent2.id)) {
|
|
2647
3484
|
onSelect(agent2.id);
|
|
2648
3485
|
}
|
|
2649
3486
|
}
|
|
@@ -2929,19 +3766,16 @@ function InitApp({
|
|
|
2929
3766
|
void (async () => {
|
|
2930
3767
|
try {
|
|
2931
3768
|
const configDir = join(dir2, ".moltnet", name2);
|
|
2932
|
-
const projectSlug = deriveProjectSlug(dir2);
|
|
2933
3769
|
const identity = await runIdentityPhase({
|
|
2934
3770
|
apiUrl: apiUrl2,
|
|
2935
3771
|
agentName: name2,
|
|
2936
3772
|
configDir,
|
|
2937
|
-
projectSlug,
|
|
2938
3773
|
dispatch
|
|
2939
3774
|
});
|
|
2940
3775
|
const githubApp = await runGithubAppPhase({
|
|
2941
3776
|
apiUrl: apiUrl2,
|
|
2942
3777
|
agentName: name2,
|
|
2943
3778
|
configDir,
|
|
2944
|
-
projectSlug,
|
|
2945
3779
|
publicKey: identity.publicKey,
|
|
2946
3780
|
privateKey: identity.privateKey,
|
|
2947
3781
|
fingerprint: identity.fingerprint,
|
|
@@ -2967,6 +3801,7 @@ function InitApp({
|
|
|
2967
3801
|
repoDir: dir2,
|
|
2968
3802
|
configDir,
|
|
2969
3803
|
agentName: name2,
|
|
3804
|
+
agentTypes: selectedAgent ? [selectedAgent] : [],
|
|
2970
3805
|
publicKey: identity.publicKey,
|
|
2971
3806
|
fingerprint: identity.fingerprint,
|
|
2972
3807
|
appSlug: githubApp.appSlug,
|
|
@@ -2975,7 +3810,6 @@ function InitApp({
|
|
|
2975
3810
|
identityId: installation.identityId,
|
|
2976
3811
|
clientId: installation.clientId || identity.clientId,
|
|
2977
3812
|
clientSecret: installation.clientSecret || identity.clientSecret,
|
|
2978
|
-
projectSlug,
|
|
2979
3813
|
dispatch
|
|
2980
3814
|
});
|
|
2981
3815
|
const mcpUrl = apiUrl2.replace("://api.", "://mcp.") + "/mcp";
|
|
@@ -3031,7 +3865,6 @@ function InitApp({
|
|
|
3031
3865
|
}
|
|
3032
3866
|
);
|
|
3033
3867
|
}
|
|
3034
|
-
const SUPPORTED_AGENTS = ["claude"];
|
|
3035
3868
|
const { values } = parseArgs({
|
|
3036
3869
|
args: process.argv.slice(2),
|
|
3037
3870
|
options: {
|
|
@@ -3051,6 +3884,14 @@ if (!name) {
|
|
|
3051
3884
|
);
|
|
3052
3885
|
process.exit(1);
|
|
3053
3886
|
}
|
|
3887
|
+
const AGENT_NAME_RE = /^[a-z0-9][a-z0-9-]{0,37}[a-z0-9]$/;
|
|
3888
|
+
if (!AGENT_NAME_RE.test(name)) {
|
|
3889
|
+
process.stderr.write(
|
|
3890
|
+
`Invalid agent name: "${name}". Must be 2-39 lowercase alphanumeric characters or hyphens, starting and ending with a letter or digit.
|
|
3891
|
+
`
|
|
3892
|
+
);
|
|
3893
|
+
process.exit(1);
|
|
3894
|
+
}
|
|
3054
3895
|
if (agentFlag && !SUPPORTED_AGENTS.includes(agentFlag)) {
|
|
3055
3896
|
process.stderr.write(
|
|
3056
3897
|
`Unsupported agent: ${agentFlag}. Supported: ${SUPPORTED_AGENTS.join(", ")}
|