@backstage/plugin-scaffolder-react 1.14.5 → 1.14.6-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,32 @@
1
1
  # @backstage/plugin-scaffolder-react
2
2
 
3
+ ## 1.14.6-next.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 4d26652: Fix field extension validation not working when field is in dependencies in an array field
8
+ - Updated dependencies
9
+ - @backstage/core-components@0.16.5-next.0
10
+ - @backstage/plugin-scaffolder-common@1.5.10-next.0
11
+ - @backstage/plugin-catalog-react@1.16.0-next.1
12
+ - @backstage/catalog-client@1.9.1
13
+ - @backstage/catalog-model@1.7.3
14
+ - @backstage/core-plugin-api@1.10.4
15
+ - @backstage/frontend-plugin-api@0.9.6-next.1
16
+ - @backstage/theme@0.6.4
17
+ - @backstage/types@1.2.1
18
+ - @backstage/version-bridge@1.0.11
19
+ - @backstage/plugin-permission-react@0.4.31
20
+
21
+ ## 1.14.6-next.0
22
+
23
+ ### Patch Changes
24
+
25
+ - b3b7c9c: Deprecated the alpha `ScaffolderFormFieldsApi` and `formFieldsApiRef` as these are being replaced with a different solution.
26
+ - Updated dependencies
27
+ - @backstage/plugin-catalog-react@1.16.0-next.0
28
+ - @backstage/frontend-plugin-api@0.9.6-next.0
29
+
3
30
  ## 1.14.5
4
31
 
5
32
  ### Patch Changes
package/dist/alpha.d.ts CHANGED
@@ -144,12 +144,18 @@ declare const FormFieldBlueprint: _backstage_frontend_plugin_api.ExtensionBluepr
144
144
  */
145
145
  declare function createFormField<TReturnValue extends z.ZodType, TUiOptions extends z.ZodType>(opts: FormFieldExtensionData<TReturnValue, TUiOptions>): FormField;
146
146
 
147
- /** @alpha */
147
+ /**
148
+ * @alpha
149
+ * @deprecated This API is no longer necessary and will be removed
150
+ */
148
151
  interface ScaffolderFormFieldsApi {
149
152
  getFormFields(): Promise<FormFieldExtensionData[]>;
150
153
  }
151
154
 
152
- /** @alpha */
155
+ /**
156
+ * @alpha
157
+ * @deprecated This API is no longer necessary and will be removed
158
+ */
153
159
  declare const formFieldsApiRef: _backstage_frontend_plugin_api.ApiRef<ScaffolderFormFieldsApi>;
154
160
 
155
161
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"ref.esm.js","sources":["../../../src/next/api/ref.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { createApiRef } from '@backstage/frontend-plugin-api';\nimport { ScaffolderFormFieldsApi } from './types';\n\n/** @alpha */\nexport const formFieldsApiRef = createApiRef<ScaffolderFormFieldsApi>({\n id: 'plugin.scaffolder.form-fields',\n});\n"],"names":[],"mappings":";;AAoBO,MAAM,mBAAmB,YAAsC,CAAA;AAAA,EACpE,EAAI,EAAA;AACN,CAAC;;;;"}
1
+ {"version":3,"file":"ref.esm.js","sources":["../../../src/next/api/ref.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { createApiRef } from '@backstage/frontend-plugin-api';\nimport { ScaffolderFormFieldsApi } from './types';\n\n/**\n * @alpha\n * @deprecated This API is no longer necessary and will be removed\n */\nexport const formFieldsApiRef = createApiRef<ScaffolderFormFieldsApi>({\n id: 'plugin.scaffolder.form-fields',\n});\n"],"names":[],"mappings":";;AAuBO,MAAM,mBAAmB,YAAsC,CAAA;AAAA,EACpE,EAAI,EAAA;AACN,CAAC;;;;"}
@@ -7,7 +7,10 @@ const formFieldExtensionDataRef = createExtensionDataRef().with({
7
7
  });
8
8
  const FormFieldBlueprint = createExtensionBlueprint({
9
9
  kind: "scaffolder-form-field",
10
- attachTo: { id: "api:scaffolder/form-fields", input: "formFields" },
10
+ attachTo: [
11
+ { id: "page:scaffolder", input: "formFields" },
12
+ { id: "api:scaffolder/form-fields", input: "formFields" }
13
+ ],
11
14
  dataRefs: {
12
15
  formFieldLoader: formFieldExtensionDataRef
13
16
  },
@@ -1 +1 @@
1
- {"version":3,"file":"FormFieldBlueprint.esm.js","sources":["../../../src/next/blueprints/FormFieldBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 */\nimport {\n createExtensionBlueprint,\n createExtensionDataRef,\n} from '@backstage/frontend-plugin-api';\nimport { z } from 'zod';\n\nimport { OpaqueFormField, FormField } from '@internal/scaffolder';\nimport { FormFieldExtensionData } from './types';\n\nconst formFieldExtensionDataRef = createExtensionDataRef<\n () => Promise<FormField>\n>().with({\n id: 'scaffolder.form-field-loader',\n});\n\n/**\n * @alpha\n * Creates extensions that are Field Extensions for the Scaffolder\n * */\nexport const FormFieldBlueprint = createExtensionBlueprint({\n kind: 'scaffolder-form-field',\n attachTo: { id: 'api:scaffolder/form-fields', input: 'formFields' },\n dataRefs: {\n formFieldLoader: formFieldExtensionDataRef,\n },\n output: [formFieldExtensionDataRef],\n *factory(params: { field: () => Promise<FormField> }) {\n yield formFieldExtensionDataRef(params.field);\n },\n});\n\n/**\n * @alpha\n * Used to create a form field binding with typechecking for compliance\n */\nexport function createFormField<\n TReturnValue extends z.ZodType,\n TUiOptions extends z.ZodType,\n>(opts: FormFieldExtensionData<TReturnValue, TUiOptions>): FormField {\n return OpaqueFormField.createInstance('v1', opts);\n}\n"],"names":[],"mappings":";;;;AAwBA,MAAM,yBAAA,GAA4B,sBAEhC,EAAA,CAAE,IAAK,CAAA;AAAA,EACP,EAAI,EAAA;AACN,CAAC,CAAA;AAMM,MAAM,qBAAqB,wBAAyB,CAAA;AAAA,EACzD,IAAM,EAAA,uBAAA;AAAA,EACN,QAAU,EAAA,EAAE,EAAI,EAAA,4BAAA,EAA8B,OAAO,YAAa,EAAA;AAAA,EAClE,QAAU,EAAA;AAAA,IACR,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,MAAA,EAAQ,CAAC,yBAAyB,CAAA;AAAA,EAClC,CAAC,QAAQ,MAA6C,EAAA;AACpD,IAAM,MAAA,yBAAA,CAA0B,OAAO,KAAK,CAAA;AAAA;AAEhD,CAAC;AAMM,SAAS,gBAGd,IAAmE,EAAA;AACnE,EAAO,OAAA,eAAA,CAAgB,cAAe,CAAA,IAAA,EAAM,IAAI,CAAA;AAClD;;;;"}
1
+ {"version":3,"file":"FormFieldBlueprint.esm.js","sources":["../../../src/next/blueprints/FormFieldBlueprint.tsx"],"sourcesContent":["/*\n * Copyright 2024 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 */\nimport {\n createExtensionBlueprint,\n createExtensionDataRef,\n} from '@backstage/frontend-plugin-api';\nimport { z } from 'zod';\n\nimport { OpaqueFormField, FormField } from '@internal/scaffolder';\nimport { FormFieldExtensionData } from './types';\n\nconst formFieldExtensionDataRef = createExtensionDataRef<\n () => Promise<FormField>\n>().with({\n id: 'scaffolder.form-field-loader',\n});\n\n/**\n * @alpha\n * Creates extensions that are Field Extensions for the Scaffolder\n * */\nexport const FormFieldBlueprint = createExtensionBlueprint({\n kind: 'scaffolder-form-field',\n attachTo: [\n { id: 'page:scaffolder', input: 'formFields' },\n { id: 'api:scaffolder/form-fields', input: 'formFields' },\n ],\n dataRefs: {\n formFieldLoader: formFieldExtensionDataRef,\n },\n output: [formFieldExtensionDataRef],\n *factory(params: { field: () => Promise<FormField> }) {\n yield formFieldExtensionDataRef(params.field);\n },\n});\n\n/**\n * @alpha\n * Used to create a form field binding with typechecking for compliance\n */\nexport function createFormField<\n TReturnValue extends z.ZodType,\n TUiOptions extends z.ZodType,\n>(opts: FormFieldExtensionData<TReturnValue, TUiOptions>): FormField {\n return OpaqueFormField.createInstance('v1', opts);\n}\n"],"names":[],"mappings":";;;;AAwBA,MAAM,yBAAA,GAA4B,sBAEhC,EAAA,CAAE,IAAK,CAAA;AAAA,EACP,EAAI,EAAA;AACN,CAAC,CAAA;AAMM,MAAM,qBAAqB,wBAAyB,CAAA;AAAA,EACzD,IAAM,EAAA,uBAAA;AAAA,EACN,QAAU,EAAA;AAAA,IACR,EAAE,EAAA,EAAI,iBAAmB,EAAA,KAAA,EAAO,YAAa,EAAA;AAAA,IAC7C,EAAE,EAAA,EAAI,4BAA8B,EAAA,KAAA,EAAO,YAAa;AAAA,GAC1D;AAAA,EACA,QAAU,EAAA;AAAA,IACR,eAAiB,EAAA;AAAA,GACnB;AAAA,EACA,MAAA,EAAQ,CAAC,yBAAyB,CAAA;AAAA,EAClC,CAAC,QAAQ,MAA6C,EAAA;AACpD,IAAM,MAAA,yBAAA,CAA0B,OAAO,KAAK,CAAA;AAAA;AAEhD,CAAC;AAMM,SAAS,gBAGd,IAAmE,EAAA;AACnE,EAAO,OAAA,eAAA,CAAgB,cAAe,CAAA,IAAA,EAAM,IAAI,CAAA;AAClD;;;;"}
@@ -55,6 +55,27 @@ const createAsyncValidators = (rootSchema, validators, context) => {
55
55
  await doValidateItem(propValue, itemsSchema, itemsUiSchema);
56
56
  }
57
57
  };
58
+ const doValidateDependency = async (propValue) => {
59
+ const { schema: itemsSchema, uiSchema: itemsUiSchema } = extractSchemaFromStep(propValue);
60
+ await doValidateItem(propValue, itemsSchema, itemsUiSchema);
61
+ const iterable = Array.isArray(value) ? value : [value];
62
+ for (const item of iterable) {
63
+ if (item && isObject(item)) {
64
+ const keys = Object.keys(item);
65
+ for (const k of keys) {
66
+ if (itemsUiSchema[k] && "ui:field" in itemsUiSchema[k]) {
67
+ await validateForm(
68
+ itemsUiSchema[k]["ui:field"],
69
+ k,
70
+ item[k],
71
+ itemsSchema,
72
+ itemsUiSchema
73
+ );
74
+ }
75
+ }
76
+ }
77
+ }
78
+ };
58
79
  if ("ui:field" in definitionInSchema) {
59
80
  await doValidateItem(definitionInSchema, schema, uiSchema);
60
81
  } else if (hasItems && "ui:field" in definitionInSchema.items) {
@@ -64,6 +85,10 @@ const createAsyncValidators = (rootSchema, validators, context) => {
64
85
  for (const [, propValue] of Object.entries(properties)) {
65
86
  await doValidate(propValue);
66
87
  }
88
+ const dependencies = definitionInSchema.items?.dependencies ?? [];
89
+ for (const [, propValue] of Object.entries(dependencies)) {
90
+ await doValidateDependency(propValue);
91
+ }
67
92
  } else if (isObject(value)) {
68
93
  formValidation[key] = await validate(formData, pointer, value);
69
94
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createAsyncValidators.esm.js","sources":["../../../../src/next/components/Stepper/createAsyncValidators.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { FieldValidation } from '@rjsf/utils';\nimport type { JsonObject, JsonValue } from '@backstage/types';\nimport { ApiHolder } from '@backstage/core-plugin-api';\nimport {\n Draft07 as JSONSchema,\n JsonError,\n JsonSchema,\n} from 'json-schema-library';\nimport { createFieldValidation, extractSchemaFromStep } from '../../lib';\nimport {\n CustomFieldValidator,\n FieldExtensionUiSchema,\n} from '@backstage/plugin-scaffolder-react';\nimport { isObject } from './utils';\n\n/** @alpha */\nexport type FormValidation = {\n [name: string]: FieldValidation | FormValidation;\n};\n\nconst isJsonError = (\n value: JsonError | JsonSchema,\n): value is { type: 'error'; message: string } =>\n 'type' in value && value.type === 'error';\n\n/** @alpha */\nexport const createAsyncValidators = (\n rootSchema: JsonObject,\n validators: Record<\n string,\n undefined | CustomFieldValidator<unknown, unknown>\n >,\n context: {\n apiHolder: ApiHolder;\n },\n) => {\n async function validate(\n formData: JsonObject,\n pathPrefix: string = '#',\n current: JsonObject = formData,\n ): Promise<FormValidation> {\n const parsedSchema = new JSONSchema(rootSchema);\n const formValidation: FormValidation = {};\n\n const validateForm = async (\n validatorName: string,\n key: string,\n value: JsonValue | undefined,\n schema: JsonObject,\n uiSchema: FieldExtensionUiSchema<unknown, unknown>,\n ) => {\n const validator = validators[validatorName];\n if (validator) {\n const fieldValidation = createFieldValidation();\n try {\n await validator(value, fieldValidation, {\n ...context,\n formData,\n schema,\n uiSchema,\n });\n } catch (ex) {\n fieldValidation.addError(ex.message);\n }\n formValidation[key] = fieldValidation;\n }\n };\n\n for (const [key, value] of Object.entries(current)) {\n const pointer = `${pathPrefix}/${key}`;\n const definitionInSchema = parsedSchema.getSchema({\n pointer,\n data: formData,\n });\n\n if (!definitionInSchema) {\n continue;\n }\n\n if (isJsonError(definitionInSchema)) {\n throw new Error(definitionInSchema.message);\n }\n\n const { schema, uiSchema } = extractSchemaFromStep(\n definitionInSchema as JsonObject,\n );\n\n const hasItems = definitionInSchema && definitionInSchema.items;\n\n const doValidateItem = async (\n propValue: JsonObject,\n itemSchema: JsonObject,\n itemUiSchema: FieldExtensionUiSchema<unknown, unknown>,\n ) => {\n await validateForm(\n propValue['ui:field'] as string,\n key,\n value,\n itemSchema,\n itemUiSchema,\n );\n };\n\n const doValidate = async (propValue: JsonObject) => {\n if ('ui:field' in propValue) {\n const { schema: itemsSchema, uiSchema: itemsUiSchema } =\n extractSchemaFromStep(definitionInSchema.items);\n await doValidateItem(propValue, itemsSchema, itemsUiSchema);\n }\n };\n\n if ('ui:field' in definitionInSchema) {\n await doValidateItem(definitionInSchema, schema, uiSchema);\n } else if (hasItems && 'ui:field' in definitionInSchema.items) {\n await doValidate(definitionInSchema.items);\n } else if (hasItems && definitionInSchema.items.type === 'object') {\n const properties = (definitionInSchema.items?.properties ??\n []) as JsonObject[];\n for (const [, propValue] of Object.entries(properties)) {\n await doValidate(propValue);\n }\n } else if (isObject(value)) {\n formValidation[key] = await validate(formData, pointer, value);\n }\n }\n\n return formValidation;\n }\n\n return async (formData: JsonObject) => {\n return await validate(formData);\n };\n};\n"],"names":["JSONSchema"],"mappings":"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"}
1
+ {"version":3,"file":"createAsyncValidators.esm.js","sources":["../../../../src/next/components/Stepper/createAsyncValidators.ts"],"sourcesContent":["/*\n * Copyright 2022 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 { FieldValidation } from '@rjsf/utils';\nimport type { JsonObject, JsonValue } from '@backstage/types';\nimport { ApiHolder } from '@backstage/core-plugin-api';\nimport {\n Draft07 as JSONSchema,\n JsonError,\n JsonSchema,\n} from 'json-schema-library';\nimport { createFieldValidation, extractSchemaFromStep } from '../../lib';\nimport {\n CustomFieldValidator,\n FieldExtensionUiSchema,\n} from '@backstage/plugin-scaffolder-react';\nimport { isObject } from './utils';\n\n/** @alpha */\nexport type FormValidation = {\n [name: string]: FieldValidation | FormValidation;\n};\n\nconst isJsonError = (\n value: JsonError | JsonSchema,\n): value is { type: 'error'; message: string } =>\n 'type' in value && value.type === 'error';\n\n/** @alpha */\nexport const createAsyncValidators = (\n rootSchema: JsonObject,\n validators: Record<\n string,\n undefined | CustomFieldValidator<unknown, unknown>\n >,\n context: {\n apiHolder: ApiHolder;\n },\n) => {\n async function validate(\n formData: JsonObject,\n pathPrefix: string = '#',\n current: JsonObject = formData,\n ): Promise<FormValidation> {\n const parsedSchema = new JSONSchema(rootSchema);\n const formValidation: FormValidation = {};\n\n const validateForm = async (\n validatorName: string,\n key: string,\n value: JsonValue | undefined,\n schema: JsonObject,\n uiSchema: FieldExtensionUiSchema<unknown, unknown>,\n ) => {\n const validator = validators[validatorName];\n if (validator) {\n const fieldValidation = createFieldValidation();\n try {\n await validator(value, fieldValidation, {\n ...context,\n formData,\n schema,\n uiSchema,\n });\n } catch (ex) {\n fieldValidation.addError(ex.message);\n }\n formValidation[key] = fieldValidation;\n }\n };\n\n for (const [key, value] of Object.entries(current)) {\n const pointer = `${pathPrefix}/${key}`;\n const definitionInSchema = parsedSchema.getSchema({\n pointer,\n data: formData,\n });\n\n if (!definitionInSchema) {\n continue;\n }\n\n if (isJsonError(definitionInSchema)) {\n throw new Error(definitionInSchema.message);\n }\n\n const { schema, uiSchema } = extractSchemaFromStep(\n definitionInSchema as JsonObject,\n );\n\n const hasItems = definitionInSchema && definitionInSchema.items;\n\n const doValidateItem = async (\n propValue: JsonObject,\n itemSchema: JsonObject,\n itemUiSchema: FieldExtensionUiSchema<unknown, unknown>,\n ) => {\n await validateForm(\n propValue['ui:field'] as string,\n key,\n value,\n itemSchema,\n itemUiSchema,\n );\n };\n\n const doValidate = async (propValue: JsonObject) => {\n if ('ui:field' in propValue) {\n const { schema: itemsSchema, uiSchema: itemsUiSchema } =\n extractSchemaFromStep(definitionInSchema.items);\n await doValidateItem(propValue, itemsSchema, itemsUiSchema);\n }\n };\n\n const doValidateDependency = async (propValue: JsonObject) => {\n const { schema: itemsSchema, uiSchema: itemsUiSchema } =\n extractSchemaFromStep(propValue);\n await doValidateItem(propValue, itemsSchema, itemsUiSchema);\n\n const iterable = Array.isArray(value) ? value : [value];\n for (const item of iterable) {\n if (item && isObject(item)) {\n const keys = Object.keys(item);\n for (const k of keys) {\n if (itemsUiSchema[k] && 'ui:field' in itemsUiSchema[k]) {\n await validateForm(\n itemsUiSchema[k]['ui:field'],\n k,\n item[k],\n itemsSchema,\n itemsUiSchema,\n );\n }\n }\n }\n }\n };\n\n if ('ui:field' in definitionInSchema) {\n await doValidateItem(definitionInSchema, schema, uiSchema);\n } else if (hasItems && 'ui:field' in definitionInSchema.items) {\n await doValidate(definitionInSchema.items);\n } else if (hasItems && definitionInSchema.items.type === 'object') {\n const properties = (definitionInSchema.items?.properties ??\n []) as JsonObject[];\n for (const [, propValue] of Object.entries(properties)) {\n await doValidate(propValue);\n }\n\n const dependencies = (definitionInSchema.items?.dependencies ??\n []) as JsonObject[];\n for (const [, propValue] of Object.entries(dependencies)) {\n await doValidateDependency(propValue);\n }\n } else if (isObject(value)) {\n formValidation[key] = await validate(formData, pointer, value);\n }\n }\n\n return formValidation;\n }\n\n return async (formData: JsonObject) => {\n return await validate(formData);\n };\n};\n"],"names":["JSONSchema"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-scaffolder-react",
3
- "version": "1.14.5",
3
+ "version": "1.14.6-next.1",
4
4
  "description": "A frontend library that helps other Backstage plugins interact with the Scaffolder",
5
5
  "backstage": {
6
6
  "role": "web-library",
@@ -66,17 +66,17 @@
66
66
  "test": "backstage-cli package test"
67
67
  },
68
68
  "dependencies": {
69
- "@backstage/catalog-client": "^1.9.1",
70
- "@backstage/catalog-model": "^1.7.3",
71
- "@backstage/core-components": "^0.16.4",
72
- "@backstage/core-plugin-api": "^1.10.4",
73
- "@backstage/frontend-plugin-api": "^0.9.5",
74
- "@backstage/plugin-catalog-react": "^1.15.2",
75
- "@backstage/plugin-permission-react": "^0.4.31",
76
- "@backstage/plugin-scaffolder-common": "^1.5.9",
77
- "@backstage/theme": "^0.6.4",
78
- "@backstage/types": "^1.2.1",
79
- "@backstage/version-bridge": "^1.0.11",
69
+ "@backstage/catalog-client": "1.9.1",
70
+ "@backstage/catalog-model": "1.7.3",
71
+ "@backstage/core-components": "0.16.5-next.0",
72
+ "@backstage/core-plugin-api": "1.10.4",
73
+ "@backstage/frontend-plugin-api": "0.9.6-next.1",
74
+ "@backstage/plugin-catalog-react": "1.16.0-next.1",
75
+ "@backstage/plugin-permission-react": "0.4.31",
76
+ "@backstage/plugin-scaffolder-common": "1.5.10-next.0",
77
+ "@backstage/theme": "0.6.4",
78
+ "@backstage/types": "1.2.1",
79
+ "@backstage/version-bridge": "1.0.11",
80
80
  "@material-ui/core": "^4.12.2",
81
81
  "@material-ui/icons": "^4.9.1",
82
82
  "@material-ui/lab": "4.0.0-alpha.61",
@@ -104,12 +104,12 @@
104
104
  "zod-to-json-schema": "^3.20.4"
105
105
  },
106
106
  "devDependencies": {
107
- "@backstage/cli": "^0.30.0",
108
- "@backstage/core-app-api": "^1.15.5",
109
- "@backstage/plugin-catalog": "^1.27.0",
110
- "@backstage/plugin-catalog-common": "^1.1.3",
111
- "@backstage/plugin-permission-common": "^0.8.4",
112
- "@backstage/test-utils": "^1.7.5",
107
+ "@backstage/cli": "0.30.1-next.0",
108
+ "@backstage/core-app-api": "1.15.5",
109
+ "@backstage/plugin-catalog": "1.28.0-next.1",
110
+ "@backstage/plugin-catalog-common": "1.1.3",
111
+ "@backstage/plugin-permission-common": "0.8.4",
112
+ "@backstage/test-utils": "1.7.5",
113
113
  "@testing-library/dom": "^10.0.0",
114
114
  "@testing-library/jest-dom": "^6.0.0",
115
115
  "@testing-library/react": "^16.0.0",