@docyrus/docyrus 0.0.15 → 0.0.16

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.
Files changed (3) hide show
  1. package/main.js +165 -39
  2. package/main.js.map +3 -3
  3. package/package.json +1 -1
package/main.js CHANGED
@@ -124678,7 +124678,7 @@ function buildInputSchema(args, env2, options2) {
124678
124678
  // package.json
124679
124679
  var package_default = {
124680
124680
  name: "@docyrus/docyrus",
124681
- version: "0.0.15",
124681
+ version: "0.0.16",
124682
124682
  private: false,
124683
124683
  description: "Docyrus API CLI",
124684
124684
  main: "./main.js",
@@ -126227,7 +126227,7 @@ function parseOpenApiDocument(raw) {
126227
126227
  }
126228
126228
  return parsed;
126229
126229
  }
126230
- async function loadOpenApiSpec(dependencies, tenantId) {
126230
+ async function loadOpenApiSpec(dependencies, tenantId, options2) {
126231
126231
  let filePath = dependencies.tenantOpenApiService.getTenantOpenApiFilePath(tenantId);
126232
126232
  let downloaded = false;
126233
126233
  let sourceUrl;
@@ -126241,7 +126241,7 @@ async function loadOpenApiSpec(dependencies, tenantId) {
126241
126241
  cause: error48
126242
126242
  });
126243
126243
  }
126244
- const downloadResult = await dependencies.tenantOpenApiService.downloadTenantOpenApi(tenantId);
126244
+ const downloadResult = await dependencies.tenantOpenApiService.downloadTenantOpenApi(tenantId, options2);
126245
126245
  downloaded = true;
126246
126246
  sourceUrl = downloadResult.sourceUrl;
126247
126247
  filePath = downloadResult.filePath;
@@ -126260,11 +126260,15 @@ async function withActiveTenantSpec(dependencies) {
126260
126260
  if (!activeProfile) {
126261
126261
  throw new AuthSessionError("No active session found. Run 'docyrus auth login'.");
126262
126262
  }
126263
- const spec = await loadOpenApiSpec(dependencies, activeProfile.tenantId);
126263
+ const authSessionService = dependencies.createAuthSessionService(apiBaseUrl);
126264
+ const authToken = await authSessionService.getValidAccessToken();
126264
126265
  return {
126265
126266
  apiBaseUrl,
126266
126267
  activeProfile,
126267
- spec
126268
+ spec: await loadOpenApiSpec(dependencies, activeProfile.tenantId, {
126269
+ apiBaseUrl,
126270
+ authToken
126271
+ })
126268
126272
  };
126269
126273
  }
126270
126274
  function createDiscoverCli(dependencies) {
@@ -126280,7 +126284,12 @@ function createDiscoverCli(dependencies) {
126280
126284
  if (!activeProfile) {
126281
126285
  throw new AuthSessionError("No active session found. Run 'docyrus auth login'.");
126282
126286
  }
126283
- const downloaded = await dependencies.tenantOpenApiService.downloadTenantOpenApi(activeProfile.tenantId);
126287
+ const authSessionService = dependencies.createAuthSessionService(apiBaseUrl);
126288
+ const authToken = await authSessionService.getValidAccessToken();
126289
+ const downloaded = await dependencies.tenantOpenApiService.downloadTenantOpenApi(activeProfile.tenantId, {
126290
+ apiBaseUrl,
126291
+ authToken
126292
+ });
126284
126293
  return await injectContext({
126285
126294
  apiBaseUrl,
126286
126295
  authStore: dependencies.authStore,
@@ -126753,6 +126762,65 @@ function requireNonEmptyObject(payload, label) {
126753
126762
  throw new UserInputError(`${label} payload is empty. Provide flags, --data, or --from-file.`);
126754
126763
  }
126755
126764
  }
126765
+ function isRecord5(value) {
126766
+ return typeof value === "object" && value !== null && !Array.isArray(value);
126767
+ }
126768
+ function normalizeBatchUpdateFieldItem(item) {
126769
+ if (!isRecord5(item)) {
126770
+ return item;
126771
+ }
126772
+ const normalized = {
126773
+ ...item
126774
+ };
126775
+ if (!("fieldId" in normalized) && typeof normalized.id === "string") {
126776
+ normalized.fieldId = normalized.id;
126777
+ }
126778
+ if (!("readOnly" in normalized) && "read_only" in normalized) {
126779
+ normalized.readOnly = normalized.read_only;
126780
+ }
126781
+ if (!("defaultValue" in normalized) && "default_value" in normalized) {
126782
+ normalized.defaultValue = normalized.default_value;
126783
+ }
126784
+ if (!("relationDataSourceId" in normalized) && "relation_data_source_id" in normalized) {
126785
+ normalized.relationDataSourceId = normalized.relation_data_source_id;
126786
+ }
126787
+ if (!("editorOptions" in normalized) && "options" in normalized) {
126788
+ normalized.editorOptions = normalized.options;
126789
+ }
126790
+ return normalized;
126791
+ }
126792
+ function normalizeBatchUpdateFieldsPayload(payload) {
126793
+ const fields = payload.fields;
126794
+ if (!Array.isArray(fields)) {
126795
+ return payload;
126796
+ }
126797
+ return {
126798
+ ...payload,
126799
+ fields: fields.map((item) => normalizeBatchUpdateFieldItem(item))
126800
+ };
126801
+ }
126802
+ function normalizeUpdateEnumItem(item) {
126803
+ if (!isRecord5(item)) {
126804
+ return item;
126805
+ }
126806
+ if (!("enumId" in item) && typeof item.id === "string") {
126807
+ return {
126808
+ ...item,
126809
+ enumId: item.id
126810
+ };
126811
+ }
126812
+ return item;
126813
+ }
126814
+ function normalizeUpdateEnumsPayload(payload) {
126815
+ const enums = payload.enums;
126816
+ if (!Array.isArray(enums)) {
126817
+ return payload;
126818
+ }
126819
+ return {
126820
+ ...payload,
126821
+ enums: enums.map((item) => normalizeUpdateEnumItem(item))
126822
+ };
126823
+ }
126756
126824
  function createStudioCli(dependencies) {
126757
126825
  const studioCli = Cli_exports.create("studio", {
126758
126826
  description: "Studio (dev app data source CRUD) commands",
@@ -127249,10 +127317,11 @@ function createStudioCli(dependencies) {
127249
127317
  }),
127250
127318
  "fields"
127251
127319
  );
127320
+ const normalizedPayload = normalizeBatchUpdateFieldsPayload(payload);
127252
127321
  const response = await studio.apiClient.request({
127253
127322
  method: "PATCH",
127254
127323
  path: `/dev/apps/${appId}/data-sources/${dataSourceId}/fields/batch`,
127255
- body: payload
127324
+ body: normalizedPayload
127256
127325
  });
127257
127326
  return await wrapStudioPayload(studio.apiBaseUrl, dependencies, response.data);
127258
127327
  }
@@ -127413,10 +127482,11 @@ function createStudioCli(dependencies) {
127413
127482
  }),
127414
127483
  "enums"
127415
127484
  );
127485
+ const normalizedPayload = normalizeUpdateEnumsPayload(payload);
127416
127486
  const response = await studio.apiClient.request({
127417
127487
  method: "PATCH",
127418
127488
  path: `/dev/apps/${appId}/data-sources/${dataSourceId}/fields/${fieldId}/enums`,
127419
- body: payload
127489
+ body: normalizedPayload
127420
127490
  });
127421
127491
  return await wrapStudioPayload(studio.apiBaseUrl, dependencies, response.data);
127422
127492
  }
@@ -127750,7 +127820,7 @@ var ApiClient = class {
127750
127820
 
127751
127821
  // src/services/authSession.ts
127752
127822
  var DEFAULT_MANUAL_ACCESS_TOKEN_EXPIRY_SECONDS = 3600;
127753
- function isRecord5(value) {
127823
+ function isRecord6(value) {
127754
127824
  return typeof value === "object" && value !== null;
127755
127825
  }
127756
127826
  function extractRecordValue(record2, keys) {
@@ -128063,11 +128133,11 @@ var AuthSessionService = class {
128063
128133
  fetchFn: this.params.fetchFn
128064
128134
  });
128065
128135
  const payload = response.data;
128066
- const dataCandidate = isRecord5(payload) && isRecord5(payload.data) ? payload.data : payload;
128067
- if (!isRecord5(dataCandidate)) {
128136
+ const dataCandidate = isRecord6(payload) && isRecord6(payload.data) ? payload.data : payload;
128137
+ if (!isRecord6(dataCandidate)) {
128068
128138
  throw new AuthSessionError("Unable to parse /users/me response.");
128069
128139
  }
128070
- const tenantCandidate = isRecord5(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
128140
+ const tenantCandidate = isRecord6(dataCandidate.tenant) ? dataCandidate.tenant : void 0;
128071
128141
  const userId = extractString3(dataCandidate, ["id", "user_id"]);
128072
128142
  const email3 = extractString3(dataCandidate, ["email"]);
128073
128143
  const tenantId = tenantCandidate ? extractString3(tenantCandidate, ["id"]) : extractString3(dataCandidate, ["tenant_id", "tenantId"]);
@@ -128093,13 +128163,13 @@ var AuthSessionService = class {
128093
128163
  fetchFn: this.params.fetchFn
128094
128164
  });
128095
128165
  const payload = response.data;
128096
- const listCandidate = Array.isArray(payload) ? payload : isRecord5(payload) && Array.isArray(payload.data) ? payload.data : null;
128166
+ const listCandidate = Array.isArray(payload) ? payload : isRecord6(payload) && Array.isArray(payload.data) ? payload.data : null;
128097
128167
  if (!listCandidate) {
128098
128168
  throw new AuthSessionError("Unable to parse tenant catalog response.");
128099
128169
  }
128100
128170
  const mapped = [];
128101
128171
  for (const item of listCandidate) {
128102
- if (!isRecord5(item)) {
128172
+ if (!isRecord6(item)) {
128103
128173
  continue;
128104
128174
  }
128105
128175
  const tenantId = extractString3(item, ["id", "tenant_id"]);
@@ -128781,10 +128851,66 @@ var import_node_path9 = require("node:path");
128781
128851
  function resolveSourceUrl(tenantId, template) {
128782
128852
  return template.replace("{tenantId}", encodeURIComponent(tenantId));
128783
128853
  }
128854
+ async function parseOpenApiJsonResponse(response, params) {
128855
+ const content = await response.text();
128856
+ let parsedContent;
128857
+ try {
128858
+ parsedContent = JSON.parse(content);
128859
+ } catch (error48) {
128860
+ throw new AuthSessionError("Downloaded tenant OpenAPI spec is invalid JSON.", {
128861
+ tenantId: params.tenantId,
128862
+ sourceUrl: params.sourceUrl,
128863
+ cause: error48
128864
+ });
128865
+ }
128866
+ return parsedContent;
128867
+ }
128784
128868
  var TenantOpenApiService = class {
128785
128869
  constructor(params) {
128786
128870
  this.params = params;
128787
128871
  }
128872
+ async #writeOpenApiFile(tenantId, parsedContent) {
128873
+ const filePath = this.getTenantOpenApiFilePath(tenantId);
128874
+ await (0, import_promises7.mkdir)((0, import_node_path9.dirname)(filePath), {
128875
+ recursive: true,
128876
+ mode: 448
128877
+ });
128878
+ await (0, import_promises7.writeFile)(filePath, `${JSON.stringify(parsedContent, null, 2)}
128879
+ `, {
128880
+ encoding: "utf8",
128881
+ mode: 384
128882
+ });
128883
+ await (0, import_promises7.chmod)(filePath, 384);
128884
+ return filePath;
128885
+ }
128886
+ async #generateTenantOpenApiViaAuthenticatedEndpoint(tenantId, options2) {
128887
+ if (!options2.apiBaseUrl || !options2.authToken) {
128888
+ throw new AuthSessionError("Failed to download tenant OpenAPI spec.", {
128889
+ tenantId,
128890
+ reason: "OpenAPI file is missing and no authenticated fallback request could be made."
128891
+ });
128892
+ }
128893
+ const apiUrl = `${normalizeApiBaseUrl(options2.apiBaseUrl)}/api/openapi.json`;
128894
+ const response = await (this.params?.fetchFn || fetch)(apiUrl, {
128895
+ method: "GET",
128896
+ headers: {
128897
+ Accept: "application/json",
128898
+ Authorization: `Bearer ${options2.authToken}`
128899
+ }
128900
+ });
128901
+ if (!response.ok) {
128902
+ throw new AuthSessionError("Failed to generate tenant OpenAPI spec via authenticated endpoint.", {
128903
+ tenantId,
128904
+ sourceUrl: apiUrl,
128905
+ status: response.status,
128906
+ statusText: response.statusText
128907
+ });
128908
+ }
128909
+ return await parseOpenApiJsonResponse(response, {
128910
+ tenantId,
128911
+ sourceUrl: apiUrl
128912
+ });
128913
+ }
128788
128914
  getTenantOpenApiFilePath(tenantId) {
128789
128915
  const normalizedTenantId = tenantId.trim();
128790
128916
  if (!normalizedTenantId) {
@@ -128793,7 +128919,7 @@ var TenantOpenApiService = class {
128793
128919
  const rootPath = this.params?.rootPath || TENANT_OPENAPI_ROOT_PATH;
128794
128920
  return (0, import_node_path9.join)(rootPath, normalizedTenantId, "openapi.json");
128795
128921
  }
128796
- async downloadTenantOpenApi(tenantId) {
128922
+ async downloadTenantOpenApi(tenantId, options2 = {}) {
128797
128923
  const normalizedTenantId = tenantId.trim();
128798
128924
  if (!normalizedTenantId) {
128799
128925
  throw new AuthSessionError("Tenant ID is required to download OpenAPI spec.");
@@ -128806,35 +128932,34 @@ var TenantOpenApiService = class {
128806
128932
  method: "GET"
128807
128933
  });
128808
128934
  if (!response.ok) {
128809
- throw new AuthSessionError("Failed to download tenant OpenAPI spec.", {
128810
- tenantId: normalizedTenantId,
128811
- sourceUrl,
128812
- status: response.status,
128813
- statusText: response.statusText
128935
+ if (response.status !== 404) {
128936
+ throw new AuthSessionError("Failed to download tenant OpenAPI spec.", {
128937
+ tenantId: normalizedTenantId,
128938
+ sourceUrl,
128939
+ status: response.status,
128940
+ statusText: response.statusText
128941
+ });
128942
+ }
128943
+ const generatedSpec = await this.#generateTenantOpenApiViaAuthenticatedEndpoint(normalizedTenantId, options2);
128944
+ const retryResponse = await (this.params?.fetchFn || fetch)(sourceUrl, {
128945
+ method: "GET"
128814
128946
  });
128815
- }
128816
- const content = await response.text();
128817
- let parsedContent;
128818
- try {
128819
- parsedContent = JSON.parse(content);
128820
- } catch (error48) {
128821
- throw new AuthSessionError("Downloaded tenant OpenAPI spec is invalid JSON.", {
128947
+ const parsedContent2 = retryResponse.ok ? await parseOpenApiJsonResponse(retryResponse, {
128948
+ tenantId: normalizedTenantId,
128949
+ sourceUrl
128950
+ }) : generatedSpec;
128951
+ const filePath2 = await this.#writeOpenApiFile(normalizedTenantId, parsedContent2);
128952
+ return {
128822
128953
  tenantId: normalizedTenantId,
128823
128954
  sourceUrl,
128824
- cause: error48
128825
- });
128955
+ filePath: filePath2
128956
+ };
128826
128957
  }
128827
- const filePath = this.getTenantOpenApiFilePath(normalizedTenantId);
128828
- await (0, import_promises7.mkdir)((0, import_node_path9.dirname)(filePath), {
128829
- recursive: true,
128830
- mode: 448
128831
- });
128832
- await (0, import_promises7.writeFile)(filePath, `${JSON.stringify(parsedContent, null, 2)}
128833
- `, {
128834
- encoding: "utf8",
128835
- mode: 384
128958
+ const parsedContent = await parseOpenApiJsonResponse(response, {
128959
+ tenantId: normalizedTenantId,
128960
+ sourceUrl
128836
128961
  });
128837
- await (0, import_promises7.chmod)(filePath, 384);
128962
+ const filePath = await this.#writeOpenApiFile(normalizedTenantId, parsedContent);
128838
128963
  return {
128839
128964
  tenantId: normalizedTenantId,
128840
128965
  sourceUrl,
@@ -128937,6 +129062,7 @@ function createDocyrusCli(params) {
128937
129062
  }));
128938
129063
  cli2.command(createDiscoverCli({
128939
129064
  environmentConfigService,
129065
+ createAuthSessionService,
128940
129066
  authStore,
128941
129067
  tenantOpenApiService
128942
129068
  }));