@stackgenhq/backstage-plugin-stackgen-backend 0.3.6-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +485 -0
  2. package/config.d.ts +39 -0
  3. package/dist/actions/core/assign_project_members_action.cjs.js +227 -0
  4. package/dist/actions/core/assign_project_members_action.cjs.js.map +1 -0
  5. package/dist/actions/core/create_appstack_action.cjs.js +953 -0
  6. package/dist/actions/core/create_appstack_action.cjs.js.map +1 -0
  7. package/dist/actions/core/create_project_action.cjs.js +243 -0
  8. package/dist/actions/core/create_project_action.cjs.js.map +1 -0
  9. package/dist/actions/core/download_iac_action.cjs.js +133 -0
  10. package/dist/actions/core/download_iac_action.cjs.js.map +1 -0
  11. package/dist/actions/core/set_environment_variable_values_action.cjs.js +121 -0
  12. package/dist/actions/core/set_environment_variable_values_action.cjs.js.map +1 -0
  13. package/dist/actions/core/set_state_backend_action.cjs.js +174 -0
  14. package/dist/actions/core/set_state_backend_action.cjs.js.map +1 -0
  15. package/dist/actions/exporter/export_iac_to_git_action.cjs.js +290 -0
  16. package/dist/actions/exporter/export_iac_to_git_action.cjs.js.map +1 -0
  17. package/dist/actions/exporter/list_vault_secrets_action.cjs.js +39 -0
  18. package/dist/actions/exporter/list_vault_secrets_action.cjs.js.map +1 -0
  19. package/dist/config/constants.cjs.js +23 -0
  20. package/dist/config/constants.cjs.js.map +1 -0
  21. package/dist/exporter/exportOverrides.cjs.js +27 -0
  22. package/dist/exporter/exportOverrides.cjs.js.map +1 -0
  23. package/dist/exporter/gitExporterConfigHttp.cjs.js +105 -0
  24. package/dist/exporter/gitExporterConfigHttp.cjs.js.map +1 -0
  25. package/dist/exporter/http.cjs.js +14 -0
  26. package/dist/exporter/http.cjs.js.map +1 -0
  27. package/dist/exporter/paths.cjs.js +25 -0
  28. package/dist/exporter/paths.cjs.js.map +1 -0
  29. package/dist/exporter/projectGitExporterTemplate.cjs.js +62 -0
  30. package/dist/exporter/projectGitExporterTemplate.cjs.js.map +1 -0
  31. package/dist/exporter/topologyResolve.cjs.js +71 -0
  32. package/dist/exporter/topologyResolve.cjs.js.map +1 -0
  33. package/dist/index.cjs.js +31 -0
  34. package/dist/index.cjs.js.map +1 -0
  35. package/dist/index.d.ts +224 -0
  36. package/dist/lib/extractArchive.cjs.js +62 -0
  37. package/dist/lib/extractArchive.cjs.js.map +1 -0
  38. package/dist/modules/stackgenExporterScaffolderModule.cjs.js +29 -0
  39. package/dist/modules/stackgenExporterScaffolderModule.cjs.js.map +1 -0
  40. package/dist/modules/stackgenUiProxiesModule.cjs.js +366 -0
  41. package/dist/modules/stackgenUiProxiesModule.cjs.js.map +1 -0
  42. package/dist/plugin/plugin.cjs.js +136 -0
  43. package/dist/plugin/plugin.cjs.js.map +1 -0
  44. package/dist/plugin/router.cjs.js +341 -0
  45. package/dist/plugin/router.cjs.js.map +1 -0
  46. package/dist/services/MappingsService/mappingsService.cjs.js +149 -0
  47. package/dist/services/MappingsService/mappingsService.cjs.js.map +1 -0
  48. package/dist/services/StackgenService/stackgenService.cjs.js +267 -0
  49. package/dist/services/StackgenService/stackgenService.cjs.js.map +1 -0
  50. package/dist/utils/api-objects.cjs.js +205 -0
  51. package/dist/utils/api-objects.cjs.js.map +1 -0
  52. package/dist/vendor/stackgen-api-client/index.cjs.js +47681 -0
  53. package/dist/vendor/stackgen-api-client/index.cjs.js.map +1 -0
  54. package/migrations/20250131055302_init.js +24 -0
  55. package/migrations/20250305123456_alter_type_associations.js +23 -0
  56. package/package.json +86 -0
  57. package/templates/appstack-configure-environment.yaml +81 -0
  58. package/templates/appstack-from-template.yaml +76 -0
  59. package/templates/appstack-with-modules.yaml +69 -0
  60. package/templates/appstack-with-resources.yaml +81 -0
  61. package/templates/export-iac.yaml +97 -0
  62. package/templates/full-infra-setup.yaml +156 -0
  63. package/templates/git_export_exporter_multi_scm.yaml +123 -0
  64. package/templates/project-advanced.yaml +77 -0
  65. package/templates/project-basic.yaml +39 -0
  66. package/templates/project-with-members.yaml +86 -0
@@ -0,0 +1,267 @@
1
+ 'use strict';
2
+
3
+ var errors = require('@backstage/errors');
4
+ var apiObjects = require('../../utils/api-objects.cjs.js');
5
+
6
+ class StackGenService {
7
+ allowedTeams;
8
+ logger;
9
+ stackgenApis;
10
+ constructor(config, logger) {
11
+ this.stackgenApis = apiObjects.getStackgenApiObjects(config);
12
+ this.logger = logger;
13
+ this.allowedTeams = config.getOptionalString("stackGen.allowedTeams")?.split(",").map((teamId) => teamId.trim()) || [];
14
+ if (!this.stackgenApis.token) {
15
+ throw new errors.InputError(
16
+ "StackGen API Token is missing. Set stackGen.apiToken"
17
+ );
18
+ }
19
+ }
20
+ async mapErrorToProxyResponse(error) {
21
+ const parsedError = await apiObjects.readClientError(error);
22
+ if (parsedError.status !== 500 || parsedError.text !== String(error)) {
23
+ return {
24
+ data: parsedError.body,
25
+ status: parsedError.status,
26
+ headers: { "content-type": "application/json" },
27
+ isError: true
28
+ };
29
+ }
30
+ this.logger.error(`Proxy request failed:${error}`);
31
+ return {
32
+ data: {
33
+ message: "error in connecting to stackGen server"
34
+ },
35
+ status: 500,
36
+ headers: { "content-type": "application/json" },
37
+ isError: true
38
+ };
39
+ }
40
+ async apiResponseToProxyResponse(request, successStatus = 200) {
41
+ try {
42
+ const data = await request();
43
+ return {
44
+ data,
45
+ status: successStatus,
46
+ headers: { "content-type": "application/json" },
47
+ isError: false
48
+ };
49
+ } catch (error) {
50
+ return this.mapErrorToProxyResponse(error);
51
+ }
52
+ }
53
+ async getAllowedTeams() {
54
+ try {
55
+ const allTeamsResponse = await this.listTeams();
56
+ if (allTeamsResponse.isError) {
57
+ throw new Error("error fetching teams from stackGen");
58
+ }
59
+ const allTeams = Array.isArray(allTeamsResponse.data) ? allTeamsResponse.data : [];
60
+ if (this.allowedTeams.length > 0) {
61
+ const allowedTeams = allTeams.filter(
62
+ (team) => this.allowedTeams.includes(team.id)
63
+ );
64
+ if (allowedTeams.length === 0) {
65
+ throw new Error(`Unauthorized: No allowed teams found in StackGen.`);
66
+ }
67
+ return allowedTeams;
68
+ }
69
+ return allTeams;
70
+ } catch (error) {
71
+ this.logger.error(`Error fetching allowed teams:${error}`);
72
+ throw error;
73
+ }
74
+ }
75
+ async createOrUpdateAppstack(appStack) {
76
+ try {
77
+ if (this.allowedTeams.length > 0 && !this.allowedTeams.includes(appStack.appstackTeamId)) {
78
+ throw new Error(`Unauthorized`);
79
+ }
80
+ const apiPayload = {
81
+ name: appStack.appstackName,
82
+ coreConfig: {
83
+ provider: appStack.cloudProvider,
84
+ targetCompute: appStack.targetCompute ?? void 0
85
+ },
86
+ resources: appStack.resources || [],
87
+ teamId: appStack.appstackTeamId
88
+ };
89
+ const requestUrl = `${this.stackgenApis.baseUrl}/stackgen/v1/appstacks`;
90
+ this.logger.info(`Stackgen: Requesting ${requestUrl}`);
91
+ try {
92
+ const response = await apiObjects.executeFetchRequest(
93
+ this.stackgenApis.fetchApi,
94
+ requestUrl,
95
+ {
96
+ method: "POST",
97
+ headers: { "Content-Type": "application/json" },
98
+ body: JSON.stringify(apiPayload)
99
+ }
100
+ );
101
+ return {
102
+ data: response.data,
103
+ status: response.status,
104
+ headers: {
105
+ "content-type": response.headers["content-type"] ?? "application/json"
106
+ },
107
+ isError: !response.ok
108
+ };
109
+ } catch (error) {
110
+ return this.mapErrorToProxyResponse(error);
111
+ }
112
+ } catch (error) {
113
+ this.logger.error(`error creating/updating appstack: ${error}`);
114
+ throw new Error(
115
+ error instanceof Error ? error.message : "Failed to create or update appstack in StackGen"
116
+ );
117
+ }
118
+ }
119
+ async getAppStacks() {
120
+ try {
121
+ return await this.apiResponseToProxyResponse(
122
+ () => this.stackgenApis.integrationsAppstackApiObj.listAppStacks({})
123
+ );
124
+ } catch (error) {
125
+ this.logger.error(`Error fetching appstacks: ${error}`);
126
+ throw new Error("Failed to retrieve appstacks from StackGen");
127
+ }
128
+ }
129
+ async listTeams() {
130
+ try {
131
+ return await this.apiResponseToProxyResponse(
132
+ () => this.stackgenApis.integrationsTeamApiObj.listTeams({})
133
+ );
134
+ } catch (error) {
135
+ this.logger.error(`error fetching teams:${error}`);
136
+ throw new Error("Failed to retrieve teams from StackGen");
137
+ }
138
+ }
139
+ async listAppstacksByTeamsID(teamId) {
140
+ if (!teamId) {
141
+ throw new errors.InputError("Team ID is required to fetch appstacks.");
142
+ }
143
+ try {
144
+ return await this.apiResponseToProxyResponse(
145
+ () => this.stackgenApis.integrationsAppstackApiObj.listProjectAppStacks({
146
+ projectId: teamId
147
+ })
148
+ );
149
+ } catch (error) {
150
+ this.logger.error(
151
+ `error fetching appstacks for team ${teamId}: ${error}`
152
+ );
153
+ throw new Error(`Failed to retrieve appstacks for team ID ${teamId}`);
154
+ }
155
+ }
156
+ async listTemplateAppstacks() {
157
+ const pageSize = 100;
158
+ const maxOffset = 1e3;
159
+ const allAppstacks = [];
160
+ let offset = 0;
161
+ let reportedTotal;
162
+ try {
163
+ for (; ; ) {
164
+ const pageOffset = offset;
165
+ const response = await this.apiResponseToProxyResponse(
166
+ () => this.stackgenApis.appStacksApiObj.getTemplateAppstacks({
167
+ limit: pageSize,
168
+ offset: pageOffset
169
+ })
170
+ );
171
+ if (response.isError || response.status >= 400) {
172
+ return response;
173
+ }
174
+ const page = response.data ?? {};
175
+ const rows = Array.isArray(page.appstacks) ? page.appstacks : [];
176
+ allAppstacks.push(...rows);
177
+ if (typeof page.total === "number") {
178
+ reportedTotal = page.total;
179
+ }
180
+ if (rows.length < pageSize) {
181
+ break;
182
+ }
183
+ if (typeof reportedTotal === "number" && allAppstacks.length >= reportedTotal) {
184
+ break;
185
+ }
186
+ offset += pageSize;
187
+ if (offset > maxOffset) {
188
+ this.logger.warn(
189
+ `Stopped paging template-appstacks after offset ${offset} (collected ${allAppstacks.length})`
190
+ );
191
+ break;
192
+ }
193
+ }
194
+ return {
195
+ data: {
196
+ appstacks: allAppstacks,
197
+ total: reportedTotal ?? allAppstacks.length,
198
+ limit: allAppstacks.length,
199
+ offset: 0
200
+ },
201
+ status: 200,
202
+ headers: { "Content-Type": "application/json" },
203
+ isError: false
204
+ };
205
+ } catch (error) {
206
+ this.logger.error(`Error fetching template appstacks: ${error}`);
207
+ throw new Error("Failed to retrieve template appstacks from StackGen");
208
+ }
209
+ }
210
+ async getStackgenResourceTypes() {
211
+ try {
212
+ const response = await this.apiResponseToProxyResponse(
213
+ () => this.stackgenApis.integrationsResourceApiObj.listSupportedResources()
214
+ );
215
+ if (response.isError) {
216
+ throw new Error("error fetching resource types from StackGen");
217
+ }
218
+ return response;
219
+ } catch (error) {
220
+ this.logger.error(`error fetching resource types: ${error}`);
221
+ throw new Error("Failed to retrieve resource types from StackGen");
222
+ }
223
+ }
224
+ async getStackgenResourceTypesByTeamID(teamId) {
225
+ if (!teamId) {
226
+ throw new errors.InputError("Team ID is required to fetch resource types.");
227
+ }
228
+ try {
229
+ const response = await this.apiResponseToProxyResponse(
230
+ () => this.stackgenApis.integrationsResourceApiObj.listProjectSupportedResources(
231
+ {
232
+ projectId: teamId
233
+ }
234
+ )
235
+ );
236
+ if (response.isError) {
237
+ throw new Error(
238
+ `error fetching resource types for team ${teamId} from StackGen`
239
+ );
240
+ }
241
+ return response;
242
+ } catch (error) {
243
+ this.logger.error(
244
+ `error fetching resource types for team ${teamId}: ${error}`
245
+ );
246
+ throw new Error(
247
+ `Failed to retrieve resource types for team ID ${teamId}`
248
+ );
249
+ }
250
+ }
251
+ async createProject(project) {
252
+ try {
253
+ return await this.apiResponseToProxyResponse(
254
+ () => this.stackgenApis.integrationsProjectApiObj.createProject({
255
+ projectRequest: project
256
+ }),
257
+ 201
258
+ );
259
+ } catch (error) {
260
+ this.logger.error(`Error creating project: ${error}`);
261
+ throw new Error("Failed to create project in StackGen");
262
+ }
263
+ }
264
+ }
265
+
266
+ exports.StackGenService = StackGenService;
267
+ //# sourceMappingURL=stackgenService.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stackgenService.cjs.js","sources":["../../../src/services/StackgenService/stackgenService.ts"],"sourcesContent":["import { Config } from \"@backstage/config\";\nimport { InputError } from \"@backstage/errors\";\nimport {\n StackgenAPI,\n AppstackTeam,\n CreateOrUpdateAppstackRequest,\n CreateProjectRequest,\n ProxyResponse,\n} from \"./types\";\nimport { LoggerService } from \"@backstage/backend-plugin-api\";\nimport {\n executeFetchRequest,\n getStackgenApiObjects,\n readClientError,\n} from \"../../utils/api-objects\";\n\nexport class StackGenService implements StackgenAPI {\n private readonly allowedTeams: string[];\n private readonly logger: LoggerService;\n private readonly stackgenApis: ReturnType<typeof getStackgenApiObjects>;\n\n constructor(config: Config, logger: LoggerService) {\n this.stackgenApis = getStackgenApiObjects(config);\n this.logger = logger;\n this.allowedTeams =\n config.getOptionalString(\"stackGen.allowedTeams\")?.split(\",\").map((teamId) => teamId.trim()) || [];\n\n if (!this.stackgenApis.token) {\n throw new InputError(\n \"StackGen API Token is missing. Set stackGen.apiToken\"\n );\n }\n }\n\n private async mapErrorToProxyResponse(error: unknown): Promise<ProxyResponse> {\n const parsedError = await readClientError(error);\n if (parsedError.status !== 500 || parsedError.text !== String(error)) {\n return {\n data: parsedError.body,\n status: parsedError.status,\n headers: { \"content-type\": \"application/json\" },\n isError: true,\n };\n }\n this.logger.error(`Proxy request failed:${error}`);\n return {\n data: {\n message: \"error in connecting to stackGen server\",\n },\n status: 500,\n headers: { \"content-type\": \"application/json\" },\n isError: true,\n };\n }\n\n private async apiResponseToProxyResponse<T>(\n request: () => Promise<T>,\n successStatus = 200,\n ): Promise<ProxyResponse> {\n try {\n const data = await request();\n return {\n data,\n status: successStatus,\n headers: { \"content-type\": \"application/json\" },\n isError: false,\n };\n } catch (error) {\n return this.mapErrorToProxyResponse(error);\n }\n }\n\n async getAllowedTeams(): Promise<AppstackTeam[]> {\n try {\n const allTeamsResponse = await this.listTeams();\n if (allTeamsResponse.isError) {\n throw new Error(\"error fetching teams from stackGen\");\n }\n\n const allTeams = Array.isArray(allTeamsResponse.data)\n ? allTeamsResponse.data\n : [];\n\n if (this.allowedTeams.length > 0) {\n const allowedTeams = allTeams.filter((team) =>\n this.allowedTeams.includes(team.id)\n );\n if (allowedTeams.length === 0) {\n throw new Error(`Unauthorized: No allowed teams found in StackGen.`);\n }\n return allowedTeams;\n }\n return allTeams;\n } catch (error) {\n this.logger.error(`Error fetching allowed teams:${error}`);\n throw error;\n }\n }\n\n async createOrUpdateAppstack(\n appStack: CreateOrUpdateAppstackRequest\n ): Promise<ProxyResponse> {\n try {\n if (\n this.allowedTeams.length > 0 &&\n !this.allowedTeams.includes(appStack.appstackTeamId)\n ) {\n throw new Error(`Unauthorized`);\n }\n\n // Legacy API: coreConfig + resources (same as scaffolder action)\n const apiPayload = {\n name: appStack.appstackName,\n coreConfig: {\n provider: appStack.cloudProvider,\n targetCompute: appStack.targetCompute ?? undefined,\n },\n resources: appStack.resources || [],\n teamId: appStack.appstackTeamId,\n };\n const requestUrl = `${this.stackgenApis.baseUrl}/stackgen/v1/appstacks`;\n this.logger.info(`Stackgen: Requesting ${requestUrl}`);\n try {\n const response = await executeFetchRequest(\n this.stackgenApis.fetchApi,\n requestUrl,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(apiPayload),\n },\n );\n return {\n data: response.data,\n status: response.status,\n headers: {\n \"content-type\":\n response.headers[\"content-type\"] ?? \"application/json\",\n },\n isError: !response.ok,\n };\n } catch (error) {\n // Transport failures (DNS, timeout, etc.) must stay ProxyResponse,\n // matching the legacy proxyRequest contract for this endpoint.\n return this.mapErrorToProxyResponse(error);\n }\n } catch (error) {\n this.logger.error(`error creating/updating appstack: ${error}`);\n throw new Error(\n error instanceof Error\n ? error.message\n : \"Failed to create or update appstack in StackGen\"\n );\n }\n }\n\n async getAppStacks(): Promise<ProxyResponse> {\n try {\n return await this.apiResponseToProxyResponse(() =>\n this.stackgenApis.integrationsAppstackApiObj.listAppStacks({}),\n );\n } catch (error) {\n this.logger.error(`Error fetching appstacks: ${error}`);\n throw new Error(\"Failed to retrieve appstacks from StackGen\");\n }\n }\n\n async listTeams(): Promise<ProxyResponse> {\n try {\n return await this.apiResponseToProxyResponse(() =>\n this.stackgenApis.integrationsTeamApiObj.listTeams({}),\n );\n } catch (error) {\n this.logger.error(`error fetching teams:${error}`);\n throw new Error(\"Failed to retrieve teams from StackGen\");\n }\n }\n\n async listAppstacksByTeamsID(teamId: string): Promise<ProxyResponse> {\n if (!teamId) {\n throw new InputError(\"Team ID is required to fetch appstacks.\");\n }\n\n try {\n return await this.apiResponseToProxyResponse(() =>\n this.stackgenApis.integrationsAppstackApiObj.listProjectAppStacks({\n projectId: teamId,\n }),\n );\n } catch (error) {\n this.logger.error(\n `error fetching appstacks for team ${teamId}: ${error}`\n );\n throw new Error(`Failed to retrieve appstacks for team ID ${teamId}`);\n }\n }\n\n async listTemplateAppstacks(): Promise<ProxyResponse> {\n const pageSize = 100;\n const maxOffset = 1000;\n const allAppstacks: unknown[] = [];\n let offset = 0;\n let reportedTotal: number | undefined;\n\n try {\n for (;;) {\n const pageOffset = offset;\n const response = await this.apiResponseToProxyResponse(() =>\n this.stackgenApis.appStacksApiObj.getTemplateAppstacks({\n limit: pageSize,\n offset: pageOffset,\n }),\n );\n\n if (response.isError || response.status >= 400) {\n return response;\n }\n\n const page = response.data ?? {};\n const rows = Array.isArray(page.appstacks) ? page.appstacks : [];\n allAppstacks.push(...rows);\n\n if (typeof page.total === \"number\") {\n reportedTotal = page.total;\n }\n\n if (rows.length < pageSize) {\n break;\n }\n if (\n typeof reportedTotal === \"number\" &&\n allAppstacks.length >= reportedTotal\n ) {\n break;\n }\n\n offset += pageSize;\n if (offset > maxOffset) {\n this.logger.warn(\n `Stopped paging template-appstacks after offset ${offset} (collected ${allAppstacks.length})`,\n );\n break;\n }\n }\n\n return {\n data: {\n appstacks: allAppstacks,\n total: reportedTotal ?? allAppstacks.length,\n limit: allAppstacks.length,\n offset: 0,\n },\n status: 200,\n headers: { \"Content-Type\": \"application/json\" },\n isError: false,\n };\n } catch (error) {\n this.logger.error(`Error fetching template appstacks: ${error}`);\n throw new Error(\"Failed to retrieve template appstacks from StackGen\");\n }\n }\n\n async getStackgenResourceTypes(): Promise<ProxyResponse> {\n try {\n const response = await this.apiResponseToProxyResponse(() =>\n this.stackgenApis.integrationsResourceApiObj.listSupportedResources(),\n );\n\n if (response.isError) {\n throw new Error(\"error fetching resource types from StackGen\");\n }\n return response;\n } catch (error) {\n this.logger.error(`error fetching resource types: ${error}`);\n throw new Error(\"Failed to retrieve resource types from StackGen\");\n }\n }\n\n async getStackgenResourceTypesByTeamID(\n teamId: string\n ): Promise<ProxyResponse> {\n if (!teamId) {\n throw new InputError(\"Team ID is required to fetch resource types.\");\n }\n\n try {\n const response = await this.apiResponseToProxyResponse(() =>\n this.stackgenApis.integrationsResourceApiObj.listProjectSupportedResources(\n {\n projectId: teamId,\n },\n ),\n );\n\n if (response.isError) {\n throw new Error(\n `error fetching resource types for team ${teamId} from StackGen`\n );\n }\n return response;\n } catch (error) {\n this.logger.error(\n `error fetching resource types for team ${teamId}: ${error}`\n );\n throw new Error(\n `Failed to retrieve resource types for team ID ${teamId}`\n );\n }\n }\n\n async createProject(project: CreateProjectRequest): Promise<ProxyResponse> {\n try {\n return await this.apiResponseToProxyResponse(\n () =>\n this.stackgenApis.integrationsProjectApiObj.createProject({\n projectRequest: project,\n }),\n 201,\n );\n } catch (error) {\n this.logger.error(`Error creating project: ${error}`);\n throw new Error(\"Failed to create project in StackGen\");\n }\n }\n}\n"],"names":["getStackgenApiObjects","InputError","readClientError","executeFetchRequest"],"mappings":"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"}
@@ -0,0 +1,205 @@
1
+ 'use strict';
2
+
3
+ var index = require('../vendor/stackgen-api-client/index.cjs.js');
4
+ var http = require('../exporter/http.cjs.js');
5
+ var paths = require('../exporter/paths.cjs.js');
6
+
7
+ function getFetchApi(token) {
8
+ return (input, init) => {
9
+ const headers = new Headers(init?.headers);
10
+ headers.set("Authorization", `Bearer ${token}`);
11
+ if (!headers.has("Accept")) {
12
+ headers.set("Accept", "application/json");
13
+ }
14
+ return fetch(input, { ...init, headers });
15
+ };
16
+ }
17
+ const apiObjectsCache = /* @__PURE__ */ new WeakMap();
18
+ function getStackgenApiObjects(config) {
19
+ const cached = apiObjectsCache.get(config);
20
+ if (cached) {
21
+ return cached;
22
+ }
23
+ const baseUrl = paths.cleanBaseUrl(config.getString("stackGen.baseUrl"));
24
+ const token = config.getString("stackGen.apiToken");
25
+ const fetchApi = getFetchApi(token);
26
+ const appcdConfig = new index.AppcdConfiguration({
27
+ basePath: `${baseUrl}/appcd/api`,
28
+ fetchApi
29
+ });
30
+ const topologyConfig = new index.TopologyConfiguration({
31
+ basePath: `${baseUrl}${paths.iacGenRoot(config)}`,
32
+ fetchApi
33
+ });
34
+ const exporterConfig = new index.ExporterConfiguration({
35
+ basePath: `${baseUrl}${paths.exporterRoot(config)}`,
36
+ fetchApi
37
+ });
38
+ const integrationsConfig = new index.IntegrationsConfiguration({
39
+ basePath: `${baseUrl}/integrations/api`,
40
+ fetchApi
41
+ });
42
+ const vaultConfig = new index.VaultConfiguration({
43
+ basePath: `${baseUrl}${paths.vaultRoot(config)}`,
44
+ fetchApi
45
+ });
46
+ const objects = {
47
+ baseUrl,
48
+ token,
49
+ fetchApi,
50
+ appStacksApiObj: new index.AppStacksApi(appcdConfig),
51
+ authenticationApiObject: new index.AuthenticationApi(appcdConfig),
52
+ projectApiObject: new index.OrgManagementApi(appcdConfig),
53
+ roleApiObj: new index.RoleManagementApi(appcdConfig),
54
+ usersApiObj: new index.UsersApi(appcdConfig),
55
+ userGroupApiObj: new index.UserGroupManagementApi(appcdConfig),
56
+ v1TopologyApiObj: new index.V1TopologyApi(topologyConfig),
57
+ v1ResourceApiObj: new index.TopologyResourceApi(topologyConfig),
58
+ v1EnvironmentProfileApiObj: new index.V1EnvironmentProfileApi(topologyConfig),
59
+ v1CustomResourceTemplateApiObj: new index.V1CustomResourceTemplateApi(
60
+ topologyConfig
61
+ ),
62
+ v1TfBlocksApiObj: new index.V1TfBlocksApi(topologyConfig),
63
+ integrationsAppstackApiObj: new index.V1AppstackApi(integrationsConfig),
64
+ integrationsProjectApiObj: new index.V1ProjectApi(integrationsConfig),
65
+ integrationsResourceApiObj: new index.IntegrationsResourceApi(integrationsConfig),
66
+ integrationsTeamApiObj: new index.V1TeamApi(integrationsConfig),
67
+ integrationsTopologyApiObj: new index.IntegrationsTopologyApi(integrationsConfig),
68
+ vaultSecretApiObj: new index.SecretApi(vaultConfig),
69
+ exporterConfigApiObj: new index.ConfigApi(exporterConfig),
70
+ exporterConfigTemplatesApiObj: new index.ConfigTemplatesApi(exporterConfig),
71
+ exporterApiObj: new index.ExportApi(exporterConfig)
72
+ };
73
+ apiObjectsCache.set(config, objects);
74
+ return objects;
75
+ }
76
+ function requestIdFromResponse(response) {
77
+ const id = response.headers.get("x-request-id")?.trim();
78
+ return id || void 0;
79
+ }
80
+ async function readClientError(error) {
81
+ const response = error?.response;
82
+ if (!response) {
83
+ return {
84
+ status: 500,
85
+ body: { message: String(error) },
86
+ text: String(error)
87
+ };
88
+ }
89
+ const requestId = requestIdFromResponse(response);
90
+ const text = await response.text().catch(() => "");
91
+ if (!text.trim()) {
92
+ return { status: response.status, body: {}, text, requestId };
93
+ }
94
+ try {
95
+ return {
96
+ status: response.status,
97
+ body: JSON.parse(text),
98
+ text,
99
+ requestId
100
+ };
101
+ } catch {
102
+ return {
103
+ status: response.status,
104
+ body: { message: text },
105
+ text,
106
+ requestId
107
+ };
108
+ }
109
+ }
110
+ function formatApiFailure(status, body, text = "", requestId) {
111
+ const fromBody = http.apiErrorMessage(body, text).trim();
112
+ const raw = fromBody || text.trim() || "";
113
+ const detail = collapseOpaqueResponseError(raw, status);
114
+ const parts = [];
115
+ if (status >= 400 && status < 600) {
116
+ parts.push(`HTTP ${status}`);
117
+ }
118
+ if (requestId) {
119
+ parts.push(`Request ID: ${requestId}`);
120
+ }
121
+ if (parts.length === 0) {
122
+ return detail;
123
+ }
124
+ return `${detail} (${parts.join(", ")})`;
125
+ }
126
+ async function formatClientErrorMessage(error) {
127
+ if (!error?.response) {
128
+ if (error instanceof Error) {
129
+ return error.message;
130
+ }
131
+ return String(error);
132
+ }
133
+ const parsed = await readClientError(error);
134
+ const textFallback = parsed.text.trim() || (error instanceof Error ? error.message : String(error));
135
+ return formatApiFailure(
136
+ parsed.status,
137
+ parsed.body,
138
+ textFallback,
139
+ parsed.requestId
140
+ );
141
+ }
142
+ function collapseOpaqueResponseError(message, status) {
143
+ const trimmed = message.trim();
144
+ if (/Response returned an error code/i.test(trimmed)) {
145
+ return status ? `StackGen API request failed` : trimmed;
146
+ }
147
+ return trimmed || "StackGen API request failed";
148
+ }
149
+ async function parseFetchResponseBody(response) {
150
+ const contentType = response.headers.get("content-type") ?? "";
151
+ const text = await response.text();
152
+ if (!contentType.includes("application/json") || !text.trim()) {
153
+ return text;
154
+ }
155
+ try {
156
+ return JSON.parse(text);
157
+ } catch {
158
+ return text;
159
+ }
160
+ }
161
+ async function executeFetchRequest(fetchApi, url, init) {
162
+ const response = await fetchApi(url, init);
163
+ const headers = {};
164
+ response.headers.forEach((value, key) => {
165
+ headers[key] = value;
166
+ });
167
+ return {
168
+ ok: response.ok,
169
+ status: response.status,
170
+ data: await parseFetchResponseBody(response),
171
+ headers
172
+ };
173
+ }
174
+ async function executeApiRequest(request, successStatus = 200) {
175
+ try {
176
+ const parsed = await request();
177
+ const text = typeof parsed === "string" ? parsed : JSON.stringify(parsed ?? {});
178
+ return {
179
+ ok: true,
180
+ status: successStatus,
181
+ parsed,
182
+ text
183
+ };
184
+ } catch (error) {
185
+ const parsedError = await readClientError(error);
186
+ if (parsedError.status === 500 && parsedError.text === String(error)) {
187
+ throw error;
188
+ }
189
+ return {
190
+ ok: false,
191
+ status: parsedError.status,
192
+ parsed: parsedError.body,
193
+ text: parsedError.text,
194
+ requestId: parsedError.requestId
195
+ };
196
+ }
197
+ }
198
+
199
+ exports.executeApiRequest = executeApiRequest;
200
+ exports.executeFetchRequest = executeFetchRequest;
201
+ exports.formatApiFailure = formatApiFailure;
202
+ exports.formatClientErrorMessage = formatClientErrorMessage;
203
+ exports.getStackgenApiObjects = getStackgenApiObjects;
204
+ exports.readClientError = readClientError;
205
+ //# sourceMappingURL=api-objects.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-objects.cjs.js","sources":["../../src/utils/api-objects.ts"],"sourcesContent":["import { Config } from \"@backstage/config\";\nimport {\n AppStacksApi,\n AppcdConfiguration,\n AuthenticationApi,\n ConfigApi,\n ConfigTemplatesApi,\n ExportApi,\n ExporterConfiguration,\n IntegrationsConfiguration,\n IntegrationsResourceApi,\n IntegrationsTopologyApi,\n OrgManagementApi,\n RoleManagementApi,\n SecretApi,\n TopologyConfiguration,\n TopologyResourceApi,\n UserGroupManagementApi,\n UsersApi,\n VaultConfiguration,\n V1AppstackApi,\n V1CustomResourceTemplateApi,\n V1EnvironmentProfileApi,\n V1ProjectApi,\n V1TeamApi,\n V1TfBlocksApi,\n V1TopologyApi,\n} from \"../../vendor/stackgen-api-client\";\nimport { apiErrorMessage } from \"../exporter/http\";\nimport { cleanBaseUrl, exporterRoot, iacGenRoot, vaultRoot } from \"../exporter/paths\";\n\nfunction getFetchApi(token: string): typeof fetch {\n return (input, init) => {\n const headers = new Headers(init?.headers);\n headers.set(\"Authorization\", `Bearer ${token}`);\n if (!headers.has(\"Accept\")) {\n headers.set(\"Accept\", \"application/json\");\n }\n return fetch(input, { ...init, headers });\n };\n}\n\nexport type StackgenApiObjects = {\n baseUrl: string;\n token: string;\n /** Authenticated fetch adapter (Bearer token); only HTTP entry point outside generated clients. */\n fetchApi: typeof fetch;\n appStacksApiObj: AppStacksApi;\n authenticationApiObject: AuthenticationApi;\n projectApiObject: OrgManagementApi;\n roleApiObj: RoleManagementApi;\n usersApiObj: UsersApi;\n userGroupApiObj: UserGroupManagementApi;\n v1TopologyApiObj: V1TopologyApi;\n v1ResourceApiObj: TopologyResourceApi;\n v1EnvironmentProfileApiObj: V1EnvironmentProfileApi;\n v1CustomResourceTemplateApiObj: V1CustomResourceTemplateApi;\n v1TfBlocksApiObj: V1TfBlocksApi;\n integrationsAppstackApiObj: V1AppstackApi;\n integrationsProjectApiObj: V1ProjectApi;\n integrationsResourceApiObj: IntegrationsResourceApi;\n integrationsTeamApiObj: V1TeamApi;\n integrationsTopologyApiObj: IntegrationsTopologyApi;\n vaultSecretApiObj: SecretApi;\n exporterConfigApiObj: ConfigApi;\n exporterConfigTemplatesApiObj: ConfigTemplatesApi;\n exporterApiObj: ExportApi;\n};\n\nconst apiObjectsCache = new WeakMap<Config, StackgenApiObjects>();\n\nexport function getStackgenApiObjects(config: Config): StackgenApiObjects {\n const cached = apiObjectsCache.get(config);\n if (cached) {\n return cached;\n }\n\n const baseUrl = cleanBaseUrl(config.getString(\"stackGen.baseUrl\"));\n const token = config.getString(\"stackGen.apiToken\");\n const fetchApi = getFetchApi(token);\n\n const appcdConfig = new AppcdConfiguration({\n basePath: `${baseUrl}/appcd/api`,\n fetchApi,\n });\n const topologyConfig = new TopologyConfiguration({\n basePath: `${baseUrl}${iacGenRoot(config)}`,\n fetchApi,\n });\n const exporterConfig = new ExporterConfiguration({\n basePath: `${baseUrl}${exporterRoot(config)}`,\n fetchApi,\n });\n const integrationsConfig = new IntegrationsConfiguration({\n basePath: `${baseUrl}/integrations/api`,\n fetchApi,\n });\n const vaultConfig = new VaultConfiguration({\n basePath: `${baseUrl}${vaultRoot(config)}`,\n fetchApi,\n });\n\n const objects: StackgenApiObjects = {\n baseUrl,\n token,\n fetchApi,\n appStacksApiObj: new AppStacksApi(appcdConfig),\n authenticationApiObject: new AuthenticationApi(appcdConfig),\n projectApiObject: new OrgManagementApi(appcdConfig),\n roleApiObj: new RoleManagementApi(appcdConfig),\n usersApiObj: new UsersApi(appcdConfig),\n userGroupApiObj: new UserGroupManagementApi(appcdConfig),\n v1TopologyApiObj: new V1TopologyApi(topologyConfig),\n v1ResourceApiObj: new TopologyResourceApi(topologyConfig),\n v1EnvironmentProfileApiObj: new V1EnvironmentProfileApi(topologyConfig),\n v1CustomResourceTemplateApiObj: new V1CustomResourceTemplateApi(\n topologyConfig,\n ),\n v1TfBlocksApiObj: new V1TfBlocksApi(topologyConfig),\n integrationsAppstackApiObj: new V1AppstackApi(integrationsConfig),\n integrationsProjectApiObj: new V1ProjectApi(integrationsConfig),\n integrationsResourceApiObj: new IntegrationsResourceApi(integrationsConfig),\n integrationsTeamApiObj: new V1TeamApi(integrationsConfig),\n integrationsTopologyApiObj: new IntegrationsTopologyApi(integrationsConfig),\n vaultSecretApiObj: new SecretApi(vaultConfig),\n exporterConfigApiObj: new ConfigApi(exporterConfig),\n exporterConfigTemplatesApiObj: new ConfigTemplatesApi(exporterConfig),\n exporterApiObj: new ExportApi(exporterConfig),\n };\n\n apiObjectsCache.set(config, objects);\n return objects;\n}\n\nexport type ClientErrorDetails = {\n status: number;\n body: unknown;\n text: string;\n /** Upstream `x-request-id` when present on the error Response. */\n requestId?: string;\n};\n\nfunction requestIdFromResponse(response: Response): string | undefined {\n const id = response.headers.get(\"x-request-id\")?.trim();\n return id || undefined;\n}\n\nexport async function readClientError(error: unknown): Promise<ClientErrorDetails> {\n const response = (error as { response?: Response })?.response;\n if (!response) {\n return {\n status: 500,\n body: { message: String(error) },\n text: String(error),\n };\n }\n\n const requestId = requestIdFromResponse(response);\n const text = await response.text().catch(() => \"\");\n if (!text.trim()) {\n return { status: response.status, body: {}, text, requestId };\n }\n\n try {\n return {\n status: response.status,\n body: JSON.parse(text),\n text,\n requestId,\n };\n } catch {\n return {\n status: response.status,\n body: { message: text },\n text,\n requestId,\n };\n }\n}\n\n/**\n * Formats status / body / request-id the same way for thrown client errors and\n * executeApiRequest non-ok results.\n */\nexport function formatApiFailure(\n status: number,\n body: unknown,\n text = \"\",\n requestId?: string,\n): string {\n const fromBody = apiErrorMessage(body, text).trim();\n const raw = fromBody || text.trim() || \"\";\n const detail = collapseOpaqueResponseError(raw, status);\n\n const parts: string[] = [];\n if (status >= 400 && status < 600) {\n parts.push(`HTTP ${status}`);\n }\n if (requestId) {\n parts.push(`Request ID: ${requestId}`);\n }\n if (parts.length === 0) {\n return detail;\n }\n return `${detail} (${parts.join(\", \")})`;\n}\n\n/**\n * Builds a user-facing error string from a generated-client / fetch failure.\n * Prefer API body `msg` / `message` / `extras` over opaque ResponseError text;\n * include HTTP status and Request ID when available.\n *\n * Response-less errors (already wrapped `Error`s, validation, FS, etc.) are\n * returned as-is — do not invent a synthetic HTTP 500.\n */\nexport async function formatClientErrorMessage(error: unknown): Promise<string> {\n if (!(error as { response?: unknown })?.response) {\n if (error instanceof Error) {\n return error.message;\n }\n return String(error);\n }\n\n const parsed = await readClientError(error);\n const textFallback =\n parsed.text.trim() ||\n (error instanceof Error ? error.message : String(error));\n return formatApiFailure(\n parsed.status,\n parsed.body,\n textFallback,\n parsed.requestId,\n );\n}\n\nfunction collapseOpaqueResponseError(message: string, status: number): string {\n const trimmed = message.trim();\n if (/Response returned an error code/i.test(trimmed)) {\n return status ? `StackGen API request failed` : trimmed;\n }\n return trimmed || \"StackGen API request failed\";\n}\n\nexport type ApiRequestResult<T = unknown> = {\n ok: boolean;\n status: number;\n parsed: T;\n text: string;\n requestId?: string;\n};\n\nexport type FetchRequestResult = {\n ok: boolean;\n status: number;\n data: unknown;\n headers: Record<string, string>;\n};\n\nasync function parseFetchResponseBody(response: Response): Promise<unknown> {\n const contentType = response.headers.get(\"content-type\") ?? \"\";\n const text = await response.text();\n if (!contentType.includes(\"application/json\") || !text.trim()) {\n return text;\n }\n try {\n return JSON.parse(text);\n } catch {\n return text;\n }\n}\n\n/** For StackGen routes not covered by generated OpenAPI clients (e.g. legacy backstage adapter). */\nexport async function executeFetchRequest(\n fetchApi: typeof fetch,\n url: string,\n init: RequestInit,\n): Promise<FetchRequestResult> {\n const response = await fetchApi(url, init);\n const headers: Record<string, string> = {};\n response.headers.forEach((value, key) => {\n headers[key] = value;\n });\n return {\n ok: response.ok,\n status: response.status,\n data: await parseFetchResponseBody(response),\n headers,\n };\n}\n\n/**\n * Runs a generated-client call and normalizes success/error into { ok, status, parsed }.\n * `parsed` is intentionally untyped: error bodies and some StackGen responses use\n * fields outside the OpenAPI success models (msg/message, legacy aliases, etc.).\n */\nexport async function executeApiRequest(\n request: () => Promise<unknown>,\n successStatus = 200,\n): Promise<ApiRequestResult<any>> {\n try {\n const parsed = await request();\n const text =\n typeof parsed === \"string\" ? parsed : JSON.stringify(parsed ?? {});\n return {\n ok: true,\n status: successStatus,\n parsed,\n text,\n };\n } catch (error) {\n const parsedError = await readClientError(error);\n if (parsedError.status === 500 && parsedError.text === String(error)) {\n throw error;\n }\n return {\n ok: false,\n status: parsedError.status,\n parsed: parsedError.body,\n text: parsedError.text,\n requestId: parsedError.requestId,\n };\n }\n}\n"],"names":["cleanBaseUrl","AppcdConfiguration","TopologyConfiguration","iacGenRoot","ExporterConfiguration","exporterRoot","IntegrationsConfiguration","VaultConfiguration","vaultRoot","AppStacksApi","AuthenticationApi","OrgManagementApi","RoleManagementApi","UsersApi","UserGroupManagementApi","V1TopologyApi","TopologyResourceApi","V1EnvironmentProfileApi","V1CustomResourceTemplateApi","V1TfBlocksApi","V1AppstackApi","V1ProjectApi","IntegrationsResourceApi","V1TeamApi","IntegrationsTopologyApi","SecretApi","ConfigApi","ConfigTemplatesApi","ExportApi","apiErrorMessage"],"mappings":"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"}