@backstage/backend-defaults 0.16.1-next.0 → 0.16.1-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @backstage/backend-defaults
2
2
 
3
+ ## 0.16.1-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 4559806: Added support for typed `examples` on actions registered via the actions registry. Action authors can now provide examples with compile-time-checked `input` and `output` values that match their schema definitions.
8
+ - 5cd814f: Refactored auditor severity log level mappings to use `zod/v4` with schema-driven defaults and type inference.
9
+ - 6e2aaab: Fixed `AwsS3UrlReader` failing to read files from S3 buckets configured with custom endpoint hosts. When an integration was configured with a specific endpoint like `https://bucket-1.s3.eu-central-1.amazonaws.com`, the URL parser incorrectly fell through to the non-AWS code path, always defaulting the region to `us-east-1` instead of extracting it from the hostname.
10
+ - Updated dependencies
11
+ - @backstage/backend-plugin-api@1.9.0-next.1
12
+ - @backstage/plugin-auth-node@0.7.0-next.1
13
+ - @backstage/backend-app-api@1.6.1-next.1
14
+ - @backstage/plugin-events-node@0.4.21-next.1
15
+ - @backstage/plugin-permission-node@0.10.12-next.1
16
+
3
17
  ## 0.16.1-next.0
4
18
 
5
19
  ### Patch Changes
@@ -69,6 +69,7 @@ class DefaultActionsRegistryService {
69
69
  idempotent: action.attributes?.idempotent ?? false,
70
70
  readOnly: action.attributes?.readOnly ?? false
71
71
  },
72
+ examples: action.examples,
72
73
  schema: {
73
74
  input: action.schema?.input ? zodToJsonSchema__default.default(action.schema.input(v3.z)) : zodToJsonSchema__default.default(v3.z.object({})),
74
75
  output: action.schema?.output ? zodToJsonSchema__default.default(action.schema.output(v3.z)) : zodToJsonSchema__default.default(v3.z.object({}))
@@ -1 +1 @@
1
- {"version":3,"file":"DefaultActionsRegistryService.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod/v3';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport { InputError, NotAllowedError, NotFoundError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\n\ntype ActionEntry = [string, ActionsRegistryActionOptions<any, any>];\n\nexport class DefaultActionsRegistryService implements ActionsRegistryService {\n private actions: Map<string, ActionsRegistryActionOptions<any, any>> =\n new Map();\n\n private readonly logger: LoggerService;\n private readonly httpAuth: HttpAuthService;\n private readonly auth: AuthService;\n private readonly metadata: PluginMetadataService;\n private readonly permissions: PermissionsService;\n private readonly permissionsRegistry: PermissionsRegistryService;\n\n private constructor(\n logger: LoggerService,\n httpAuth: HttpAuthService,\n auth: AuthService,\n metadata: PluginMetadataService,\n permissions: PermissionsService,\n permissionsRegistry: PermissionsRegistryService,\n ) {\n this.logger = logger;\n this.httpAuth = httpAuth;\n this.auth = auth;\n this.metadata = metadata;\n this.permissions = permissions;\n this.permissionsRegistry = permissionsRegistry;\n }\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(\n logger,\n httpAuth,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n );\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use(json());\n\n router.get('/.backstage/actions/v1/actions', async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n const entries = Array.from(this.actions.entries());\n\n const allowedActions = await this.filterByPermissions(\n entries,\n credentials,\n );\n\n return res.json({\n actions: allowedActions.map(([id, action]) => ({\n id,\n name: action.name,\n title: action.title,\n description: action.description,\n pluginId: this.metadata.getId(),\n attributes: {\n // Inspired by the @modelcontextprotocol/sdk defaults for the hints.\n // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812\n destructive: action.attributes?.destructive ?? true,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n },\n })),\n });\n });\n\n router.post(\n '/.backstage/actions/v1/actions/:actionId/invoke',\n async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by an authenticated principal, not an anonymous request`,\n );\n }\n\n const action = this.actions.get(req.params.actionId);\n\n if (!action) {\n throw new NotFoundError(`Action \"${req.params.actionId}\" not found`);\n }\n\n if (action.visibilityPermission) {\n const [decision] = await this.permissions.authorize(\n [{ permission: action.visibilityPermission }],\n { credentials },\n );\n if (decision.result !== AuthorizeResult.ALLOW) {\n throw new NotFoundError(\n `Action \"${req.params.actionId}\" not found`,\n );\n }\n }\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(req.body)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(\n `Invalid input to action \"${req.params.actionId}\"`,\n input.error,\n );\n }\n\n const result = await action.action({\n input: input.data,\n credentials,\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${req.params.actionId}\"`,\n output.error,\n );\n }\n\n res.json({ output: output.data });\n },\n );\n return router;\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n >(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void {\n const id = `${this.metadata.getId()}:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n if (options.visibilityPermission) {\n this.permissionsRegistry.addPermissions([options.visibilityPermission]);\n }\n\n this.actions.set(id, options);\n }\n\n private async filterByPermissions(\n entries: ActionEntry[],\n credentials: BackstageCredentials,\n ): Promise<ActionEntry[]> {\n const permissionedEntries = entries.filter(\n ([_, action]) => action.visibilityPermission,\n );\n\n if (permissionedEntries.length === 0) {\n return entries;\n }\n\n const decisions = await this.permissions.authorize(\n permissionedEntries.map(([_, action]) => ({\n permission: action.visibilityPermission!,\n })),\n { credentials },\n );\n\n const deniedIds = new Set(\n permissionedEntries\n .filter((_, index) => decisions[index].result !== AuthorizeResult.ALLOW)\n .map(([id]) => id),\n );\n\n return entries.filter(([id]) => !deniedIds.has(id));\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","AuthorizeResult","InputError"],"mappings":"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"}
1
+ {"version":3,"file":"DefaultActionsRegistryService.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AuthService,\n BackstageCredentials,\n HttpAuthService,\n LoggerService,\n PermissionsRegistryService,\n PermissionsService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod/v3';\nimport zodToJsonSchema from 'zod-to-json-schema';\nimport {\n ActionsRegistryActionOptions,\n ActionsRegistryService,\n} from '@backstage/backend-plugin-api/alpha';\nimport { InputError, NotAllowedError, NotFoundError } from '@backstage/errors';\nimport { AuthorizeResult } from '@backstage/plugin-permission-common';\n\ntype ActionEntry = [string, ActionsRegistryActionOptions<any, any>];\n\nexport class DefaultActionsRegistryService implements ActionsRegistryService {\n private actions: Map<string, ActionsRegistryActionOptions<any, any>> =\n new Map();\n\n private readonly logger: LoggerService;\n private readonly httpAuth: HttpAuthService;\n private readonly auth: AuthService;\n private readonly metadata: PluginMetadataService;\n private readonly permissions: PermissionsService;\n private readonly permissionsRegistry: PermissionsRegistryService;\n\n private constructor(\n logger: LoggerService,\n httpAuth: HttpAuthService,\n auth: AuthService,\n metadata: PluginMetadataService,\n permissions: PermissionsService,\n permissionsRegistry: PermissionsRegistryService,\n ) {\n this.logger = logger;\n this.httpAuth = httpAuth;\n this.auth = auth;\n this.metadata = metadata;\n this.permissions = permissions;\n this.permissionsRegistry = permissionsRegistry;\n }\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n permissions: PermissionsService;\n permissionsRegistry: PermissionsRegistryService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(\n logger,\n httpAuth,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n );\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use(json());\n\n router.get('/.backstage/actions/v1/actions', async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n const entries = Array.from(this.actions.entries());\n\n const allowedActions = await this.filterByPermissions(\n entries,\n credentials,\n );\n\n return res.json({\n actions: allowedActions.map(([id, action]) => ({\n id,\n name: action.name,\n title: action.title,\n description: action.description,\n pluginId: this.metadata.getId(),\n attributes: {\n // Inspired by the @modelcontextprotocol/sdk defaults for the hints.\n // https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812\n destructive: action.attributes?.destructive ?? true,\n idempotent: action.attributes?.idempotent ?? false,\n readOnly: action.attributes?.readOnly ?? false,\n },\n examples: action.examples,\n schema: {\n input: action.schema?.input\n ? zodToJsonSchema(action.schema.input(z))\n : zodToJsonSchema(z.object({})),\n output: action.schema?.output\n ? zodToJsonSchema(action.schema.output(z))\n : zodToJsonSchema(z.object({})),\n },\n })),\n });\n });\n\n router.post(\n '/.backstage/actions/v1/actions/:actionId/invoke',\n async (req, res) => {\n const credentials = await this.httpAuth.credentials(req);\n if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by an authenticated principal, not an anonymous request`,\n );\n }\n\n const action = this.actions.get(req.params.actionId);\n\n if (!action) {\n throw new NotFoundError(`Action \"${req.params.actionId}\" not found`);\n }\n\n if (action.visibilityPermission) {\n const [decision] = await this.permissions.authorize(\n [{ permission: action.visibilityPermission }],\n { credentials },\n );\n if (decision.result !== AuthorizeResult.ALLOW) {\n throw new NotFoundError(\n `Action \"${req.params.actionId}\" not found`,\n );\n }\n }\n\n const input = action.schema?.input\n ? action.schema.input(z).safeParse(req.body)\n : ({ success: true, data: undefined } as const);\n\n if (!input.success) {\n throw new InputError(\n `Invalid input to action \"${req.params.actionId}\"`,\n input.error,\n );\n }\n\n const result = await action.action({\n input: input.data,\n credentials,\n logger: this.logger,\n });\n\n const output = action.schema?.output\n ? action.schema.output(z).safeParse(result?.output)\n : ({ success: true, data: result?.output } as const);\n\n if (!output.success) {\n throw new InputError(\n `Invalid output from action \"${req.params.actionId}\"`,\n output.error,\n );\n }\n\n res.json({ output: output.data });\n },\n );\n return router;\n }\n\n register<\n TInputSchema extends AnyZodObject,\n TOutputSchema extends AnyZodObject,\n >(options: ActionsRegistryActionOptions<TInputSchema, TOutputSchema>): void {\n const id = `${this.metadata.getId()}:${options.name}`;\n\n if (this.actions.has(id)) {\n throw new Error(`Action with id \"${id}\" is already registered`);\n }\n\n if (options.visibilityPermission) {\n this.permissionsRegistry.addPermissions([options.visibilityPermission]);\n }\n\n this.actions.set(id, options);\n }\n\n private async filterByPermissions(\n entries: ActionEntry[],\n credentials: BackstageCredentials,\n ): Promise<ActionEntry[]> {\n const permissionedEntries = entries.filter(\n ([_, action]) => action.visibilityPermission,\n );\n\n if (permissionedEntries.length === 0) {\n return entries;\n }\n\n const decisions = await this.permissions.authorize(\n permissionedEntries.map(([_, action]) => ({\n permission: action.visibilityPermission!,\n })),\n { credentials },\n );\n\n const deniedIds = new Set(\n permissionedEntries\n .filter((_, index) => decisions[index].result !== AuthorizeResult.ALLOW)\n .map(([id]) => id),\n );\n\n return entries.filter(([id]) => !deniedIds.has(id));\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","AuthorizeResult","InputError"],"mappings":"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"}
@@ -1,30 +1,38 @@
1
1
  'use strict';
2
2
 
3
3
  var errors = require('@backstage/errors');
4
- var types = require('./types.cjs.js');
4
+ var v4 = require('zod/v4');
5
5
 
6
+ const CONFIG_ROOT_KEY = "backend.auditor";
7
+ const logLevel = v4.z.enum(["debug", "info", "warn", "error"]);
8
+ const severityLogLevelMappingsSchema = v4.z.object({
9
+ low: logLevel.default("debug"),
10
+ medium: logLevel.default("info"),
11
+ high: logLevel.default("info"),
12
+ critical: logLevel.default("info")
13
+ });
6
14
  function getSeverityLogLevelMappings(config) {
7
- const auditorConfig = config.getOptionalConfig(types.CONFIG_ROOT_KEY);
8
- const severityLogLevelMappings = {
9
- low: auditorConfig?.getOptionalString("severityLogLevelMappings.low") ?? "debug",
10
- medium: auditorConfig?.getOptionalString("severityLogLevelMappings.medium") ?? "info",
11
- high: auditorConfig?.getOptionalString("severityLogLevelMappings.high") ?? "info",
12
- critical: auditorConfig?.getOptionalString("severityLogLevelMappings.critical") ?? "info"
15
+ const auditorConfig = config.getOptionalConfig(CONFIG_ROOT_KEY);
16
+ const input = {
17
+ low: auditorConfig?.getOptionalString("severityLogLevelMappings.low"),
18
+ medium: auditorConfig?.getOptionalString("severityLogLevelMappings.medium"),
19
+ high: auditorConfig?.getOptionalString("severityLogLevelMappings.high"),
20
+ critical: auditorConfig?.getOptionalString(
21
+ "severityLogLevelMappings.critical"
22
+ )
13
23
  };
14
- const res = types.severityLogLevelMappingsSchema.safeParse(
15
- severityLogLevelMappings
16
- );
17
- if (!res.success) {
18
- const key = res.error.issues.at(0)?.path.at(0);
19
- const value = res.error.issues.at(0).received;
20
- const validKeys = res.error.issues.at(0).options;
24
+ const parsed = severityLogLevelMappingsSchema.safeParse(input);
25
+ if (!parsed.success) {
26
+ const issue = parsed.error.issues[0];
27
+ const key = issue.path[0];
28
+ const receivedValue = input[key];
21
29
  throw new errors.InputError(
22
- `The configuration value for 'backend.auditor.severityLogLevelMappings.${key}' was given an invalid value: '${value}'. Expected one of the following valid values: '${validKeys.join(
30
+ `The configuration value for '${CONFIG_ROOT_KEY}.severityLogLevelMappings.${key}' was given an invalid value: '${receivedValue}'. Expected one of the following valid values: '${logLevel.options.join(
23
31
  ", "
24
32
  )}'.`
25
33
  );
26
34
  }
27
- return severityLogLevelMappings;
35
+ return parsed.data;
28
36
  }
29
37
 
30
38
  exports.getSeverityLogLevelMappings = getSeverityLogLevelMappings;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.cjs.js","sources":["../../../src/entrypoints/auditor/utils.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Config } from '@backstage/config';\nimport { InputError } from '@backstage/errors';\nimport { z } from 'zod/v3';\nimport { CONFIG_ROOT_KEY, severityLogLevelMappingsSchema } from './types';\n\n/**\n * Gets the `backend.auditor.severityLogLevelMappings` configuration.\n *\n * @param config - The root Backstage {@link @backstage/config#Config} object.\n * @returns The validated severity-to-log-level mappings.\n * @throws error - {@link @backstage/errors#InputError} if the mapping configuration is invalid.\n */\nexport function getSeverityLogLevelMappings(config: Config) {\n const auditorConfig = config.getOptionalConfig(CONFIG_ROOT_KEY);\n\n const severityLogLevelMappings = {\n low:\n auditorConfig?.getOptionalString('severityLogLevelMappings.low') ??\n 'debug',\n medium:\n auditorConfig?.getOptionalString('severityLogLevelMappings.medium') ??\n 'info',\n high:\n auditorConfig?.getOptionalString('severityLogLevelMappings.high') ??\n 'info',\n critical:\n auditorConfig?.getOptionalString('severityLogLevelMappings.critical') ??\n 'info',\n } as Required<z.infer<typeof severityLogLevelMappingsSchema>>;\n\n const res = severityLogLevelMappingsSchema.safeParse(\n severityLogLevelMappings,\n );\n if (!res.success) {\n const key = res.error.issues.at(0)?.path.at(0) as string;\n const value = (\n res.error.issues.at(0) as unknown as Record<PropertyKey, unknown>\n ).received as string;\n const validKeys = (\n res.error.issues.at(0) as unknown as Record<PropertyKey, unknown>\n ).options as string[];\n throw new InputError(\n `The configuration value for 'backend.auditor.severityLogLevelMappings.${key}' was given an invalid value: '${value}'. Expected one of the following valid values: '${validKeys.join(\n ', ',\n )}'.`,\n );\n }\n\n return severityLogLevelMappings;\n}\n"],"names":["CONFIG_ROOT_KEY","severityLogLevelMappingsSchema","InputError"],"mappings":";;;;;AA4BO,SAAS,4BAA4B,MAAA,EAAgB;AAC1D,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,iBAAA,CAAkBA,qBAAe,CAAA;AAE9D,EAAA,MAAM,wBAAA,GAA2B;AAAA,IAC/B,GAAA,EACE,aAAA,EAAe,iBAAA,CAAkB,8BAA8B,CAAA,IAC/D,OAAA;AAAA,IACF,MAAA,EACE,aAAA,EAAe,iBAAA,CAAkB,iCAAiC,CAAA,IAClE,MAAA;AAAA,IACF,IAAA,EACE,aAAA,EAAe,iBAAA,CAAkB,+BAA+B,CAAA,IAChE,MAAA;AAAA,IACF,QAAA,EACE,aAAA,EAAe,iBAAA,CAAkB,mCAAmC,CAAA,IACpE;AAAA,GACJ;AAEA,EAAA,MAAM,MAAMC,oCAAA,CAA+B,SAAA;AAAA,IACzC;AAAA,GACF;AACA,EAAA,IAAI,CAAC,IAAI,OAAA,EAAS;AAChB,IAAA,MAAM,GAAA,GAAM,IAAI,KAAA,CAAM,MAAA,CAAO,GAAG,CAAC,CAAA,EAAG,IAAA,CAAK,EAAA,CAAG,CAAC,CAAA;AAC7C,IAAA,MAAM,QACJ,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,CAAC,CAAA,CACrB,QAAA;AACF,IAAA,MAAM,YACJ,GAAA,CAAI,KAAA,CAAM,MAAA,CAAO,EAAA,CAAG,CAAC,CAAA,CACrB,OAAA;AACF,IAAA,MAAM,IAAIC,iBAAA;AAAA,MACR,CAAA,sEAAA,EAAyE,GAAG,CAAA,+BAAA,EAAkC,KAAK,mDAAmD,SAAA,CAAU,IAAA;AAAA,QAC9K;AAAA,OACD,CAAA,EAAA;AAAA,KACH;AAAA,EACF;AAEA,EAAA,OAAO,wBAAA;AACT;;;;"}
1
+ {"version":3,"file":"utils.cjs.js","sources":["../../../src/entrypoints/auditor/utils.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport type { Config } from '@backstage/config';\nimport { InputError } from '@backstage/errors';\nimport { z } from 'zod/v4';\n\nconst CONFIG_ROOT_KEY = 'backend.auditor';\n\nconst logLevel = z.enum(['debug', 'info', 'warn', 'error']);\n\nconst severityLogLevelMappingsSchema = z.object({\n low: logLevel.default('debug'),\n medium: logLevel.default('info'),\n high: logLevel.default('info'),\n critical: logLevel.default('info'),\n});\n\ntype SeverityLogLevelMappings = z.infer<typeof severityLogLevelMappingsSchema>;\n\n/**\n * Gets the `backend.auditor.severityLogLevelMappings` configuration.\n *\n * @param config - The root Backstage {@link @backstage/config#Config} object.\n * @returns The validated severity-to-log-level mappings.\n * @throws error - {@link @backstage/errors#InputError} if the mapping configuration is invalid.\n */\nexport function getSeverityLogLevelMappings(\n config: Config,\n): SeverityLogLevelMappings {\n const auditorConfig = config.getOptionalConfig(CONFIG_ROOT_KEY);\n\n const input = {\n low: auditorConfig?.getOptionalString('severityLogLevelMappings.low'),\n medium: auditorConfig?.getOptionalString('severityLogLevelMappings.medium'),\n high: auditorConfig?.getOptionalString('severityLogLevelMappings.high'),\n critical: auditorConfig?.getOptionalString(\n 'severityLogLevelMappings.critical',\n ),\n };\n\n const parsed = severityLogLevelMappingsSchema.safeParse(input);\n\n if (!parsed.success) {\n const issue = parsed.error.issues[0];\n const key = issue.path[0] as keyof typeof input;\n const receivedValue = input[key];\n throw new InputError(\n `The configuration value for '${CONFIG_ROOT_KEY}.severityLogLevelMappings.${key}' was given an invalid value: '${receivedValue}'. Expected one of the following valid values: '${logLevel.options.join(\n ', ',\n )}'.`,\n );\n }\n\n return parsed.data;\n}\n"],"names":["z","InputError"],"mappings":";;;;;AAoBA,MAAM,eAAA,GAAkB,iBAAA;AAExB,MAAM,QAAA,GAAWA,KAAE,IAAA,CAAK,CAAC,SAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,CAAC,CAAA;AAE1D,MAAM,8BAAA,GAAiCA,KAAE,MAAA,CAAO;AAAA,EAC9C,GAAA,EAAK,QAAA,CAAS,OAAA,CAAQ,OAAO,CAAA;AAAA,EAC7B,MAAA,EAAQ,QAAA,CAAS,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC/B,IAAA,EAAM,QAAA,CAAS,OAAA,CAAQ,MAAM,CAAA;AAAA,EAC7B,QAAA,EAAU,QAAA,CAAS,OAAA,CAAQ,MAAM;AACnC,CAAC,CAAA;AAWM,SAAS,4BACd,MAAA,EAC0B;AAC1B,EAAA,MAAM,aAAA,GAAgB,MAAA,CAAO,iBAAA,CAAkB,eAAe,CAAA;AAE9D,EAAA,MAAM,KAAA,GAAQ;AAAA,IACZ,GAAA,EAAK,aAAA,EAAe,iBAAA,CAAkB,8BAA8B,CAAA;AAAA,IACpE,MAAA,EAAQ,aAAA,EAAe,iBAAA,CAAkB,iCAAiC,CAAA;AAAA,IAC1E,IAAA,EAAM,aAAA,EAAe,iBAAA,CAAkB,+BAA+B,CAAA;AAAA,IACtE,UAAU,aAAA,EAAe,iBAAA;AAAA,MACvB;AAAA;AACF,GACF;AAEA,EAAA,MAAM,MAAA,GAAS,8BAAA,CAA+B,SAAA,CAAU,KAAK,CAAA;AAE7D,EAAA,IAAI,CAAC,OAAO,OAAA,EAAS;AACnB,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,MAAA,CAAO,CAAC,CAAA;AACnC,IAAA,MAAM,GAAA,GAAM,KAAA,CAAM,IAAA,CAAK,CAAC,CAAA;AACxB,IAAA,MAAM,aAAA,GAAgB,MAAM,GAAG,CAAA;AAC/B,IAAA,MAAM,IAAIC,iBAAA;AAAA,MACR,CAAA,6BAAA,EAAgC,eAAe,CAAA,0BAAA,EAA6B,GAAG,kCAAkC,aAAa,CAAA,gDAAA,EAAmD,SAAS,OAAA,CAAQ,IAAA;AAAA,QAChM;AAAA,OACD,CAAA,EAAA;AAAA,KACH;AAAA,EACF;AAEA,EAAA,OAAO,MAAA,CAAO,IAAA;AAChB;;;;"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  var cron = require('cron');
4
4
  var luxon = require('luxon');
5
- var v3 = require('zod/v3');
5
+ var v4 = require('zod/v4');
6
6
 
7
7
  function isValidOptionalDurationString(d) {
8
8
  try {
@@ -25,33 +25,33 @@ function isValidCronFormat(c) {
25
25
  function isValidTrigger(t) {
26
26
  return t === "manual";
27
27
  }
28
- v3.z.object({
29
- version: v3.z.literal(1),
30
- initialDelayDuration: v3.z.string().optional().refine(isValidOptionalDurationString, {
28
+ v4.z.object({
29
+ version: v4.z.literal(1),
30
+ initialDelayDuration: v4.z.string().optional().refine(isValidOptionalDurationString, {
31
31
  message: "Invalid duration, expecting ISO Period"
32
32
  }),
33
- recurringAtMostEveryDuration: v3.z.string().refine(isValidOptionalDurationString, {
33
+ recurringAtMostEveryDuration: v4.z.string().refine(isValidOptionalDurationString, {
34
34
  message: "Invalid duration, expecting ISO Period"
35
35
  }),
36
- timeoutAfterDuration: v3.z.string().refine(isValidOptionalDurationString, {
36
+ timeoutAfterDuration: v4.z.string().refine(isValidOptionalDurationString, {
37
37
  message: "Invalid duration, expecting ISO Period"
38
38
  })
39
39
  });
40
- const taskSettingsV2Schema = v3.z.object({
41
- version: v3.z.literal(2),
42
- cadence: v3.z.string().refine(isValidCronFormat, { message: "Invalid cron" }).or(
43
- v3.z.string().refine(isValidTrigger, {
40
+ const taskSettingsV2Schema = v4.z.object({
41
+ version: v4.z.literal(2),
42
+ cadence: v4.z.string().refine(isValidCronFormat, { message: "Invalid cron" }).or(
43
+ v4.z.string().refine(isValidTrigger, {
44
44
  message: "Invalid trigger, expecting 'manual'"
45
45
  })
46
46
  ).or(
47
- v3.z.string().refine(isValidOptionalDurationString, {
47
+ v4.z.string().refine(isValidOptionalDurationString, {
48
48
  message: "Invalid duration, expecting ISO Period"
49
49
  })
50
50
  ),
51
- timeoutAfterDuration: v3.z.string().refine(isValidOptionalDurationString, {
51
+ timeoutAfterDuration: v4.z.string().refine(isValidOptionalDurationString, {
52
52
  message: "Invalid duration, expecting ISO Period"
53
53
  }),
54
- initialDelayDuration: v3.z.string().optional().refine(isValidOptionalDurationString, {
54
+ initialDelayDuration: v4.z.string().optional().refine(isValidOptionalDurationString, {
55
55
  message: "Invalid duration, expecting ISO Period"
56
56
  })
57
57
  });
@@ -1 +1 @@
1
- {"version":3,"file":"types.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JsonObject } from '@backstage/types';\nimport { CronTime } from 'cron';\nimport { Duration } from 'luxon';\nimport { z } from 'zod/v3';\n\nfunction isValidOptionalDurationString(d: string | undefined): boolean {\n try {\n return !d || Duration.fromISO(d).isValid;\n } catch {\n return false;\n }\n}\n\nfunction isValidCronFormat(c: string | undefined): boolean {\n try {\n if (!c) {\n return false;\n }\n // parse cron format to ensure it's a valid format.\n // eslint-disable-next-line no-new\n new CronTime(c);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidTrigger(t: string): boolean {\n return t === 'manual';\n}\n\nexport const taskSettingsV1Schema = z.object({\n version: z.literal(1),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n recurringAtMostEveryDuration: z\n .string()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 1).\n */\nexport type TaskSettingsV1 = z.infer<typeof taskSettingsV1Schema>;\n\nexport const taskSettingsV2Schema = z.object({\n version: z.literal(2),\n cadence: z\n .string()\n .refine(isValidCronFormat, { message: 'Invalid cron' })\n .or(\n z.string().refine(isValidTrigger, {\n message: \"Invalid trigger, expecting 'manual'\",\n }),\n )\n .or(\n z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n ),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 2).\n */\nexport type TaskSettingsV2 = z.infer<typeof taskSettingsV2Schema>;\n\n/**\n * The shape of a task definition as returned by the service's REST API.\n */\nexport interface TaskApiTasksResponse {\n taskId: string;\n pluginId: string;\n scope: 'global' | 'local';\n settings: { version: number } & JsonObject;\n taskState:\n | {\n status: 'running';\n startedAt: string;\n timesOutAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | {\n status: 'idle';\n startsAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | null;\n workerState:\n | {\n status: 'initial-wait';\n }\n | {\n status: 'idle';\n }\n | {\n status: 'running';\n }\n | null;\n}\n"],"names":["Duration","CronTime","z"],"mappings":";;;;;;AAqBA,SAAS,8BAA8B,CAAA,EAAgC;AACrE,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,CAAA,IAAKA,cAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,CAAA,EAAgC;AACzD,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,CAAA,EAAG;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,IAAIC,cAAS,CAAC,CAAA;AACd,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,eAAe,CAAA,EAAoB;AAC1C,EAAA,OAAO,CAAA,KAAM,QAAA;AACf;AAEoCC,KAAE,MAAA,CAAO;AAAA,EAC3C,OAAA,EAASA,IAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,sBAAsBA,IAAA,CACnB,MAAA,GACA,QAAA,EAAS,CACT,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACH,4BAAA,EAA8BA,IAAA,CAC3B,MAAA,EAAO,CACP,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACH,oBAAA,EAAsBA,IAAA,CAAE,MAAA,EAAO,CAAE,OAAO,6BAAA,EAA+B;AAAA,IACrE,OAAA,EAAS;AAAA,GACV;AACH,CAAC;AAOM,MAAM,oBAAA,GAAuBA,KAAE,MAAA,CAAO;AAAA,EAC3C,OAAA,EAASA,IAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,OAAA,EAASA,IAAA,CACN,MAAA,EAAO,CACP,MAAA,CAAO,mBAAmB,EAAE,OAAA,EAAS,cAAA,EAAgB,CAAA,CACrD,EAAA;AAAA,IACCA,IAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,cAAA,EAAgB;AAAA,MAChC,OAAA,EAAS;AAAA,KACV;AAAA,GACH,CACC,EAAA;AAAA,IACCA,IAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,6BAAA,EAA+B;AAAA,MAC/C,OAAA,EAAS;AAAA,KACV;AAAA,GACH;AAAA,EACF,oBAAA,EAAsBA,IAAA,CAAE,MAAA,EAAO,CAAE,OAAO,6BAAA,EAA+B;AAAA,IACrE,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACD,sBAAsBA,IAAA,CACnB,MAAA,GACA,QAAA,EAAS,CACT,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV;AACL,CAAC;;;;"}
1
+ {"version":3,"file":"types.cjs.js","sources":["../../../../src/entrypoints/scheduler/lib/types.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JsonObject } from '@backstage/types';\nimport { CronTime } from 'cron';\nimport { Duration } from 'luxon';\nimport { z } from 'zod/v4';\n\nfunction isValidOptionalDurationString(d: string | undefined): boolean {\n try {\n return !d || Duration.fromISO(d).isValid;\n } catch {\n return false;\n }\n}\n\nfunction isValidCronFormat(c: string | undefined): boolean {\n try {\n if (!c) {\n return false;\n }\n // parse cron format to ensure it's a valid format.\n // eslint-disable-next-line no-new\n new CronTime(c);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction isValidTrigger(t: string): boolean {\n return t === 'manual';\n}\n\nexport const taskSettingsV1Schema = z.object({\n version: z.literal(1),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n recurringAtMostEveryDuration: z\n .string()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 1).\n */\nexport type TaskSettingsV1 = z.infer<typeof taskSettingsV1Schema>;\n\nexport const taskSettingsV2Schema = z.object({\n version: z.literal(2),\n cadence: z\n .string()\n .refine(isValidCronFormat, { message: 'Invalid cron' })\n .or(\n z.string().refine(isValidTrigger, {\n message: \"Invalid trigger, expecting 'manual'\",\n }),\n )\n .or(\n z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n ),\n timeoutAfterDuration: z.string().refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n initialDelayDuration: z\n .string()\n .optional()\n .refine(isValidOptionalDurationString, {\n message: 'Invalid duration, expecting ISO Period',\n }),\n});\n\n/**\n * The properties that control a scheduled task (version 2).\n */\nexport type TaskSettingsV2 = z.infer<typeof taskSettingsV2Schema>;\n\n/**\n * The shape of a task definition as returned by the service's REST API.\n */\nexport interface TaskApiTasksResponse {\n taskId: string;\n pluginId: string;\n scope: 'global' | 'local';\n settings: { version: number } & JsonObject;\n taskState:\n | {\n status: 'running';\n startedAt: string;\n timesOutAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | {\n status: 'idle';\n startsAt?: string;\n lastRunError?: string;\n lastRunEndedAt?: string;\n }\n | null;\n workerState:\n | {\n status: 'initial-wait';\n }\n | {\n status: 'idle';\n }\n | {\n status: 'running';\n }\n | null;\n}\n"],"names":["Duration","CronTime","z"],"mappings":";;;;;;AAqBA,SAAS,8BAA8B,CAAA,EAAgC;AACrE,EAAA,IAAI;AACF,IAAA,OAAO,CAAC,CAAA,IAAKA,cAAA,CAAS,OAAA,CAAQ,CAAC,CAAA,CAAE,OAAA;AAAA,EACnC,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,kBAAkB,CAAA,EAAgC;AACzD,EAAA,IAAI;AACF,IAAA,IAAI,CAAC,CAAA,EAAG;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAGA,IAAA,IAAIC,cAAS,CAAC,CAAA;AACd,IAAA,OAAO,IAAA;AAAA,EACT,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,eAAe,CAAA,EAAoB;AAC1C,EAAA,OAAO,CAAA,KAAM,QAAA;AACf;AAEoCC,KAAE,MAAA,CAAO;AAAA,EAC3C,OAAA,EAASA,IAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,sBAAsBA,IAAA,CACnB,MAAA,GACA,QAAA,EAAS,CACT,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACH,4BAAA,EAA8BA,IAAA,CAC3B,MAAA,EAAO,CACP,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACH,oBAAA,EAAsBA,IAAA,CAAE,MAAA,EAAO,CAAE,OAAO,6BAAA,EAA+B;AAAA,IACrE,OAAA,EAAS;AAAA,GACV;AACH,CAAC;AAOM,MAAM,oBAAA,GAAuBA,KAAE,MAAA,CAAO;AAAA,EAC3C,OAAA,EAASA,IAAA,CAAE,OAAA,CAAQ,CAAC,CAAA;AAAA,EACpB,OAAA,EAASA,IAAA,CACN,MAAA,EAAO,CACP,MAAA,CAAO,mBAAmB,EAAE,OAAA,EAAS,cAAA,EAAgB,CAAA,CACrD,EAAA;AAAA,IACCA,IAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,cAAA,EAAgB;AAAA,MAChC,OAAA,EAAS;AAAA,KACV;AAAA,GACH,CACC,EAAA;AAAA,IACCA,IAAA,CAAE,MAAA,EAAO,CAAE,MAAA,CAAO,6BAAA,EAA+B;AAAA,MAC/C,OAAA,EAAS;AAAA,KACV;AAAA,GACH;AAAA,EACF,oBAAA,EAAsBA,IAAA,CAAE,MAAA,EAAO,CAAE,OAAO,6BAAA,EAA+B;AAAA,IACrE,OAAA,EAAS;AAAA,GACV,CAAA;AAAA,EACD,sBAAsBA,IAAA,CACnB,MAAA,GACA,QAAA,EAAS,CACT,OAAO,6BAAA,EAA+B;AAAA,IACrC,OAAA,EAAS;AAAA,GACV;AACL,CAAC;;;;"}
@@ -15,7 +15,7 @@ function parseUrl(url, config) {
15
15
  const parsedUrl = new URL(url);
16
16
  const pathname = parsedUrl.pathname.substring(1);
17
17
  const host = parsedUrl.host;
18
- if (config.host === "amazonaws.com" || config.host === "amazonaws.com.cn") {
18
+ if (config.host === "amazonaws.com" || config.host === "amazonaws.com.cn" || config.host.endsWith(".amazonaws.com") || config.host.endsWith(".amazonaws.com.cn")) {
19
19
  const match = host.match(
20
20
  /^(?:([a-z0-9.-]+)\.)?s3(?:[.-]([a-z0-9-]+))?\.amazonaws\.com(\.cn)?$/
21
21
  );
@@ -1 +1 @@
1
- {"version":3,"file":"AwsS3UrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/AwsS3UrlReader.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport {\n AwsS3Integration,\n ScmIntegrations,\n AwsS3IntegrationConfig,\n} from '@backstage/integration';\nimport {\n assertError,\n ForwardedError,\n NotModifiedError,\n} from '@backstage/errors';\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport { AwsCredentialIdentityProvider } from '@aws-sdk/types';\nimport {\n S3Client,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n GetObjectCommand,\n GetObjectCommandInput,\n} from '@aws-sdk/client-s3';\nimport { AbortController } from '@aws-sdk/abort-controller';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { Readable } from 'node:stream';\nimport { relative } from 'node:path/posix';\n\nexport const DEFAULT_REGION = 'us-east-1';\n\n/**\n * Path style URLs: https://s3.(region).amazonaws.com/(bucket)/(key)\n * The region can also be on the old form: https://s3-(region).amazonaws.com/(bucket)/(key)\n * Virtual hosted style URLs: https://(bucket).s3.(region).amazonaws.com/(key)\n * See https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access\n */\nexport function parseUrl(\n url: string,\n config: AwsS3IntegrationConfig,\n): { path: string; bucket: string; region: string } {\n const parsedUrl = new URL(url);\n\n /**\n * Removes the leading '/' from the pathname to be processed\n * as a parameter by AWS S3 SDK getObject method.\n */\n const pathname = parsedUrl.pathname.substring(1);\n const host = parsedUrl.host;\n\n // Treat Amazon hosted separately because it has special region logic\n if (config.host === 'amazonaws.com' || config.host === 'amazonaws.com.cn') {\n const match = host.match(\n /^(?:([a-z0-9.-]+)\\.)?s3(?:[.-]([a-z0-9-]+))?\\.amazonaws\\.com(\\.cn)?$/,\n );\n if (!match) {\n throw new Error(`Invalid AWS S3 URL ${url}`);\n }\n\n const [, hostBucket, hostRegion] = match;\n\n if (config.s3ForcePathStyle || !hostBucket) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: hostBucket,\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n const usePathStyle =\n config.s3ForcePathStyle || host.length === config.host.length;\n\n if (usePathStyle) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: host.substring(0, host.length - config.host.length - 1),\n region: DEFAULT_REGION,\n };\n}\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for AWS S3 buckets.\n *\n * @public\n */\nexport class AwsS3UrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n const credsManager = DefaultAwsCredentialsManager.fromConfig(config);\n\n return integrations.awsS3.list().map(integration => {\n const reader = new AwsS3UrlReader(credsManager, integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) =>\n url.host.endsWith(integration.config.host);\n return { reader, predicate };\n });\n };\n\n private readonly credsManager: AwsCredentialsManager;\n private readonly integration: AwsS3Integration;\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n };\n\n constructor(\n credsManager: AwsCredentialsManager,\n integration: AwsS3Integration,\n deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\n ) {\n this.credsManager = credsManager;\n this.integration = integration;\n this.deps = deps;\n }\n\n /**\n * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:\n * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html\n */\n private static buildStaticCredentials(\n accessKeyId: string,\n secretAccessKey: string,\n ): AwsCredentialIdentityProvider {\n return async () => {\n return {\n accessKeyId,\n secretAccessKey,\n };\n };\n }\n\n private static async buildCredentials(\n credsManager: AwsCredentialsManager,\n region: string,\n integration?: AwsS3Integration,\n ): Promise<AwsCredentialIdentityProvider> {\n // Fall back to the default credential chain if neither account ID\n // nor explicit credentials are provided\n if (!integration) {\n return (await credsManager.getCredentialProvider()).sdkCredentialProvider;\n }\n\n const accessKeyId = integration.config.accessKeyId;\n const secretAccessKey = integration.config.secretAccessKey;\n let explicitCredentials: AwsCredentialIdentityProvider;\n if (accessKeyId && secretAccessKey) {\n explicitCredentials = AwsS3UrlReader.buildStaticCredentials(\n accessKeyId,\n secretAccessKey,\n );\n } else {\n explicitCredentials = (await credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const roleArn = integration.config.roleArn;\n if (roleArn) {\n return fromTemporaryCredentials({\n masterCredentials: explicitCredentials,\n params: {\n RoleSessionName: 'backstage-aws-s3-url-reader',\n RoleArn: roleArn,\n ExternalId: integration.config.externalId,\n },\n clientConfig: { region },\n });\n }\n\n return explicitCredentials;\n }\n\n private async buildS3Client(\n credsManager: AwsCredentialsManager,\n region: string,\n integration: AwsS3Integration,\n ): Promise<S3Client> {\n const credentials = await AwsS3UrlReader.buildCredentials(\n credsManager,\n region,\n integration,\n );\n\n const s3 = new S3Client({\n customUserAgent: 'backstage-aws-s3-url-reader',\n region: region,\n credentials: credentials,\n endpoint: integration.config.endpoint,\n forcePathStyle: integration.config.s3ForcePathStyle,\n });\n return s3;\n }\n\n private async retrieveS3ObjectData(stream: Readable): Promise<Readable> {\n return new Promise((resolve, reject) => {\n try {\n const chunks: any[] = [];\n stream.on('data', chunk => chunks.push(chunk));\n stream.on('error', (e: Error) =>\n reject(new ForwardedError('Unable to read stream', e)),\n );\n stream.on('end', () => resolve(Readable.from(Buffer.concat(chunks))));\n } catch (e) {\n throw new ForwardedError('Unable to parse the response data', e);\n }\n });\n }\n\n async read(url: string): Promise<Buffer> {\n const response = await this.readUrl(url);\n return response.buffer();\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const { etag, lastModifiedAfter } = options ?? {};\n\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n\n const params: GetObjectCommandInput = {\n Bucket: bucket,\n Key: path,\n ...(etag && { IfNoneMatch: etag }),\n ...(lastModifiedAfter && {\n IfModifiedSince: lastModifiedAfter,\n }),\n };\n\n options?.signal?.addEventListener('abort', () => abortController.abort());\n const getObjectCommand = new GetObjectCommand(params);\n const response = await s3Client.send(getObjectCommand, {\n abortSignal: abortController.signal,\n });\n\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n return ReadUrlResponseFactory.fromReadable(s3ObjectData, {\n etag: response.ETag,\n lastModifiedAt: response.LastModified,\n });\n } catch (e) {\n if (e.$metadata && e.$metadata.httpStatusCode === 304) {\n throw new NotModifiedError();\n }\n\n throw new ForwardedError('Could not retrieve file from S3', e);\n }\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n const allObjects: String[] = [];\n const responses = [];\n let continuationToken: string | undefined;\n let output: ListObjectsV2CommandOutput;\n do {\n const listObjectsV2Command = new ListObjectsV2Command({\n Bucket: bucket,\n ContinuationToken: continuationToken,\n Prefix: path,\n });\n options?.signal?.addEventListener('abort', () =>\n abortController.abort(),\n );\n output = await s3Client.send(listObjectsV2Command, {\n abortSignal: abortController.signal,\n });\n if (output.Contents) {\n output.Contents.forEach(contents => {\n allObjects.push(contents.Key!);\n });\n }\n continuationToken = output.NextContinuationToken;\n } while (continuationToken);\n\n for (let i = 0; i < allObjects.length; i++) {\n const getObjectCommand = new GetObjectCommand({\n Bucket: bucket,\n Key: String(allObjects[i]),\n });\n const response = await s3Client.send(getObjectCommand);\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n responses.push({\n data: s3ObjectData,\n path: relative(path, String(allObjects[i])),\n lastModifiedAt: response?.LastModified ?? undefined,\n });\n }\n\n return await this.deps.treeResponseFactory.fromReadableArray(responses);\n } catch (e) {\n throw new ForwardedError('Could not retrieve file tree from S3', e);\n }\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { path } = parseUrl(url, this.integration.config);\n\n if (path.match(/[*?]/)) {\n throw new Error('Unsupported search pattern URL');\n }\n\n try {\n const data = await this.readUrl(url, options);\n\n return {\n files: [\n {\n url: url,\n content: data.buffer,\n lastModifiedAt: data.lastModifiedAt,\n },\n ],\n etag: data.etag ?? '',\n };\n } catch (error) {\n assertError(error);\n if (error.name === 'NotFoundError') {\n return {\n files: [],\n etag: '',\n };\n }\n throw error;\n }\n }\n\n toString() {\n const secretAccessKey = this.integration.config.secretAccessKey;\n return `awsS3{host=${this.integration.config.host},authed=${Boolean(\n secretAccessKey,\n )}}`;\n }\n}\n"],"names":["ScmIntegrations","DefaultAwsCredentialsManager","fromTemporaryCredentials","S3Client","ForwardedError","Readable","abortController","AbortController","GetObjectCommand","ReadUrlResponseFactory","NotModifiedError","ListObjectsV2Command","relative","assertError"],"mappings":"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"}
1
+ {"version":3,"file":"AwsS3UrlReader.cjs.js","sources":["../../../../src/entrypoints/urlReader/lib/AwsS3UrlReader.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n UrlReaderService,\n UrlReaderServiceReadTreeOptions,\n UrlReaderServiceReadTreeResponse,\n UrlReaderServiceReadUrlOptions,\n UrlReaderServiceReadUrlResponse,\n UrlReaderServiceSearchOptions,\n UrlReaderServiceSearchResponse,\n} from '@backstage/backend-plugin-api';\nimport { ReaderFactory, ReadTreeResponseFactory } from './types';\nimport {\n AwsCredentialsManager,\n DefaultAwsCredentialsManager,\n} from '@backstage/integration-aws-node';\nimport {\n AwsS3Integration,\n ScmIntegrations,\n AwsS3IntegrationConfig,\n} from '@backstage/integration';\nimport {\n assertError,\n ForwardedError,\n NotModifiedError,\n} from '@backstage/errors';\nimport { fromTemporaryCredentials } from '@aws-sdk/credential-providers';\nimport { AwsCredentialIdentityProvider } from '@aws-sdk/types';\nimport {\n S3Client,\n ListObjectsV2Command,\n ListObjectsV2CommandOutput,\n GetObjectCommand,\n GetObjectCommandInput,\n} from '@aws-sdk/client-s3';\nimport { AbortController } from '@aws-sdk/abort-controller';\nimport { ReadUrlResponseFactory } from './ReadUrlResponseFactory';\nimport { Readable } from 'node:stream';\nimport { relative } from 'node:path/posix';\n\nexport const DEFAULT_REGION = 'us-east-1';\n\n/**\n * Path style URLs: https://s3.(region).amazonaws.com/(bucket)/(key)\n * The region can also be on the old form: https://s3-(region).amazonaws.com/(bucket)/(key)\n * Virtual hosted style URLs: https://(bucket).s3.(region).amazonaws.com/(key)\n * See https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access\n */\nexport function parseUrl(\n url: string,\n config: AwsS3IntegrationConfig,\n): { path: string; bucket: string; region: string } {\n const parsedUrl = new URL(url);\n\n /**\n * Removes the leading '/' from the pathname to be processed\n * as a parameter by AWS S3 SDK getObject method.\n */\n const pathname = parsedUrl.pathname.substring(1);\n const host = parsedUrl.host;\n\n // Treat Amazon hosted separately because it has special region logic\n if (\n config.host === 'amazonaws.com' ||\n config.host === 'amazonaws.com.cn' ||\n config.host.endsWith('.amazonaws.com') ||\n config.host.endsWith('.amazonaws.com.cn')\n ) {\n const match = host.match(\n /^(?:([a-z0-9.-]+)\\.)?s3(?:[.-]([a-z0-9-]+))?\\.amazonaws\\.com(\\.cn)?$/,\n );\n if (!match) {\n throw new Error(`Invalid AWS S3 URL ${url}`);\n }\n\n const [, hostBucket, hostRegion] = match;\n\n if (config.s3ForcePathStyle || !hostBucket) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: hostBucket,\n region: hostRegion ?? DEFAULT_REGION,\n };\n }\n\n const usePathStyle =\n config.s3ForcePathStyle || host.length === config.host.length;\n\n if (usePathStyle) {\n const slashIndex = pathname.indexOf('/');\n if (slashIndex < 0) {\n throw new Error(\n `Invalid path-style AWS S3 URL ${url}, does not contain bucket in the path`,\n );\n }\n\n return {\n path: pathname.substring(slashIndex + 1),\n bucket: pathname.substring(0, slashIndex),\n region: DEFAULT_REGION,\n };\n }\n\n return {\n path: pathname,\n bucket: host.substring(0, host.length - config.host.length - 1),\n region: DEFAULT_REGION,\n };\n}\n\n/**\n * Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for AWS S3 buckets.\n *\n * @public\n */\nexport class AwsS3UrlReader implements UrlReaderService {\n static factory: ReaderFactory = ({ config, treeResponseFactory }) => {\n const integrations = ScmIntegrations.fromConfig(config);\n const credsManager = DefaultAwsCredentialsManager.fromConfig(config);\n\n return integrations.awsS3.list().map(integration => {\n const reader = new AwsS3UrlReader(credsManager, integration, {\n treeResponseFactory,\n });\n const predicate = (url: URL) =>\n url.host.endsWith(integration.config.host);\n return { reader, predicate };\n });\n };\n\n private readonly credsManager: AwsCredentialsManager;\n private readonly integration: AwsS3Integration;\n private readonly deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n };\n\n constructor(\n credsManager: AwsCredentialsManager,\n integration: AwsS3Integration,\n deps: {\n treeResponseFactory: ReadTreeResponseFactory;\n },\n ) {\n this.credsManager = credsManager;\n this.integration = integration;\n this.deps = deps;\n }\n\n /**\n * If accessKeyId and secretAccessKey are missing, the standard credentials provider chain will be used:\n * https://docs.aws.amazon.com/AWSJavaSDK/latest/javadoc/com/amazonaws/auth/DefaultAWSCredentialsProviderChain.html\n */\n private static buildStaticCredentials(\n accessKeyId: string,\n secretAccessKey: string,\n ): AwsCredentialIdentityProvider {\n return async () => {\n return {\n accessKeyId,\n secretAccessKey,\n };\n };\n }\n\n private static async buildCredentials(\n credsManager: AwsCredentialsManager,\n region: string,\n integration?: AwsS3Integration,\n ): Promise<AwsCredentialIdentityProvider> {\n // Fall back to the default credential chain if neither account ID\n // nor explicit credentials are provided\n if (!integration) {\n return (await credsManager.getCredentialProvider()).sdkCredentialProvider;\n }\n\n const accessKeyId = integration.config.accessKeyId;\n const secretAccessKey = integration.config.secretAccessKey;\n let explicitCredentials: AwsCredentialIdentityProvider;\n if (accessKeyId && secretAccessKey) {\n explicitCredentials = AwsS3UrlReader.buildStaticCredentials(\n accessKeyId,\n secretAccessKey,\n );\n } else {\n explicitCredentials = (await credsManager.getCredentialProvider())\n .sdkCredentialProvider;\n }\n\n const roleArn = integration.config.roleArn;\n if (roleArn) {\n return fromTemporaryCredentials({\n masterCredentials: explicitCredentials,\n params: {\n RoleSessionName: 'backstage-aws-s3-url-reader',\n RoleArn: roleArn,\n ExternalId: integration.config.externalId,\n },\n clientConfig: { region },\n });\n }\n\n return explicitCredentials;\n }\n\n private async buildS3Client(\n credsManager: AwsCredentialsManager,\n region: string,\n integration: AwsS3Integration,\n ): Promise<S3Client> {\n const credentials = await AwsS3UrlReader.buildCredentials(\n credsManager,\n region,\n integration,\n );\n\n const s3 = new S3Client({\n customUserAgent: 'backstage-aws-s3-url-reader',\n region: region,\n credentials: credentials,\n endpoint: integration.config.endpoint,\n forcePathStyle: integration.config.s3ForcePathStyle,\n });\n return s3;\n }\n\n private async retrieveS3ObjectData(stream: Readable): Promise<Readable> {\n return new Promise((resolve, reject) => {\n try {\n const chunks: any[] = [];\n stream.on('data', chunk => chunks.push(chunk));\n stream.on('error', (e: Error) =>\n reject(new ForwardedError('Unable to read stream', e)),\n );\n stream.on('end', () => resolve(Readable.from(Buffer.concat(chunks))));\n } catch (e) {\n throw new ForwardedError('Unable to parse the response data', e);\n }\n });\n }\n\n async read(url: string): Promise<Buffer> {\n const response = await this.readUrl(url);\n return response.buffer();\n }\n\n async readUrl(\n url: string,\n options?: UrlReaderServiceReadUrlOptions,\n ): Promise<UrlReaderServiceReadUrlResponse> {\n const { etag, lastModifiedAfter } = options ?? {};\n\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n\n const params: GetObjectCommandInput = {\n Bucket: bucket,\n Key: path,\n ...(etag && { IfNoneMatch: etag }),\n ...(lastModifiedAfter && {\n IfModifiedSince: lastModifiedAfter,\n }),\n };\n\n options?.signal?.addEventListener('abort', () => abortController.abort());\n const getObjectCommand = new GetObjectCommand(params);\n const response = await s3Client.send(getObjectCommand, {\n abortSignal: abortController.signal,\n });\n\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n return ReadUrlResponseFactory.fromReadable(s3ObjectData, {\n etag: response.ETag,\n lastModifiedAt: response.LastModified,\n });\n } catch (e) {\n if (e.$metadata && e.$metadata.httpStatusCode === 304) {\n throw new NotModifiedError();\n }\n\n throw new ForwardedError('Could not retrieve file from S3', e);\n }\n }\n\n async readTree(\n url: string,\n options?: UrlReaderServiceReadTreeOptions,\n ): Promise<UrlReaderServiceReadTreeResponse> {\n try {\n const { path, bucket, region } = parseUrl(url, this.integration.config);\n const s3Client = await this.buildS3Client(\n this.credsManager,\n region,\n this.integration,\n );\n const abortController = new AbortController();\n const allObjects: String[] = [];\n const responses = [];\n let continuationToken: string | undefined;\n let output: ListObjectsV2CommandOutput;\n do {\n const listObjectsV2Command = new ListObjectsV2Command({\n Bucket: bucket,\n ContinuationToken: continuationToken,\n Prefix: path,\n });\n options?.signal?.addEventListener('abort', () =>\n abortController.abort(),\n );\n output = await s3Client.send(listObjectsV2Command, {\n abortSignal: abortController.signal,\n });\n if (output.Contents) {\n output.Contents.forEach(contents => {\n allObjects.push(contents.Key!);\n });\n }\n continuationToken = output.NextContinuationToken;\n } while (continuationToken);\n\n for (let i = 0; i < allObjects.length; i++) {\n const getObjectCommand = new GetObjectCommand({\n Bucket: bucket,\n Key: String(allObjects[i]),\n });\n const response = await s3Client.send(getObjectCommand);\n const s3ObjectData = await this.retrieveS3ObjectData(\n response.Body as Readable,\n );\n\n responses.push({\n data: s3ObjectData,\n path: relative(path, String(allObjects[i])),\n lastModifiedAt: response?.LastModified ?? undefined,\n });\n }\n\n return await this.deps.treeResponseFactory.fromReadableArray(responses);\n } catch (e) {\n throw new ForwardedError('Could not retrieve file tree from S3', e);\n }\n }\n\n async search(\n url: string,\n options?: UrlReaderServiceSearchOptions,\n ): Promise<UrlReaderServiceSearchResponse> {\n const { path } = parseUrl(url, this.integration.config);\n\n if (path.match(/[*?]/)) {\n throw new Error('Unsupported search pattern URL');\n }\n\n try {\n const data = await this.readUrl(url, options);\n\n return {\n files: [\n {\n url: url,\n content: data.buffer,\n lastModifiedAt: data.lastModifiedAt,\n },\n ],\n etag: data.etag ?? '',\n };\n } catch (error) {\n assertError(error);\n if (error.name === 'NotFoundError') {\n return {\n files: [],\n etag: '',\n };\n }\n throw error;\n }\n }\n\n toString() {\n const secretAccessKey = this.integration.config.secretAccessKey;\n return `awsS3{host=${this.integration.config.host},authed=${Boolean(\n secretAccessKey,\n )}}`;\n }\n}\n"],"names":["ScmIntegrations","DefaultAwsCredentialsManager","fromTemporaryCredentials","S3Client","ForwardedError","Readable","abortController","AbortController","GetObjectCommand","ReadUrlResponseFactory","NotModifiedError","ListObjectsV2Command","relative","assertError"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- var version = "0.16.1-next.0";
5
+ var version = "0.16.1-next.1";
6
6
  var packageinfo = {
7
7
  version: version};
8
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/backend-defaults",
3
- "version": "0.16.1-next.0",
3
+ "version": "0.16.1-next.1",
4
4
  "description": "Backend defaults used by Backstage backend apps",
5
5
  "backstage": {
6
6
  "role": "node-library"
@@ -217,19 +217,19 @@
217
217
  "@aws-sdk/types": "^3.347.0",
218
218
  "@azure/identity": "^4.0.0",
219
219
  "@azure/storage-blob": "^12.5.0",
220
- "@backstage/backend-app-api": "1.6.1-next.0",
220
+ "@backstage/backend-app-api": "1.6.1-next.1",
221
221
  "@backstage/backend-dev-utils": "0.1.7",
222
- "@backstage/backend-plugin-api": "1.8.1-next.0",
222
+ "@backstage/backend-plugin-api": "1.9.0-next.1",
223
223
  "@backstage/cli-node": "0.3.1-next.0",
224
224
  "@backstage/config": "1.3.6",
225
225
  "@backstage/config-loader": "1.10.10-next.0",
226
226
  "@backstage/errors": "1.2.7",
227
227
  "@backstage/integration": "2.0.0",
228
228
  "@backstage/integration-aws-node": "0.1.20",
229
- "@backstage/plugin-auth-node": "0.6.15-next.0",
230
- "@backstage/plugin-events-node": "0.4.21-next.0",
229
+ "@backstage/plugin-auth-node": "0.7.0-next.1",
230
+ "@backstage/plugin-events-node": "0.4.21-next.1",
231
231
  "@backstage/plugin-permission-common": "0.9.7",
232
- "@backstage/plugin-permission-node": "0.10.12-next.0",
232
+ "@backstage/plugin-permission-node": "0.10.12-next.1",
233
233
  "@backstage/types": "1.2.2",
234
234
  "@google-cloud/storage": "^7.0.0",
235
235
  "@keyv/memcache": "^2.0.1",
@@ -285,9 +285,9 @@
285
285
  },
286
286
  "devDependencies": {
287
287
  "@aws-sdk/util-stream-node": "^3.350.0",
288
- "@backstage/backend-plugin-api": "1.8.1-next.0",
289
- "@backstage/backend-test-utils": "1.11.2-next.0",
290
- "@backstage/cli": "0.36.1-next.0",
288
+ "@backstage/backend-plugin-api": "1.9.0-next.1",
289
+ "@backstage/backend-test-utils": "1.11.2-next.1",
290
+ "@backstage/cli": "0.36.1-next.1",
291
291
  "@google-cloud/cloud-sql-connector": "^1.4.0",
292
292
  "@types/archiver": "^7.0.0",
293
293
  "@types/base64-stream": "^1.0.2",
@@ -1,13 +0,0 @@
1
- 'use strict';
2
-
3
- var v3 = require('zod/v3');
4
-
5
- const severityLogLevelMappingsSchema = v3.z.record(
6
- v3.z.enum(["low", "medium", "high", "critical"]),
7
- v3.z.enum(["debug", "info", "warn", "error"])
8
- );
9
- const CONFIG_ROOT_KEY = "backend.auditor";
10
-
11
- exports.CONFIG_ROOT_KEY = CONFIG_ROOT_KEY;
12
- exports.severityLogLevelMappingsSchema = severityLogLevelMappingsSchema;
13
- //# sourceMappingURL=types.cjs.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.cjs.js","sources":["../../../src/entrypoints/auditor/types.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { z } from 'zod/v3';\n\n/** @internal */\nexport const severityLogLevelMappingsSchema = z.record(\n z.enum(['low', 'medium', 'high', 'critical']),\n z.enum(['debug', 'info', 'warn', 'error']),\n);\n\n/** @internal */\nexport const CONFIG_ROOT_KEY = 'backend.auditor';\n"],"names":["z"],"mappings":";;;;AAmBO,MAAM,iCAAiCA,IAAA,CAAE,MAAA;AAAA,EAC9CA,KAAE,IAAA,CAAK,CAAC,OAAO,QAAA,EAAU,MAAA,EAAQ,UAAU,CAAC,CAAA;AAAA,EAC5CA,KAAE,IAAA,CAAK,CAAC,SAAS,MAAA,EAAQ,MAAA,EAAQ,OAAO,CAAC;AAC3C;AAGO,MAAM,eAAA,GAAkB;;;;;"}