wip: start to implement the hooks

Signed-off-by: blam <ben@blam.sh>
This commit is contained in:
blam
2024-10-11 10:42:06 +02:00
parent 56eff0b621
commit 189201ef4b
15 changed files with 358 additions and 5 deletions
@@ -0,0 +1,16 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './createScaffolderFieldExtension';
@@ -31,6 +31,7 @@ import { useFilteredSchemaProperties } from '../../hooks/useFilteredSchemaProper
import { ReviewStepProps } from '@backstage/plugin-scaffolder-react';
import { useTemplateTimeSavedMinutes } from '../../hooks/useTemplateTimeSaved';
import { JsonValue } from '@backstage/types';
import { ScaffolderFormHook } from '../../extensions';
const useStyles = makeStyles({
markdown: {
@@ -52,6 +53,7 @@ export type WorkflowProps = {
description?: string;
namespace: string;
templateName: string;
formHooks?: ScaffolderFormHook[];
components?: {
ReviewStepComponent?: React.ComponentType<ReviewStepProps>;
};
@@ -0,0 +1,51 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { createScaffolderFormHook } from './createScaffolderFormHook';
describe('createScaffolderFormHook', () => {
it('should return a hook', () => {
const hook = createScaffolderFormHook({
id: 'test',
deps: {},
fn: async () => {},
});
expect(hook).toMatchInlineSnapshot();
});
it('should allow passing schema and be typesafe', () => {
const hook = createScaffolderFormHook({
id: 'test',
deps: {},
schema: {
input: {
name: z => z.string(),
age: z => z.number(),
},
},
fn: async ctx => {
const name: string = ctx.input.name;
// @ts-expect-error
const number: string = ctx.input.age;
expect([name, number]).toBeDefined();
},
});
expect(hook).toMatchInlineSnapshot();
});
});
@@ -0,0 +1,79 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { AnyApiRef } from '@backstage/core-plugin-api';
import { JsonValue } from '@backstage/types';
import { z } from 'zod';
export type ScaffolderFormHookContext<TInput> = {
input: TInput;
setSecret: (key: string, value: JsonValue) => void;
};
export type ScaffolderInitialFormHook<
TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType } = {},
TDeps extends { [key in string]: AnyApiRef } = { [key in string]: AnyApiRef },
TInput = {
[key in keyof TInputSchema]: z.infer<ReturnType<TInputSchema[key]>>;
},
> = {
version: 'v1';
id: string;
schema?: {
input?: TInputSchema;
};
deps?: TDeps;
fn: (
ctx: ScaffolderFormHookContext<TInput>,
deps: TDeps extends { [key in string]: AnyApiRef }
? { [key in keyof TDeps]: TDeps[key]['T'] }
: never,
) => Promise<void>;
};
export type ScaffolderFormHook<TInput = any> = {
id: string;
fn: (ctx: ScaffolderFormHookContext<TInput>) => Promise<void>;
};
/**
* Method for creating hooks which can be used to collect
* secrets from the user before submitting to the backend.
* @public
*/
export function createScaffolderFormHook<
TDeps extends { [key in string]: AnyApiRef },
TInputSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType },
TInput = {
[key in keyof TInputSchema]: z.infer<ReturnType<TInputSchema[key]>>;
},
>(options: {
id: string;
schema?: {
input?: TInputSchema;
};
deps?: TDeps;
fn: (
ctx: ScaffolderFormHookContext<TInput>,
deps: TDeps extends { [key in string]: AnyApiRef }
? { [key in keyof TDeps]: TDeps[key]['T'] }
: never,
) => Promise<void>;
}): ScaffolderInitialFormHook<TInputSchema, TDeps, TInput> {
return {
...options,
version: 'v1',
};
}
@@ -0,0 +1,16 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
export * from './createScaffolderFormHook';
@@ -18,3 +18,4 @@ export * from './lib';
export * from './hooks';
export * from './overridableComponents';
export * from './blueprints';
export * from './extensions';