@backstage/backend-defaults 0.16.0-next.2 → 0.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +34 -0
- package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js +68 -19
- package/dist/alpha/entrypoints/actionsRegistry/DefaultActionsRegistryService.cjs.js.map +1 -1
- package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js +15 -3
- package/dist/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.cjs.js.map +1 -1
- package/dist/entrypoints/auditor/types.cjs.js +4 -4
- package/dist/entrypoints/auditor/types.cjs.js.map +1 -1
- package/dist/entrypoints/auditor/utils.cjs.js.map +1 -1
- package/dist/entrypoints/scheduler/lib/types.cjs.js +13 -13
- package/dist/entrypoints/scheduler/lib/types.cjs.js.map +1 -1
- package/dist/package.json.cjs.js +1 -1
- package/package.json +20 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,39 @@
|
|
|
1
1
|
# @backstage/backend-defaults
|
|
2
2
|
|
|
3
|
+
## 0.16.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 42960f1: The actions registry invoke endpoint now accepts direct user credentials in addition to service principals, enabling CLI and other direct user clients to invoke actions.
|
|
8
|
+
- 0e7d8f9: The scheduler service now uses the metrics service to create metrics, providing plugin-scoped attribution.
|
|
9
|
+
- 527cf88: **BREAKING** Removed deprecated `BitbucketUrlReader`. Use the `BitbucketCloudUrlReader` or the `BitbucketServerUrlReader` instead.
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- cc8348e: Added permissions integration to the actions registry. Actions registered with a `visibilityPermission` field are now checked against the permissions framework when listing and invoking. Denied actions are filtered from list results, and invoking a denied action returns a `404 Not Found` as if the action does not exist. Permissions are automatically registered with the `PermissionsRegistryService` so they appear in the permission policy system.
|
|
14
|
+
- dee4283: Added `pluginId` field to `ActionsServiceAction` type, populated from the registering plugin's metadata.
|
|
15
|
+
- 015668c: Added `cancelTask` method to the `SchedulerService` interface and implementation, allowing cancellation of currently running scheduled tasks. For global tasks, the database lock is released and a periodic liveness check aborts the running task function. For local tasks, the task's abort signal is triggered directly. A new `POST /.backstage/scheduler/v1/tasks/:id/cancel` endpoint is also available.
|
|
16
|
+
- 638e6c7: chore(deps): bump `yauzl` from 3.2.0 to 3.2.1
|
|
17
|
+
- 6738cf0: build(deps): bump `minimatch` from 9.0.5 to 10.2.1
|
|
18
|
+
- 62f0a53: Fixed error forwarding in the actions registry so that known errors like `InputError` and `NotFoundError` thrown by actions preserve their original status codes and messages instead of being wrapped in `ForwardedError` and coerced to 500.
|
|
19
|
+
- d933f62: Add configurable throttling and retry mechanism for GitLab integration.
|
|
20
|
+
- b99158a: Fixed `yarn backstage-cli config:check --strict --config app-config.yaml` config validation error by adding
|
|
21
|
+
an optional `default` type discriminator to PostgreSQL connection configuration,
|
|
22
|
+
allowing `config:check` to properly validate `default` connection configurations.
|
|
23
|
+
- 1ee5b28: Adds an alpha `MetricsService` to provide a unified interface for metrics instrumentation across Backstage plugins.
|
|
24
|
+
- 5fcbef2: Updated dependency `express-rate-limit` to `^8.0.0`.
|
|
25
|
+
- a49a40d: Updated dependency `zod` to `^3.25.76 || ^4.0.0` & migrated to `/v3` or `/v4` imports.
|
|
26
|
+
- Updated dependencies
|
|
27
|
+
- @backstage/backend-plugin-api@1.8.0
|
|
28
|
+
- @backstage/cli-node@0.3.0
|
|
29
|
+
- @backstage/integration@2.0.0
|
|
30
|
+
- @backstage/config-loader@1.10.9
|
|
31
|
+
- @backstage/plugin-permission-common@0.9.7
|
|
32
|
+
- @backstage/plugin-permission-node@0.10.11
|
|
33
|
+
- @backstage/plugin-auth-node@0.6.14
|
|
34
|
+
- @backstage/backend-app-api@1.6.0
|
|
35
|
+
- @backstage/plugin-events-node@0.4.20
|
|
36
|
+
|
|
3
37
|
## 0.16.0-next.2
|
|
4
38
|
|
|
5
39
|
### Patch Changes
|
|
@@ -2,9 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
var Router = require('express-promise-router');
|
|
4
4
|
var express = require('express');
|
|
5
|
-
var
|
|
5
|
+
var v3 = require('zod/v3');
|
|
6
6
|
var zodToJsonSchema = require('zod-to-json-schema');
|
|
7
7
|
var errors = require('@backstage/errors');
|
|
8
|
+
var pluginPermissionCommon = require('@backstage/plugin-permission-common');
|
|
8
9
|
|
|
9
10
|
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
|
|
10
11
|
|
|
@@ -17,28 +18,50 @@ class DefaultActionsRegistryService {
|
|
|
17
18
|
httpAuth;
|
|
18
19
|
auth;
|
|
19
20
|
metadata;
|
|
20
|
-
|
|
21
|
+
permissions;
|
|
22
|
+
permissionsRegistry;
|
|
23
|
+
constructor(logger, httpAuth, auth, metadata, permissions, permissionsRegistry) {
|
|
21
24
|
this.logger = logger;
|
|
22
25
|
this.httpAuth = httpAuth;
|
|
23
26
|
this.auth = auth;
|
|
24
27
|
this.metadata = metadata;
|
|
28
|
+
this.permissions = permissions;
|
|
29
|
+
this.permissionsRegistry = permissionsRegistry;
|
|
25
30
|
}
|
|
26
31
|
static create({
|
|
27
32
|
httpAuth,
|
|
28
33
|
logger,
|
|
29
34
|
auth,
|
|
30
|
-
metadata
|
|
35
|
+
metadata,
|
|
36
|
+
permissions,
|
|
37
|
+
permissionsRegistry
|
|
31
38
|
}) {
|
|
32
|
-
return new DefaultActionsRegistryService(
|
|
39
|
+
return new DefaultActionsRegistryService(
|
|
40
|
+
logger,
|
|
41
|
+
httpAuth,
|
|
42
|
+
auth,
|
|
43
|
+
metadata,
|
|
44
|
+
permissions,
|
|
45
|
+
permissionsRegistry
|
|
46
|
+
);
|
|
33
47
|
}
|
|
34
48
|
createRouter() {
|
|
35
49
|
const router = Router__default.default();
|
|
36
50
|
router.use(express.json());
|
|
37
|
-
router.get("/.backstage/actions/v1/actions", (
|
|
51
|
+
router.get("/.backstage/actions/v1/actions", async (req, res) => {
|
|
52
|
+
const credentials = await this.httpAuth.credentials(req);
|
|
53
|
+
const entries = Array.from(this.actions.entries());
|
|
54
|
+
const allowedActions = await this.filterByPermissions(
|
|
55
|
+
entries,
|
|
56
|
+
credentials
|
|
57
|
+
);
|
|
38
58
|
return res.json({
|
|
39
|
-
actions:
|
|
59
|
+
actions: allowedActions.map(([id, action]) => ({
|
|
40
60
|
id,
|
|
41
|
-
|
|
61
|
+
name: action.name,
|
|
62
|
+
title: action.title,
|
|
63
|
+
description: action.description,
|
|
64
|
+
pluginId: this.metadata.getId(),
|
|
42
65
|
attributes: {
|
|
43
66
|
// Inspired by the @modelcontextprotocol/sdk defaults for the hints.
|
|
44
67
|
// https://github.com/modelcontextprotocol/typescript-sdk/blob/dd69efa1de8646bb6b195ff8d5f52e13739f4550/src/types.ts#L777-L812
|
|
@@ -47,8 +70,8 @@ class DefaultActionsRegistryService {
|
|
|
47
70
|
readOnly: action.attributes?.readOnly ?? false
|
|
48
71
|
},
|
|
49
72
|
schema: {
|
|
50
|
-
input: action.schema?.input ? zodToJsonSchema__default.default(action.schema.input(
|
|
51
|
-
output: action.schema?.output ? zodToJsonSchema__default.default(action.schema.output(
|
|
73
|
+
input: action.schema?.input ? zodToJsonSchema__default.default(action.schema.input(v3.z)) : zodToJsonSchema__default.default(v3.z.object({})),
|
|
74
|
+
output: action.schema?.output ? zodToJsonSchema__default.default(action.schema.output(v3.z)) : zodToJsonSchema__default.default(v3.z.object({}))
|
|
52
75
|
}
|
|
53
76
|
}))
|
|
54
77
|
});
|
|
@@ -57,22 +80,27 @@ class DefaultActionsRegistryService {
|
|
|
57
80
|
"/.backstage/actions/v1/actions/:actionId/invoke",
|
|
58
81
|
async (req, res) => {
|
|
59
82
|
const credentials = await this.httpAuth.credentials(req);
|
|
60
|
-
if (this.auth.isPrincipal(credentials, "
|
|
61
|
-
if (!credentials.principal.actor) {
|
|
62
|
-
throw new errors.NotAllowedError(
|
|
63
|
-
`Actions must be invoked by a service, not a user`
|
|
64
|
-
);
|
|
65
|
-
}
|
|
66
|
-
} else if (this.auth.isPrincipal(credentials, "none")) {
|
|
83
|
+
if (this.auth.isPrincipal(credentials, "none")) {
|
|
67
84
|
throw new errors.NotAllowedError(
|
|
68
|
-
`Actions must be invoked by
|
|
85
|
+
`Actions must be invoked by an authenticated principal, not an anonymous request`
|
|
69
86
|
);
|
|
70
87
|
}
|
|
71
88
|
const action = this.actions.get(req.params.actionId);
|
|
72
89
|
if (!action) {
|
|
73
90
|
throw new errors.NotFoundError(`Action "${req.params.actionId}" not found`);
|
|
74
91
|
}
|
|
75
|
-
|
|
92
|
+
if (action.visibilityPermission) {
|
|
93
|
+
const [decision] = await this.permissions.authorize(
|
|
94
|
+
[{ permission: action.visibilityPermission }],
|
|
95
|
+
{ credentials }
|
|
96
|
+
);
|
|
97
|
+
if (decision.result !== pluginPermissionCommon.AuthorizeResult.ALLOW) {
|
|
98
|
+
throw new errors.NotFoundError(
|
|
99
|
+
`Action "${req.params.actionId}" not found`
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
const input = action.schema?.input ? action.schema.input(v3.z).safeParse(req.body) : { success: true, data: void 0 };
|
|
76
104
|
if (!input.success) {
|
|
77
105
|
throw new errors.InputError(
|
|
78
106
|
`Invalid input to action "${req.params.actionId}"`,
|
|
@@ -84,7 +112,7 @@ class DefaultActionsRegistryService {
|
|
|
84
112
|
credentials,
|
|
85
113
|
logger: this.logger
|
|
86
114
|
});
|
|
87
|
-
const output = action.schema?.output ? action.schema.output(
|
|
115
|
+
const output = action.schema?.output ? action.schema.output(v3.z).safeParse(result?.output) : { success: true, data: result?.output };
|
|
88
116
|
if (!output.success) {
|
|
89
117
|
throw new errors.InputError(
|
|
90
118
|
`Invalid output from action "${req.params.actionId}"`,
|
|
@@ -101,8 +129,29 @@ class DefaultActionsRegistryService {
|
|
|
101
129
|
if (this.actions.has(id)) {
|
|
102
130
|
throw new Error(`Action with id "${id}" is already registered`);
|
|
103
131
|
}
|
|
132
|
+
if (options.visibilityPermission) {
|
|
133
|
+
this.permissionsRegistry.addPermissions([options.visibilityPermission]);
|
|
134
|
+
}
|
|
104
135
|
this.actions.set(id, options);
|
|
105
136
|
}
|
|
137
|
+
async filterByPermissions(entries, credentials) {
|
|
138
|
+
const permissionedEntries = entries.filter(
|
|
139
|
+
([_, action]) => action.visibilityPermission
|
|
140
|
+
);
|
|
141
|
+
if (permissionedEntries.length === 0) {
|
|
142
|
+
return entries;
|
|
143
|
+
}
|
|
144
|
+
const decisions = await this.permissions.authorize(
|
|
145
|
+
permissionedEntries.map(([_, action]) => ({
|
|
146
|
+
permission: action.visibilityPermission
|
|
147
|
+
})),
|
|
148
|
+
{ credentials }
|
|
149
|
+
);
|
|
150
|
+
const deniedIds = new Set(
|
|
151
|
+
permissionedEntries.filter((_, index) => decisions[index].result !== pluginPermissionCommon.AuthorizeResult.ALLOW).map(([id]) => id)
|
|
152
|
+
);
|
|
153
|
+
return entries.filter(([id]) => !deniedIds.has(id));
|
|
154
|
+
}
|
|
106
155
|
}
|
|
107
156
|
|
|
108
157
|
exports.DefaultActionsRegistryService = DefaultActionsRegistryService;
|
|
@@ -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 HttpAuthService,\n LoggerService,\n PluginMetadataService,\n} from '@backstage/backend-plugin-api';\nimport PromiseRouter from 'express-promise-router';\nimport { Router, json } from 'express';\nimport { z, AnyZodObject } from 'zod';\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';\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\n private constructor(\n logger: LoggerService,\n httpAuth: HttpAuthService,\n auth: AuthService,\n metadata: PluginMetadataService,\n ) {\n this.logger = logger;\n this.httpAuth = httpAuth;\n this.auth = auth;\n this.metadata = metadata;\n }\n\n static create({\n httpAuth,\n logger,\n auth,\n metadata,\n }: {\n httpAuth: HttpAuthService;\n logger: LoggerService;\n auth: AuthService;\n metadata: PluginMetadataService;\n }): DefaultActionsRegistryService {\n return new DefaultActionsRegistryService(logger, httpAuth, auth, metadata);\n }\n\n createRouter(): Router {\n const router = PromiseRouter();\n router.use(json());\n\n router.get('/.backstage/actions/v1/actions', (_, res) => {\n return res.json({\n actions: Array.from(this.actions.entries()).map(([id, action]) => ({\n id,\n ...action,\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, 'user')) {\n if (!credentials.principal.actor) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, not a user`,\n );\n }\n } else if (this.auth.isPrincipal(credentials, 'none')) {\n throw new NotAllowedError(\n `Actions must be invoked by a service, 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 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 this.actions.set(id, options);\n }\n}\n"],"names":["PromiseRouter","json","zodToJsonSchema","z","NotAllowedError","NotFoundError","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 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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"}
|
|
@@ -11,14 +11,26 @@ const actionsRegistryServiceFactory = backendPluginApi.createServiceFactory({
|
|
|
11
11
|
httpRouter: backendPluginApi.coreServices.httpRouter,
|
|
12
12
|
httpAuth: backendPluginApi.coreServices.httpAuth,
|
|
13
13
|
logger: backendPluginApi.coreServices.logger,
|
|
14
|
-
auth: backendPluginApi.coreServices.auth
|
|
14
|
+
auth: backendPluginApi.coreServices.auth,
|
|
15
|
+
permissions: backendPluginApi.coreServices.permissions,
|
|
16
|
+
permissionsRegistry: backendPluginApi.coreServices.permissionsRegistry
|
|
15
17
|
},
|
|
16
|
-
factory: ({
|
|
18
|
+
factory: ({
|
|
19
|
+
metadata,
|
|
20
|
+
httpRouter,
|
|
21
|
+
httpAuth,
|
|
22
|
+
logger,
|
|
23
|
+
auth,
|
|
24
|
+
permissions,
|
|
25
|
+
permissionsRegistry
|
|
26
|
+
}) => {
|
|
17
27
|
const actionsRegistryService = DefaultActionsRegistryService.DefaultActionsRegistryService.create({
|
|
18
28
|
httpAuth,
|
|
19
29
|
logger,
|
|
20
30
|
auth,
|
|
21
|
-
metadata
|
|
31
|
+
metadata,
|
|
32
|
+
permissions,
|
|
33
|
+
permissionsRegistry
|
|
22
34
|
});
|
|
23
35
|
httpRouter.use(actionsRegistryService.createRouter());
|
|
24
36
|
return actionsRegistryService;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actionsRegistryServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.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 coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { DefaultActionsRegistryService } from './DefaultActionsRegistryService';\nimport { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsRegistryServiceFactory = createServiceFactory({\n service: actionsRegistryServiceRef,\n deps: {\n metadata: coreServices.pluginMetadata,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n logger: coreServices.logger,\n auth: coreServices.auth,\n },\n factory: ({
|
|
1
|
+
{"version":3,"file":"actionsRegistryServiceFactory.cjs.js","sources":["../../../../src/alpha/entrypoints/actionsRegistry/actionsRegistryServiceFactory.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 coreServices,\n createServiceFactory,\n} from '@backstage/backend-plugin-api';\nimport { DefaultActionsRegistryService } from './DefaultActionsRegistryService';\nimport { actionsRegistryServiceRef } from '@backstage/backend-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const actionsRegistryServiceFactory = createServiceFactory({\n service: actionsRegistryServiceRef,\n deps: {\n metadata: coreServices.pluginMetadata,\n httpRouter: coreServices.httpRouter,\n httpAuth: coreServices.httpAuth,\n logger: coreServices.logger,\n auth: coreServices.auth,\n permissions: coreServices.permissions,\n permissionsRegistry: coreServices.permissionsRegistry,\n },\n factory: ({\n metadata,\n httpRouter,\n httpAuth,\n logger,\n auth,\n permissions,\n permissionsRegistry,\n }) => {\n const actionsRegistryService = DefaultActionsRegistryService.create({\n httpAuth,\n logger,\n auth,\n metadata,\n permissions,\n permissionsRegistry,\n });\n\n httpRouter.use(actionsRegistryService.createRouter());\n\n return actionsRegistryService;\n },\n});\n"],"names":["createServiceFactory","actionsRegistryServiceRef","coreServices","DefaultActionsRegistryService"],"mappings":";;;;;;AA0BO,MAAM,gCAAgCA,qCAAA,CAAqB;AAAA,EAChE,OAAA,EAASC,+BAAA;AAAA,EACT,IAAA,EAAM;AAAA,IACJ,UAAUC,6BAAA,CAAa,cAAA;AAAA,IACvB,YAAYA,6BAAA,CAAa,UAAA;AAAA,IACzB,UAAUA,6BAAA,CAAa,QAAA;AAAA,IACvB,QAAQA,6BAAA,CAAa,MAAA;AAAA,IACrB,MAAMA,6BAAA,CAAa,IAAA;AAAA,IACnB,aAAaA,6BAAA,CAAa,WAAA;AAAA,IAC1B,qBAAqBA,6BAAA,CAAa;AAAA,GACpC;AAAA,EACA,SAAS,CAAC;AAAA,IACR,QAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,MAAA;AAAA,IACA,IAAA;AAAA,IACA,WAAA;AAAA,IACA;AAAA,GACF,KAAM;AACJ,IAAA,MAAM,sBAAA,GAAyBC,4DAA8B,MAAA,CAAO;AAAA,MAClE,QAAA;AAAA,MACA,MAAA;AAAA,MACA,IAAA;AAAA,MACA,QAAA;AAAA,MACA,WAAA;AAAA,MACA;AAAA,KACD,CAAA;AAED,IAAA,UAAA,CAAW,GAAA,CAAI,sBAAA,CAAuB,YAAA,EAAc,CAAA;AAEpD,IAAA,OAAO,sBAAA;AAAA,EACT;AACF,CAAC;;;;"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var v3 = require('zod/v3');
|
|
4
4
|
|
|
5
|
-
const severityLogLevelMappingsSchema =
|
|
6
|
-
|
|
7
|
-
|
|
5
|
+
const severityLogLevelMappingsSchema = v3.z.record(
|
|
6
|
+
v3.z.enum(["low", "medium", "high", "critical"]),
|
|
7
|
+
v3.z.enum(["debug", "info", "warn", "error"])
|
|
8
8
|
);
|
|
9
9
|
const CONFIG_ROOT_KEY = "backend.auditor";
|
|
10
10
|
|
|
@@ -1 +1 @@
|
|
|
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';\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,
|
|
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;;;;;"}
|
|
@@ -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';\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/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;;;;"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var cron = require('cron');
|
|
4
4
|
var luxon = require('luxon');
|
|
5
|
-
var
|
|
5
|
+
var v3 = require('zod/v3');
|
|
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
|
-
|
|
29
|
-
version:
|
|
30
|
-
initialDelayDuration:
|
|
28
|
+
v3.z.object({
|
|
29
|
+
version: v3.z.literal(1),
|
|
30
|
+
initialDelayDuration: v3.z.string().optional().refine(isValidOptionalDurationString, {
|
|
31
31
|
message: "Invalid duration, expecting ISO Period"
|
|
32
32
|
}),
|
|
33
|
-
recurringAtMostEveryDuration:
|
|
33
|
+
recurringAtMostEveryDuration: v3.z.string().refine(isValidOptionalDurationString, {
|
|
34
34
|
message: "Invalid duration, expecting ISO Period"
|
|
35
35
|
}),
|
|
36
|
-
timeoutAfterDuration:
|
|
36
|
+
timeoutAfterDuration: v3.z.string().refine(isValidOptionalDurationString, {
|
|
37
37
|
message: "Invalid duration, expecting ISO Period"
|
|
38
38
|
})
|
|
39
39
|
});
|
|
40
|
-
const taskSettingsV2Schema =
|
|
41
|
-
version:
|
|
42
|
-
cadence:
|
|
43
|
-
|
|
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, {
|
|
44
44
|
message: "Invalid trigger, expecting 'manual'"
|
|
45
45
|
})
|
|
46
46
|
).or(
|
|
47
|
-
|
|
47
|
+
v3.z.string().refine(isValidOptionalDurationString, {
|
|
48
48
|
message: "Invalid duration, expecting ISO Period"
|
|
49
49
|
})
|
|
50
50
|
),
|
|
51
|
-
timeoutAfterDuration:
|
|
51
|
+
timeoutAfterDuration: v3.z.string().refine(isValidOptionalDurationString, {
|
|
52
52
|
message: "Invalid duration, expecting ISO Period"
|
|
53
53
|
}),
|
|
54
|
-
initialDelayDuration:
|
|
54
|
+
initialDelayDuration: v3.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';\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,
|
|
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;;;;"}
|
package/dist/package.json.cjs.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/backend-defaults",
|
|
3
|
-
"version": "0.16.0
|
|
3
|
+
"version": "0.16.0",
|
|
4
4
|
"description": "Backend defaults used by Backstage backend apps",
|
|
5
5
|
"backstage": {
|
|
6
6
|
"role": "node-library"
|
|
@@ -217,19 +217,20 @@
|
|
|
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.0
|
|
221
|
-
"@backstage/backend-dev-utils": "0.1.7",
|
|
222
|
-
"@backstage/backend-plugin-api": "1.8.0
|
|
223
|
-
"@backstage/cli-node": "0.
|
|
224
|
-
"@backstage/config": "1.3.6",
|
|
225
|
-
"@backstage/config-loader": "1.10.9
|
|
226
|
-
"@backstage/errors": "1.2.7",
|
|
227
|
-
"@backstage/integration": "2.0.0
|
|
228
|
-
"@backstage/integration-aws-node": "0.1.20",
|
|
229
|
-
"@backstage/plugin-auth-node": "0.6.14
|
|
230
|
-
"@backstage/plugin-events-node": "0.4.20
|
|
231
|
-
"@backstage/plugin-permission-
|
|
232
|
-
"@backstage/
|
|
220
|
+
"@backstage/backend-app-api": "^1.6.0",
|
|
221
|
+
"@backstage/backend-dev-utils": "^0.1.7",
|
|
222
|
+
"@backstage/backend-plugin-api": "^1.8.0",
|
|
223
|
+
"@backstage/cli-node": "^0.3.0",
|
|
224
|
+
"@backstage/config": "^1.3.6",
|
|
225
|
+
"@backstage/config-loader": "^1.10.9",
|
|
226
|
+
"@backstage/errors": "^1.2.7",
|
|
227
|
+
"@backstage/integration": "^2.0.0",
|
|
228
|
+
"@backstage/integration-aws-node": "^0.1.20",
|
|
229
|
+
"@backstage/plugin-auth-node": "^0.6.14",
|
|
230
|
+
"@backstage/plugin-events-node": "^0.4.20",
|
|
231
|
+
"@backstage/plugin-permission-common": "^0.9.7",
|
|
232
|
+
"@backstage/plugin-permission-node": "^0.10.11",
|
|
233
|
+
"@backstage/types": "^1.2.2",
|
|
233
234
|
"@google-cloud/storage": "^7.0.0",
|
|
234
235
|
"@keyv/memcache": "^2.0.1",
|
|
235
236
|
"@keyv/redis": "^4.0.1",
|
|
@@ -277,16 +278,16 @@
|
|
|
277
278
|
"uuid": "^11.0.0",
|
|
278
279
|
"winston": "^3.2.1",
|
|
279
280
|
"winston-transport": "^4.5.0",
|
|
280
|
-
"yauzl": "^3.
|
|
281
|
+
"yauzl": "^3.2.1",
|
|
281
282
|
"yn": "^4.0.0",
|
|
282
|
-
"zod": "^3.25.76",
|
|
283
|
+
"zod": "^3.25.76 || ^4.0.0",
|
|
283
284
|
"zod-to-json-schema": "^3.25.1"
|
|
284
285
|
},
|
|
285
286
|
"devDependencies": {
|
|
286
287
|
"@aws-sdk/util-stream-node": "^3.350.0",
|
|
287
|
-
"@backstage/backend-plugin-api": "1.8.0
|
|
288
|
-
"@backstage/backend-test-utils": "1.11.1
|
|
289
|
-
"@backstage/cli": "0.36.0
|
|
288
|
+
"@backstage/backend-plugin-api": "^1.8.0",
|
|
289
|
+
"@backstage/backend-test-utils": "^1.11.1",
|
|
290
|
+
"@backstage/cli": "^0.36.0",
|
|
290
291
|
"@google-cloud/cloud-sql-connector": "^1.4.0",
|
|
291
292
|
"@types/archiver": "^7.0.0",
|
|
292
293
|
"@types/base64-stream": "^1.0.2",
|