@docyrus/docyrus 0.0.1 → 0.0.2
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 +11 -0
- package/main.js +363 -24
- package/main.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -97,6 +97,17 @@ Download current tenant OpenAPI spec:
|
|
|
97
97
|
docyrus discover api --json
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
+
Discover from downloaded tenant OpenAPI spec:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
docyrus discover namespaces --json
|
|
104
|
+
docyrus discover path /v1/users --json
|
|
105
|
+
docyrus discover endpoint /v1/users/me --json
|
|
106
|
+
docyrus discover endpoint [PUT]/v1/users/me/photo --json
|
|
107
|
+
docyrus discover entity UserEntity --json
|
|
108
|
+
docyrus discover search users,UserEntity --json
|
|
109
|
+
```
|
|
110
|
+
|
|
100
111
|
Work with accounts and tenants:
|
|
101
112
|
|
|
102
113
|
```bash
|
package/main.js
CHANGED
|
@@ -39952,7 +39952,7 @@ function buildInputSchema(args, env, options) {
|
|
|
39952
39952
|
// package.json
|
|
39953
39953
|
var package_default = {
|
|
39954
39954
|
name: "@docyrus/docyrus",
|
|
39955
|
-
version: "0.0.
|
|
39955
|
+
version: "0.0.2",
|
|
39956
39956
|
private: false,
|
|
39957
39957
|
description: "Docyrus API CLI",
|
|
39958
39958
|
main: "./main.js",
|
|
@@ -40752,6 +40752,185 @@ function createDsCli(dependencies) {
|
|
|
40752
40752
|
}
|
|
40753
40753
|
|
|
40754
40754
|
// src/commands/discoverCommands.ts
|
|
40755
|
+
var import_promises2 = require("node:fs/promises");
|
|
40756
|
+
var SUPPORTED_HTTP_METHODS2 = [
|
|
40757
|
+
"GET",
|
|
40758
|
+
"POST",
|
|
40759
|
+
"PUT",
|
|
40760
|
+
"PATCH",
|
|
40761
|
+
"DELETE",
|
|
40762
|
+
"HEAD",
|
|
40763
|
+
"OPTIONS",
|
|
40764
|
+
"TRACE"
|
|
40765
|
+
];
|
|
40766
|
+
function isRecord(value) {
|
|
40767
|
+
return typeof value === "object" && value !== null;
|
|
40768
|
+
}
|
|
40769
|
+
function isEnoentError(error48) {
|
|
40770
|
+
return typeof error48 === "object" && error48 !== null && "code" in error48 && error48.code === "ENOENT";
|
|
40771
|
+
}
|
|
40772
|
+
function normalizePathInput(pathValue) {
|
|
40773
|
+
const trimmed = pathValue.trim();
|
|
40774
|
+
if (!trimmed) {
|
|
40775
|
+
throw new UserInputError("Path is required.");
|
|
40776
|
+
}
|
|
40777
|
+
return trimmed.startsWith("/") ? trimmed : `/${trimmed}`;
|
|
40778
|
+
}
|
|
40779
|
+
function buildPathCandidates(pathValue) {
|
|
40780
|
+
const normalized = normalizePathInput(pathValue);
|
|
40781
|
+
const candidates = /* @__PURE__ */ new Set([normalized]);
|
|
40782
|
+
if (normalized === "/v1") {
|
|
40783
|
+
candidates.add("/");
|
|
40784
|
+
} else if (normalized.startsWith("/v1/")) {
|
|
40785
|
+
candidates.add(normalized.substring(3));
|
|
40786
|
+
} else {
|
|
40787
|
+
candidates.add(`/v1${normalized}`);
|
|
40788
|
+
}
|
|
40789
|
+
return Array.from(candidates.values());
|
|
40790
|
+
}
|
|
40791
|
+
function toOutputPath(pathValue) {
|
|
40792
|
+
const normalized = normalizePathInput(pathValue);
|
|
40793
|
+
if (normalized === "/") {
|
|
40794
|
+
return "/v1";
|
|
40795
|
+
}
|
|
40796
|
+
if (normalized.startsWith("/v1/") || normalized === "/v1") {
|
|
40797
|
+
return normalized;
|
|
40798
|
+
}
|
|
40799
|
+
return `/v1${normalized}`;
|
|
40800
|
+
}
|
|
40801
|
+
function parseEndpointSelector(input) {
|
|
40802
|
+
const trimmed = input.trim();
|
|
40803
|
+
if (!trimmed) {
|
|
40804
|
+
throw new UserInputError("Endpoint selector is required.");
|
|
40805
|
+
}
|
|
40806
|
+
const methodPathMatch = trimmed.match(/^\[([a-z]+)\](\/.*)$/i);
|
|
40807
|
+
if (!methodPathMatch) {
|
|
40808
|
+
return {
|
|
40809
|
+
path: trimmed,
|
|
40810
|
+
method: "GET"
|
|
40811
|
+
};
|
|
40812
|
+
}
|
|
40813
|
+
return {
|
|
40814
|
+
method: methodPathMatch[1].toUpperCase(),
|
|
40815
|
+
path: methodPathMatch[2]
|
|
40816
|
+
};
|
|
40817
|
+
}
|
|
40818
|
+
function getPaths(document) {
|
|
40819
|
+
const rawPaths = document.paths;
|
|
40820
|
+
return isRecord(rawPaths) ? rawPaths : {};
|
|
40821
|
+
}
|
|
40822
|
+
function getEntities(document) {
|
|
40823
|
+
const components = isRecord(document.components) ? document.components : null;
|
|
40824
|
+
if (components && isRecord(components.schemas)) {
|
|
40825
|
+
return components.schemas;
|
|
40826
|
+
}
|
|
40827
|
+
const definitions = document.definitions;
|
|
40828
|
+
if (isRecord(definitions)) {
|
|
40829
|
+
return definitions;
|
|
40830
|
+
}
|
|
40831
|
+
return {};
|
|
40832
|
+
}
|
|
40833
|
+
function extractNamespaces(paths) {
|
|
40834
|
+
const namespaces = /* @__PURE__ */ new Set();
|
|
40835
|
+
for (const path3 of Object.keys(paths)) {
|
|
40836
|
+
const segments = path3.split("/").map((item) => item.trim()).filter((item) => item.length > 0);
|
|
40837
|
+
if (segments.length === 0) {
|
|
40838
|
+
continue;
|
|
40839
|
+
}
|
|
40840
|
+
const namespace = segments[0] === "v1" ? segments[1] : segments[0];
|
|
40841
|
+
if (namespace) {
|
|
40842
|
+
namespaces.add(`/v1/${namespace}`);
|
|
40843
|
+
}
|
|
40844
|
+
}
|
|
40845
|
+
return Array.from(namespaces.values()).sort((left, right) => left.localeCompare(right));
|
|
40846
|
+
}
|
|
40847
|
+
function getPathOperation(pathItem, method) {
|
|
40848
|
+
if (!isRecord(pathItem)) {
|
|
40849
|
+
return null;
|
|
40850
|
+
}
|
|
40851
|
+
const normalizedMethod = method.toLowerCase();
|
|
40852
|
+
const operation = pathItem[normalizedMethod];
|
|
40853
|
+
return isRecord(operation) ? operation : null;
|
|
40854
|
+
}
|
|
40855
|
+
function toEndpointMethodEntries(paths, pathFilter) {
|
|
40856
|
+
const entries = [];
|
|
40857
|
+
const sortedPaths = Object.keys(paths).filter(pathFilter).sort((left, right) => left.localeCompare(right));
|
|
40858
|
+
for (const path3 of sortedPaths) {
|
|
40859
|
+
const pathItem = paths[path3];
|
|
40860
|
+
if (!isRecord(pathItem)) {
|
|
40861
|
+
continue;
|
|
40862
|
+
}
|
|
40863
|
+
for (const method of SUPPORTED_HTTP_METHODS2) {
|
|
40864
|
+
const operation = getPathOperation(pathItem, method);
|
|
40865
|
+
if (!operation) {
|
|
40866
|
+
continue;
|
|
40867
|
+
}
|
|
40868
|
+
const descriptionValue = operation.description;
|
|
40869
|
+
const summaryValue = operation.summary;
|
|
40870
|
+
const description = typeof descriptionValue === "string" ? descriptionValue : typeof summaryValue === "string" ? summaryValue : void 0;
|
|
40871
|
+
entries.push({
|
|
40872
|
+
path: toOutputPath(path3),
|
|
40873
|
+
method,
|
|
40874
|
+
description
|
|
40875
|
+
});
|
|
40876
|
+
}
|
|
40877
|
+
}
|
|
40878
|
+
return entries;
|
|
40879
|
+
}
|
|
40880
|
+
function parseOpenApiDocument(raw) {
|
|
40881
|
+
let parsed;
|
|
40882
|
+
try {
|
|
40883
|
+
parsed = JSON.parse(raw);
|
|
40884
|
+
} catch (error48) {
|
|
40885
|
+
throw new UserInputError("Stored OpenAPI spec is invalid JSON. Run 'docyrus discover api' to re-download.", {
|
|
40886
|
+
cause: error48
|
|
40887
|
+
});
|
|
40888
|
+
}
|
|
40889
|
+
if (!isRecord(parsed)) {
|
|
40890
|
+
throw new UserInputError("Stored OpenAPI spec must be a JSON object. Run 'docyrus discover api' to re-download.");
|
|
40891
|
+
}
|
|
40892
|
+
return parsed;
|
|
40893
|
+
}
|
|
40894
|
+
async function loadOpenApiSpec(dependencies, tenantId) {
|
|
40895
|
+
let filePath = dependencies.tenantOpenApiService.getTenantOpenApiFilePath(tenantId);
|
|
40896
|
+
let downloaded = false;
|
|
40897
|
+
let sourceUrl;
|
|
40898
|
+
let content;
|
|
40899
|
+
try {
|
|
40900
|
+
content = await (0, import_promises2.readFile)(filePath, "utf8");
|
|
40901
|
+
} catch (error48) {
|
|
40902
|
+
if (!isEnoentError(error48)) {
|
|
40903
|
+
throw new UserInputError("Failed to read downloaded OpenAPI spec file.", {
|
|
40904
|
+
filePath,
|
|
40905
|
+
cause: error48
|
|
40906
|
+
});
|
|
40907
|
+
}
|
|
40908
|
+
const downloadResult = await dependencies.tenantOpenApiService.downloadTenantOpenApi(tenantId);
|
|
40909
|
+
downloaded = true;
|
|
40910
|
+
sourceUrl = downloadResult.sourceUrl;
|
|
40911
|
+
filePath = downloadResult.filePath;
|
|
40912
|
+
content = await (0, import_promises2.readFile)(filePath, "utf8");
|
|
40913
|
+
}
|
|
40914
|
+
return {
|
|
40915
|
+
filePath,
|
|
40916
|
+
downloaded,
|
|
40917
|
+
sourceUrl,
|
|
40918
|
+
document: parseOpenApiDocument(content)
|
|
40919
|
+
};
|
|
40920
|
+
}
|
|
40921
|
+
async function withActiveTenantSpec(dependencies) {
|
|
40922
|
+
const apiBaseUrl = await dependencies.environmentConfigService.getActiveApiBaseUrl();
|
|
40923
|
+
const activeProfile = await dependencies.authStore.getActiveProfile(apiBaseUrl);
|
|
40924
|
+
if (!activeProfile) {
|
|
40925
|
+
throw new AuthSessionError("No active session found. Run 'docyrus auth login'.");
|
|
40926
|
+
}
|
|
40927
|
+
const spec = await loadOpenApiSpec(dependencies, activeProfile.tenantId);
|
|
40928
|
+
return {
|
|
40929
|
+
apiBaseUrl,
|
|
40930
|
+
activeProfile,
|
|
40931
|
+
spec
|
|
40932
|
+
};
|
|
40933
|
+
}
|
|
40755
40934
|
function createDiscoverCli(dependencies) {
|
|
40756
40935
|
const discoverCli = Cli_exports.create("discover", {
|
|
40757
40936
|
description: "Discovery commands",
|
|
@@ -40778,6 +40957,154 @@ function createDiscoverCli(dependencies) {
|
|
|
40778
40957
|
});
|
|
40779
40958
|
}
|
|
40780
40959
|
});
|
|
40960
|
+
discoverCli.command("namespaces", {
|
|
40961
|
+
description: "List API namespaces from active tenant OpenAPI spec",
|
|
40962
|
+
run: async () => {
|
|
40963
|
+
const { apiBaseUrl, spec } = await withActiveTenantSpec(dependencies);
|
|
40964
|
+
const namespaces = extractNamespaces(getPaths(spec.document));
|
|
40965
|
+
return await injectContext({
|
|
40966
|
+
apiBaseUrl,
|
|
40967
|
+
authStore: dependencies.authStore,
|
|
40968
|
+
payload: {
|
|
40969
|
+
namespaces,
|
|
40970
|
+
count: namespaces.length,
|
|
40971
|
+
specFilePath: spec.filePath,
|
|
40972
|
+
downloaded: spec.downloaded,
|
|
40973
|
+
sourceUrl: spec.sourceUrl
|
|
40974
|
+
}
|
|
40975
|
+
});
|
|
40976
|
+
}
|
|
40977
|
+
});
|
|
40978
|
+
discoverCli.command("path", {
|
|
40979
|
+
description: "List endpoints with method and description for matching path prefix",
|
|
40980
|
+
args: external_exports.object({
|
|
40981
|
+
prefix: external_exports.string().min(1).describe("Path prefix, e.g. /v1/users")
|
|
40982
|
+
}),
|
|
40983
|
+
run: async (context) => {
|
|
40984
|
+
const { apiBaseUrl, spec } = await withActiveTenantSpec(dependencies);
|
|
40985
|
+
const paths = getPaths(spec.document);
|
|
40986
|
+
const candidates = buildPathCandidates(context.args.prefix);
|
|
40987
|
+
const endpoints = toEndpointMethodEntries(
|
|
40988
|
+
paths,
|
|
40989
|
+
(path3) => candidates.some((candidate) => path3.startsWith(candidate))
|
|
40990
|
+
);
|
|
40991
|
+
return await injectContext({
|
|
40992
|
+
apiBaseUrl,
|
|
40993
|
+
authStore: dependencies.authStore,
|
|
40994
|
+
payload: {
|
|
40995
|
+
prefix: context.args.prefix,
|
|
40996
|
+
normalizedPrefixes: candidates,
|
|
40997
|
+
endpoints,
|
|
40998
|
+
count: endpoints.length,
|
|
40999
|
+
specFilePath: spec.filePath,
|
|
41000
|
+
downloaded: spec.downloaded,
|
|
41001
|
+
sourceUrl: spec.sourceUrl
|
|
41002
|
+
}
|
|
41003
|
+
});
|
|
41004
|
+
}
|
|
41005
|
+
});
|
|
41006
|
+
discoverCli.command("endpoint", {
|
|
41007
|
+
description: "Return full endpoint object for a path and HTTP method",
|
|
41008
|
+
args: external_exports.object({
|
|
41009
|
+
selector: external_exports.string().min(1).describe("Endpoint selector, e.g. /v1/users/me or [PUT]/v1/users/me/photo")
|
|
41010
|
+
}),
|
|
41011
|
+
run: async (context) => {
|
|
41012
|
+
const { apiBaseUrl, spec } = await withActiveTenantSpec(dependencies);
|
|
41013
|
+
const paths = getPaths(spec.document);
|
|
41014
|
+
const selector = parseEndpointSelector(context.args.selector);
|
|
41015
|
+
const candidates = buildPathCandidates(selector.path);
|
|
41016
|
+
const resolvedPath = candidates.find((candidate) => candidate in paths);
|
|
41017
|
+
if (!resolvedPath) {
|
|
41018
|
+
throw new UserInputError(`Endpoint '${selector.path}' was not found in downloaded OpenAPI spec.`);
|
|
41019
|
+
}
|
|
41020
|
+
if (!SUPPORTED_HTTP_METHODS2.includes(selector.method)) {
|
|
41021
|
+
throw new UserInputError(`Unsupported HTTP method '${selector.method}'.`);
|
|
41022
|
+
}
|
|
41023
|
+
const operation = getPathOperation(paths[resolvedPath], selector.method);
|
|
41024
|
+
if (!operation) {
|
|
41025
|
+
throw new UserInputError(
|
|
41026
|
+
`Method '${selector.method}' is not available for endpoint '${toOutputPath(resolvedPath)}'.`
|
|
41027
|
+
);
|
|
41028
|
+
}
|
|
41029
|
+
return await injectContext({
|
|
41030
|
+
apiBaseUrl,
|
|
41031
|
+
authStore: dependencies.authStore,
|
|
41032
|
+
payload: {
|
|
41033
|
+
requestedSelector: context.args.selector,
|
|
41034
|
+
method: selector.method,
|
|
41035
|
+
resolvedPath: toOutputPath(resolvedPath),
|
|
41036
|
+
endpoint: operation,
|
|
41037
|
+
specFilePath: spec.filePath,
|
|
41038
|
+
downloaded: spec.downloaded,
|
|
41039
|
+
sourceUrl: spec.sourceUrl
|
|
41040
|
+
}
|
|
41041
|
+
});
|
|
41042
|
+
}
|
|
41043
|
+
});
|
|
41044
|
+
discoverCli.command("entity", {
|
|
41045
|
+
description: "Return full entity object by name",
|
|
41046
|
+
args: external_exports.object({
|
|
41047
|
+
name: external_exports.string().min(1).describe("Entity name, e.g. UserEntity")
|
|
41048
|
+
}),
|
|
41049
|
+
run: async (context) => {
|
|
41050
|
+
const { apiBaseUrl, spec } = await withActiveTenantSpec(dependencies);
|
|
41051
|
+
const entities = getEntities(spec.document);
|
|
41052
|
+
const requestedName = context.args.name.trim();
|
|
41053
|
+
if (!(requestedName in entities)) {
|
|
41054
|
+
throw new UserInputError(`Entity '${context.args.name}' was not found in downloaded OpenAPI spec.`);
|
|
41055
|
+
}
|
|
41056
|
+
return await injectContext({
|
|
41057
|
+
apiBaseUrl,
|
|
41058
|
+
authStore: dependencies.authStore,
|
|
41059
|
+
payload: {
|
|
41060
|
+
entityName: requestedName,
|
|
41061
|
+
entity: entities[requestedName],
|
|
41062
|
+
specFilePath: spec.filePath,
|
|
41063
|
+
downloaded: spec.downloaded,
|
|
41064
|
+
sourceUrl: spec.sourceUrl
|
|
41065
|
+
}
|
|
41066
|
+
});
|
|
41067
|
+
}
|
|
41068
|
+
});
|
|
41069
|
+
discoverCli.command("search", {
|
|
41070
|
+
description: "Search endpoint paths and entity names (endpoint results include method and description)",
|
|
41071
|
+
args: external_exports.object({
|
|
41072
|
+
query: external_exports.string().min(1).describe("One or more comma-separated search strings")
|
|
41073
|
+
}),
|
|
41074
|
+
run: async (context) => {
|
|
41075
|
+
const { apiBaseUrl, spec } = await withActiveTenantSpec(dependencies);
|
|
41076
|
+
const terms = context.args.query.split(",").map((term) => term.trim()).filter((term) => term.length > 0);
|
|
41077
|
+
if (terms.length === 0) {
|
|
41078
|
+
throw new UserInputError("Provide at least one non-empty search term.");
|
|
41079
|
+
}
|
|
41080
|
+
const entityNames = Object.keys(getEntities(spec.document));
|
|
41081
|
+
const pathMap = getPaths(spec.document);
|
|
41082
|
+
const results = terms.map((term) => {
|
|
41083
|
+
const loweredTerm = term.toLowerCase();
|
|
41084
|
+
const matchingEndpoints = toEndpointMethodEntries(
|
|
41085
|
+
pathMap,
|
|
41086
|
+
(path3) => path3.toLowerCase().includes(loweredTerm)
|
|
41087
|
+
);
|
|
41088
|
+
const matchingEntities = entityNames.filter((entityName) => entityName.toLowerCase().includes(loweredTerm));
|
|
41089
|
+
return {
|
|
41090
|
+
term,
|
|
41091
|
+
endpoints: matchingEndpoints,
|
|
41092
|
+
entityNames: matchingEntities.sort((left, right) => left.localeCompare(right))
|
|
41093
|
+
};
|
|
41094
|
+
});
|
|
41095
|
+
return await injectContext({
|
|
41096
|
+
apiBaseUrl,
|
|
41097
|
+
authStore: dependencies.authStore,
|
|
41098
|
+
payload: {
|
|
41099
|
+
terms,
|
|
41100
|
+
results,
|
|
41101
|
+
specFilePath: spec.filePath,
|
|
41102
|
+
downloaded: spec.downloaded,
|
|
41103
|
+
sourceUrl: spec.sourceUrl
|
|
41104
|
+
}
|
|
41105
|
+
});
|
|
41106
|
+
}
|
|
41107
|
+
});
|
|
40781
41108
|
return discoverCli;
|
|
40782
41109
|
}
|
|
40783
41110
|
|
|
@@ -40972,7 +41299,7 @@ var ApiClient = class {
|
|
|
40972
41299
|
};
|
|
40973
41300
|
|
|
40974
41301
|
// src/services/authSession.ts
|
|
40975
|
-
function
|
|
41302
|
+
function isRecord2(value) {
|
|
40976
41303
|
return typeof value === "object" && value !== null;
|
|
40977
41304
|
}
|
|
40978
41305
|
function extractRecordValue(record2, keys) {
|
|
@@ -41271,11 +41598,11 @@ var AuthSessionService = class {
|
|
|
41271
41598
|
fetchFn: this.params.fetchFn
|
|
41272
41599
|
});
|
|
41273
41600
|
const payload = response.data;
|
|
41274
|
-
const dataCandidate =
|
|
41275
|
-
if (!
|
|
41601
|
+
const dataCandidate = isRecord2(payload) && isRecord2(payload.data) ? payload.data : payload;
|
|
41602
|
+
if (!isRecord2(dataCandidate)) {
|
|
41276
41603
|
throw new AuthSessionError("Unable to parse /users/me response.");
|
|
41277
41604
|
}
|
|
41278
|
-
const tenantCandidate =
|
|
41605
|
+
const tenantCandidate = isRecord2(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
|
|
41279
41606
|
const userId = extractString(dataCandidate, ["id", "user_id"]);
|
|
41280
41607
|
const email3 = extractString(dataCandidate, ["email"]);
|
|
41281
41608
|
const tenantId = tenantCandidate ? extractString(tenantCandidate, ["id"]) : extractString(dataCandidate, ["tenant_id", "tenantId"]);
|
|
@@ -41301,13 +41628,13 @@ var AuthSessionService = class {
|
|
|
41301
41628
|
fetchFn: this.params.fetchFn
|
|
41302
41629
|
});
|
|
41303
41630
|
const payload = response.data;
|
|
41304
|
-
const listCandidate = Array.isArray(payload) ? payload :
|
|
41631
|
+
const listCandidate = Array.isArray(payload) ? payload : isRecord2(payload) && Array.isArray(payload.data) ? payload.data : null;
|
|
41305
41632
|
if (!listCandidate) {
|
|
41306
41633
|
throw new AuthSessionError("Unable to parse tenant catalog response.");
|
|
41307
41634
|
}
|
|
41308
41635
|
const mapped = [];
|
|
41309
41636
|
for (const item of listCandidate) {
|
|
41310
|
-
if (!
|
|
41637
|
+
if (!isRecord2(item)) {
|
|
41311
41638
|
continue;
|
|
41312
41639
|
}
|
|
41313
41640
|
const tenantId = extractString(item, ["id", "tenant_id"]);
|
|
@@ -41466,7 +41793,7 @@ var AuthSessionService = class {
|
|
|
41466
41793
|
};
|
|
41467
41794
|
|
|
41468
41795
|
// src/services/authStore.ts
|
|
41469
|
-
var
|
|
41796
|
+
var import_promises3 = require("node:fs/promises");
|
|
41470
41797
|
var import_node_path4 = require("node:path");
|
|
41471
41798
|
function createEmptyState() {
|
|
41472
41799
|
return {
|
|
@@ -41506,7 +41833,7 @@ var AuthStore = class {
|
|
|
41506
41833
|
}
|
|
41507
41834
|
async readState() {
|
|
41508
41835
|
try {
|
|
41509
|
-
const raw = await (0,
|
|
41836
|
+
const raw = await (0, import_promises3.readFile)(this.authFilePath, "utf8");
|
|
41510
41837
|
const parsed = JSON.parse(raw);
|
|
41511
41838
|
const legacy = LegacyAuthSessionSchema.safeParse(parsed);
|
|
41512
41839
|
if (legacy.success) {
|
|
@@ -41543,16 +41870,16 @@ var AuthStore = class {
|
|
|
41543
41870
|
}
|
|
41544
41871
|
const normalized = normalizeState(validated.data);
|
|
41545
41872
|
const directory = (0, import_node_path4.dirname)(this.authFilePath);
|
|
41546
|
-
await (0,
|
|
41873
|
+
await (0, import_promises3.mkdir)(directory, {
|
|
41547
41874
|
recursive: true,
|
|
41548
41875
|
mode: 448
|
|
41549
41876
|
});
|
|
41550
|
-
await (0,
|
|
41877
|
+
await (0, import_promises3.writeFile)(this.authFilePath, `${JSON.stringify(normalized, null, 2)}
|
|
41551
41878
|
`, {
|
|
41552
41879
|
encoding: "utf8",
|
|
41553
41880
|
mode: 384
|
|
41554
41881
|
});
|
|
41555
|
-
await (0,
|
|
41882
|
+
await (0, import_promises3.chmod)(this.authFilePath, 384);
|
|
41556
41883
|
}
|
|
41557
41884
|
async getActiveProfile(apiBaseUrl) {
|
|
41558
41885
|
const normalizedApiBaseUrl = normalizeApiBaseUrl(apiBaseUrl);
|
|
@@ -41749,14 +42076,14 @@ var AuthStore = class {
|
|
|
41749
42076
|
await this.writeState(state);
|
|
41750
42077
|
}
|
|
41751
42078
|
async clear() {
|
|
41752
|
-
await (0,
|
|
42079
|
+
await (0, import_promises3.rm)(this.authFilePath, {
|
|
41753
42080
|
force: true
|
|
41754
42081
|
});
|
|
41755
42082
|
}
|
|
41756
42083
|
};
|
|
41757
42084
|
|
|
41758
42085
|
// src/services/environmentConfig.ts
|
|
41759
|
-
var
|
|
42086
|
+
var import_promises4 = require("node:fs/promises");
|
|
41760
42087
|
var import_node_path5 = require("node:path");
|
|
41761
42088
|
var ENVIRONMENT_ID_ALIASES = {
|
|
41762
42089
|
"local-development": "dev",
|
|
@@ -41843,7 +42170,7 @@ var EnvironmentConfigService = class {
|
|
|
41843
42170
|
}
|
|
41844
42171
|
async readState() {
|
|
41845
42172
|
try {
|
|
41846
|
-
const raw = await (0,
|
|
42173
|
+
const raw = await (0, import_promises4.readFile)(this.configFilePath, "utf8");
|
|
41847
42174
|
const parsed = JSON.parse(raw);
|
|
41848
42175
|
const validated = EnvironmentConfigStateSchema.safeParse(parsed);
|
|
41849
42176
|
if (!validated.success) {
|
|
@@ -41878,16 +42205,16 @@ var EnvironmentConfigService = class {
|
|
|
41878
42205
|
}
|
|
41879
42206
|
const normalized = normalizeState2(validated.data);
|
|
41880
42207
|
const directory = (0, import_node_path5.dirname)(this.configFilePath);
|
|
41881
|
-
await (0,
|
|
42208
|
+
await (0, import_promises4.mkdir)(directory, {
|
|
41882
42209
|
recursive: true,
|
|
41883
42210
|
mode: 448
|
|
41884
42211
|
});
|
|
41885
|
-
await (0,
|
|
42212
|
+
await (0, import_promises4.writeFile)(this.configFilePath, `${JSON.stringify(normalized, null, 2)}
|
|
41886
42213
|
`, {
|
|
41887
42214
|
encoding: "utf8",
|
|
41888
42215
|
mode: 384
|
|
41889
42216
|
});
|
|
41890
|
-
await (0,
|
|
42217
|
+
await (0, import_promises4.chmod)(this.configFilePath, 384);
|
|
41891
42218
|
}
|
|
41892
42219
|
async getActiveEnvironment() {
|
|
41893
42220
|
const state = await this.#readStateWithDefaults();
|
|
@@ -41953,7 +42280,7 @@ var EnvironmentConfigService = class {
|
|
|
41953
42280
|
};
|
|
41954
42281
|
|
|
41955
42282
|
// src/services/tenantOpenApi.ts
|
|
41956
|
-
var
|
|
42283
|
+
var import_promises5 = require("node:fs/promises");
|
|
41957
42284
|
var import_node_path6 = require("node:path");
|
|
41958
42285
|
function resolveSourceUrl(tenantId, template) {
|
|
41959
42286
|
return template.replace("{tenantId}", encodeURIComponent(tenantId));
|
|
@@ -41962,6 +42289,14 @@ var TenantOpenApiService = class {
|
|
|
41962
42289
|
constructor(params) {
|
|
41963
42290
|
this.params = params;
|
|
41964
42291
|
}
|
|
42292
|
+
getTenantOpenApiFilePath(tenantId) {
|
|
42293
|
+
const normalizedTenantId = tenantId.trim();
|
|
42294
|
+
if (!normalizedTenantId) {
|
|
42295
|
+
throw new AuthSessionError("Tenant ID is required to resolve OpenAPI spec path.");
|
|
42296
|
+
}
|
|
42297
|
+
const rootPath = this.params?.rootPath || TENANT_OPENAPI_ROOT_PATH;
|
|
42298
|
+
return (0, import_node_path6.join)(rootPath, normalizedTenantId, "openapi.json");
|
|
42299
|
+
}
|
|
41965
42300
|
async downloadTenantOpenApi(tenantId) {
|
|
41966
42301
|
const normalizedTenantId = tenantId.trim();
|
|
41967
42302
|
if (!normalizedTenantId) {
|
|
@@ -41993,18 +42328,17 @@ var TenantOpenApiService = class {
|
|
|
41993
42328
|
cause: error48
|
|
41994
42329
|
});
|
|
41995
42330
|
}
|
|
41996
|
-
const
|
|
41997
|
-
|
|
41998
|
-
await (0, import_promises4.mkdir)((0, import_node_path6.dirname)(filePath), {
|
|
42331
|
+
const filePath = this.getTenantOpenApiFilePath(normalizedTenantId);
|
|
42332
|
+
await (0, import_promises5.mkdir)((0, import_node_path6.dirname)(filePath), {
|
|
41999
42333
|
recursive: true,
|
|
42000
42334
|
mode: 448
|
|
42001
42335
|
});
|
|
42002
|
-
await (0,
|
|
42336
|
+
await (0, import_promises5.writeFile)(filePath, `${JSON.stringify(parsedContent, null, 2)}
|
|
42003
42337
|
`, {
|
|
42004
42338
|
encoding: "utf8",
|
|
42005
42339
|
mode: 384
|
|
42006
42340
|
});
|
|
42007
|
-
await (0,
|
|
42341
|
+
await (0, import_promises5.chmod)(filePath, 384);
|
|
42008
42342
|
return {
|
|
42009
42343
|
tenantId: normalizedTenantId,
|
|
42010
42344
|
sourceUrl,
|
|
@@ -42021,6 +42355,11 @@ var ROOT_HELP_COMMANDS = [
|
|
|
42021
42355
|
{ command: "auth accounts list", description: "List saved user accounts" },
|
|
42022
42356
|
{ command: "auth tenants use --tenantId <id>", description: "Switch active tenant for selected user" },
|
|
42023
42357
|
{ command: "discover api", description: "Download active tenant OpenAPI spec" },
|
|
42358
|
+
{ command: "discover namespaces", description: "List namespaces from tenant OpenAPI spec" },
|
|
42359
|
+
{ command: "discover path <prefix>", description: "List endpoint paths by prefix" },
|
|
42360
|
+
{ command: "discover endpoint <path>", description: "Show endpoint object by exact path" },
|
|
42361
|
+
{ command: "discover entity <name>", description: "Show entity object by name" },
|
|
42362
|
+
{ command: "discover search <terms>", description: "Search in endpoint paths and entity names" },
|
|
42024
42363
|
{ command: "ds list <appSlug> <dataSourceSlug>", description: "List data source items" },
|
|
42025
42364
|
{ command: "apps list", description: "List apps" },
|
|
42026
42365
|
{ command: "curl <path>", description: "Send arbitrary API requests" }
|