@opensumi/ide-debug 2.24.6-rc-1685671765.0 → 2.25.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.
Files changed (174) hide show
  1. package/lib/browser/components/floating-click-widget/index.d.ts.map +1 -1
  2. package/lib/browser/components/floating-click-widget/index.js +3 -2
  3. package/lib/browser/components/floating-click-widget/index.js.map +1 -1
  4. package/lib/browser/components/floating-click-widget/index.module.less +4 -0
  5. package/lib/browser/debug-configuration-manager.d.ts +6 -0
  6. package/lib/browser/debug-configuration-manager.d.ts.map +1 -1
  7. package/lib/browser/debug-configuration-manager.js +64 -17
  8. package/lib/browser/debug-configuration-manager.js.map +1 -1
  9. package/lib/browser/debug-contribution.d.ts.map +1 -1
  10. package/lib/browser/debug-contribution.js +11 -3
  11. package/lib/browser/debug-contribution.js.map +1 -1
  12. package/lib/browser/{debug-schema-updater.d.ts → debug-schema-manager.d.ts} +2 -2
  13. package/lib/browser/debug-schema-manager.d.ts.map +1 -0
  14. package/lib/browser/{debug-schema-updater.js → debug-schema-manager.js} +10 -10
  15. package/lib/browser/debug-schema-manager.js.map +1 -0
  16. package/lib/browser/debugUtils.d.ts +1 -0
  17. package/lib/browser/debugUtils.d.ts.map +1 -1
  18. package/lib/browser/debugUtils.js +22 -1
  19. package/lib/browser/debugUtils.js.map +1 -1
  20. package/lib/browser/editor/debug-breakpoint-zone-widget.d.ts +2 -0
  21. package/lib/browser/editor/debug-breakpoint-zone-widget.d.ts.map +1 -1
  22. package/lib/browser/editor/debug-breakpoint-zone-widget.js +14 -0
  23. package/lib/browser/editor/debug-breakpoint-zone-widget.js.map +1 -1
  24. package/lib/browser/index.d.ts.map +1 -1
  25. package/lib/browser/index.js +5 -0
  26. package/lib/browser/index.js.map +1 -1
  27. package/lib/browser/preferences/components/checkbox-widget.d.ts +4 -0
  28. package/lib/browser/preferences/components/checkbox-widget.d.ts.map +1 -0
  29. package/lib/browser/preferences/components/checkbox-widget.js +27 -0
  30. package/lib/browser/preferences/components/checkbox-widget.js.map +1 -0
  31. package/lib/browser/preferences/components/fields/any-of-field.d.ts +4 -0
  32. package/lib/browser/preferences/components/fields/any-of-field.d.ts.map +1 -0
  33. package/lib/browser/preferences/components/fields/any-of-field.js +28 -0
  34. package/lib/browser/preferences/components/fields/any-of-field.js.map +1 -0
  35. package/lib/browser/preferences/components/fields/array-field.d.ts +5 -0
  36. package/lib/browser/preferences/components/fields/array-field.d.ts.map +1 -0
  37. package/lib/browser/preferences/components/fields/array-field.js +19 -0
  38. package/lib/browser/preferences/components/fields/array-field.js.map +1 -0
  39. package/lib/browser/preferences/components/fields/object-filed.d.ts +5 -0
  40. package/lib/browser/preferences/components/fields/object-filed.d.ts.map +1 -0
  41. package/lib/browser/preferences/components/fields/object-filed.js +26 -0
  42. package/lib/browser/preferences/components/fields/object-filed.js.map +1 -0
  43. package/lib/browser/preferences/components/fields/title-field.d.ts +4 -0
  44. package/lib/browser/preferences/components/fields/title-field.d.ts.map +1 -0
  45. package/lib/browser/preferences/components/fields/title-field.js +12 -0
  46. package/lib/browser/preferences/components/fields/title-field.js.map +1 -0
  47. package/lib/browser/preferences/components/json-widget.module.less +36 -0
  48. package/lib/browser/preferences/components/select-widget.d.ts +4 -0
  49. package/lib/browser/preferences/components/select-widget.d.ts.map +1 -0
  50. package/lib/browser/preferences/components/select-widget.js +28 -0
  51. package/lib/browser/preferences/components/select-widget.js.map +1 -0
  52. package/lib/browser/preferences/components/text-widget.d.ts +4 -0
  53. package/lib/browser/preferences/components/text-widget.d.ts.map +1 -0
  54. package/lib/browser/preferences/components/text-widget.js +41 -0
  55. package/lib/browser/preferences/components/text-widget.js.map +1 -0
  56. package/lib/browser/preferences/launch-preferences-contribution.d.ts +14 -2
  57. package/lib/browser/preferences/launch-preferences-contribution.d.ts.map +1 -1
  58. package/lib/browser/preferences/launch-preferences-contribution.js +61 -2
  59. package/lib/browser/preferences/launch-preferences-contribution.js.map +1 -1
  60. package/lib/browser/preferences/launch.module.less +102 -0
  61. package/lib/browser/preferences/launch.service.d.ts +31 -0
  62. package/lib/browser/preferences/launch.service.d.ts.map +1 -0
  63. package/lib/browser/preferences/launch.service.js +109 -0
  64. package/lib/browser/preferences/launch.service.js.map +1 -0
  65. package/lib/browser/preferences/launch.view.d.ts +3 -0
  66. package/lib/browser/preferences/launch.view.d.ts.map +1 -0
  67. package/lib/browser/preferences/launch.view.js +287 -0
  68. package/lib/browser/preferences/launch.view.js.map +1 -0
  69. package/lib/browser/preferences/model/configuration-items.d.ts +12 -0
  70. package/lib/browser/preferences/model/configuration-items.d.ts.map +1 -0
  71. package/lib/browser/preferences/model/configuration-items.js +22 -0
  72. package/lib/browser/preferences/model/configuration-items.js.map +1 -0
  73. package/lib/browser/preferences/templates/additional-template.d.ts +4 -0
  74. package/lib/browser/preferences/templates/additional-template.d.ts.map +1 -0
  75. package/lib/browser/preferences/templates/additional-template.js +30 -0
  76. package/lib/browser/preferences/templates/additional-template.js.map +1 -0
  77. package/lib/browser/preferences/templates/array-field-item-template.d.ts +4 -0
  78. package/lib/browser/preferences/templates/array-field-item-template.d.ts.map +1 -0
  79. package/lib/browser/preferences/templates/array-field-item-template.js +31 -0
  80. package/lib/browser/preferences/templates/array-field-item-template.js.map +1 -0
  81. package/lib/browser/preferences/templates/array-field-template.d.ts +4 -0
  82. package/lib/browser/preferences/templates/array-field-template.d.ts.map +1 -0
  83. package/lib/browser/preferences/templates/array-field-template.js +31 -0
  84. package/lib/browser/preferences/templates/array-field-template.js.map +1 -0
  85. package/lib/browser/preferences/templates/base-input-template.d.ts +4 -0
  86. package/lib/browser/preferences/templates/base-input-template.d.ts.map +1 -0
  87. package/lib/browser/preferences/templates/base-input-template.js +29 -0
  88. package/lib/browser/preferences/templates/base-input-template.js.map +1 -0
  89. package/lib/browser/preferences/templates/button-template.d.ts +12 -0
  90. package/lib/browser/preferences/templates/button-template.d.ts.map +1 -0
  91. package/lib/browser/preferences/templates/button-template.js +71 -0
  92. package/lib/browser/preferences/templates/button-template.js.map +1 -0
  93. package/lib/browser/preferences/templates/description-field-template.d.ts +4 -0
  94. package/lib/browser/preferences/templates/description-field-template.d.ts.map +1 -0
  95. package/lib/browser/preferences/templates/description-field-template.js +16 -0
  96. package/lib/browser/preferences/templates/description-field-template.js.map +1 -0
  97. package/lib/browser/preferences/templates/field-template.d.ts +4 -0
  98. package/lib/browser/preferences/templates/field-template.d.ts.map +1 -0
  99. package/lib/browser/preferences/templates/field-template.js +19 -0
  100. package/lib/browser/preferences/templates/field-template.js.map +1 -0
  101. package/lib/browser/preferences/templates/json-templates.module.less +133 -0
  102. package/lib/browser/preferences/templates/object-field-template.d.ts +4 -0
  103. package/lib/browser/preferences/templates/object-field-template.d.ts.map +1 -0
  104. package/lib/browser/preferences/templates/object-field-template.js +74 -0
  105. package/lib/browser/preferences/templates/object-field-template.js.map +1 -0
  106. package/lib/browser/view/breakpoints/debug-breakpoints.module.less +19 -17
  107. package/lib/browser/view/breakpoints/debug-breakpoints.view.d.ts.map +1 -1
  108. package/lib/browser/view/breakpoints/debug-breakpoints.view.js +15 -7
  109. package/lib/browser/view/breakpoints/debug-breakpoints.view.js.map +1 -1
  110. package/lib/browser/view/configuration/debug-configuration.service.d.ts +1 -0
  111. package/lib/browser/view/configuration/debug-configuration.service.d.ts.map +1 -1
  112. package/lib/browser/view/configuration/debug-configuration.service.js +3 -0
  113. package/lib/browser/view/configuration/debug-configuration.service.js.map +1 -1
  114. package/lib/common/constants.d.ts +2 -0
  115. package/lib/common/constants.d.ts.map +1 -1
  116. package/lib/common/constants.js +4 -2
  117. package/lib/common/constants.js.map +1 -1
  118. package/lib/common/debug-schema.d.ts +5 -0
  119. package/lib/common/debug-schema.d.ts.map +1 -0
  120. package/lib/common/debug-schema.js +7 -0
  121. package/lib/common/debug-schema.js.map +1 -0
  122. package/lib/common/debug-service.d.ts +10 -0
  123. package/lib/common/debug-service.d.ts.map +1 -1
  124. package/lib/common/debug-service.js +8 -1
  125. package/lib/common/debug-service.js.map +1 -1
  126. package/lib/common/index.d.ts +1 -1
  127. package/lib/common/index.d.ts.map +1 -1
  128. package/lib/common/index.js +1 -1
  129. package/lib/common/index.js.map +1 -1
  130. package/package.json +26 -23
  131. package/src/browser/components/floating-click-widget/index.module.less +4 -0
  132. package/src/browser/components/floating-click-widget/index.tsx +4 -1
  133. package/src/browser/debug-configuration-manager.ts +82 -18
  134. package/src/browser/debug-contribution.ts +12 -4
  135. package/src/browser/{debug-schema-updater.ts → debug-schema-manager.ts} +5 -4
  136. package/src/browser/debugUtils.ts +23 -0
  137. package/src/browser/editor/debug-breakpoint-zone-widget.tsx +16 -1
  138. package/src/browser/index.ts +6 -0
  139. package/src/browser/preferences/components/checkbox-widget.tsx +78 -0
  140. package/src/browser/preferences/components/fields/any-of-field.tsx +90 -0
  141. package/src/browser/preferences/components/fields/array-field.tsx +25 -0
  142. package/src/browser/preferences/components/fields/object-filed.tsx +33 -0
  143. package/src/browser/preferences/components/fields/title-field.tsx +16 -0
  144. package/src/browser/preferences/components/json-widget.module.less +36 -0
  145. package/src/browser/preferences/components/select-widget.tsx +68 -0
  146. package/src/browser/preferences/components/text-widget.tsx +114 -0
  147. package/src/browser/preferences/launch-preferences-contribution.ts +84 -3
  148. package/src/browser/preferences/launch.module.less +102 -0
  149. package/src/browser/preferences/launch.service.ts +133 -0
  150. package/src/browser/preferences/launch.view.tsx +494 -0
  151. package/src/browser/preferences/model/configuration-items.ts +24 -0
  152. package/src/browser/preferences/templates/additional-template.tsx +77 -0
  153. package/src/browser/preferences/templates/array-field-item-template.tsx +90 -0
  154. package/src/browser/preferences/templates/array-field-template.tsx +92 -0
  155. package/src/browser/preferences/templates/base-input-template.tsx +79 -0
  156. package/src/browser/preferences/templates/button-template.tsx +107 -0
  157. package/src/browser/preferences/templates/description-field-template.tsx +29 -0
  158. package/src/browser/preferences/templates/field-template.tsx +71 -0
  159. package/src/browser/preferences/templates/json-templates.module.less +133 -0
  160. package/src/browser/preferences/templates/object-field-template.tsx +156 -0
  161. package/src/browser/view/breakpoints/debug-breakpoints.module.less +19 -17
  162. package/src/browser/view/breakpoints/debug-breakpoints.view.tsx +22 -10
  163. package/src/browser/view/configuration/debug-configuration.service.ts +4 -0
  164. package/src/common/constants.ts +3 -0
  165. package/src/common/debug-schema.ts +5 -0
  166. package/src/common/debug-service.ts +13 -0
  167. package/src/common/index.ts +1 -1
  168. package/lib/browser/debug-schema-updater.d.ts.map +0 -1
  169. package/lib/browser/debug-schema-updater.js.map +0 -1
  170. package/lib/common/debug-schema-updater.d.ts +0 -3
  171. package/lib/common/debug-schema-updater.d.ts.map +0 -1
  172. package/lib/common/debug-schema-updater.js +0 -5
  173. package/lib/common/debug-schema-updater.js.map +0 -1
  174. package/src/common/debug-schema-updater.ts +0 -3
@@ -0,0 +1,494 @@
1
+ import { IChangeEvent, withTheme } from '@rjsf/core';
2
+ import { GenericObjectType, RJSFSchema, StrictRJSFSchema, SubmitButtonProps } from '@rjsf/utils';
3
+ import validator from '@rjsf/validator-ajv8';
4
+ import cls from 'classnames';
5
+ import lodashGet from 'lodash/get';
6
+ import throttle from 'lodash/throttle';
7
+ import React, { useCallback, useEffect, useMemo, useState } from 'react';
8
+ import AutoSizer from 'react-virtualized-auto-sizer';
9
+
10
+ import { Button, ComponentContextProvider, RecycleList } from '@opensumi/ide-components';
11
+ import {
12
+ localize,
13
+ getIcon,
14
+ useInjectable,
15
+ IJSONSchemaRegistry,
16
+ ISchemaContributions,
17
+ IJSONSchema,
18
+ IJSONSchemaSnippet,
19
+ IJSONSchemaMap,
20
+ isUndefined,
21
+ Disposable,
22
+ Schemes,
23
+ CommandService,
24
+ isObject,
25
+ } from '@opensumi/ide-core-browser';
26
+ import { EDITOR_COMMANDS } from '@opensumi/ide-core-browser';
27
+ import { EDirection, SplitPanel } from '@opensumi/ide-core-browser/lib/components';
28
+ import { MenuActionList } from '@opensumi/ide-core-browser/lib/components/actions/index';
29
+ import { LabelMenuItemNode } from '@opensumi/ide-core-browser/lib/menu/next/menu.interface';
30
+ import { acquireAjv } from '@opensumi/ide-core-browser/lib/utils/schema';
31
+ import { ReactEditorComponent } from '@opensumi/ide-editor/lib/browser/index';
32
+
33
+ import { DebugConfiguration } from '../../common/debug-configuration';
34
+ import { launchExtensionSchemaUri } from '../../common/debug-schema';
35
+ import { ILaunchService } from '../../common/debug-service';
36
+ import { DebugConfigurationManager } from '../debug-configuration-manager';
37
+ import { parseSnippet } from '../debugUtils';
38
+
39
+ import { CheckboxWidget } from './components/checkbox-widget';
40
+ import { AnyOfField } from './components/fields/any-of-field';
41
+ import { ArrayField } from './components/fields/array-field';
42
+ import { ObjectField } from './components/fields/object-filed';
43
+ import { TitleField } from './components/fields/title-field';
44
+ import { SelectWidget } from './components/select-widget';
45
+ import { TextWidget } from './components/text-widget';
46
+ import styles from './launch.module.less';
47
+ import { LaunchService } from './launch.service';
48
+ import { ConfigurationItemsModel } from './model/configuration-items';
49
+ import { WrapIfAdditionalTemplate } from './templates/additional-template';
50
+ import { ArrayFieldItemTemplate } from './templates/array-field-item-template';
51
+ import { ArrayFieldTemplate } from './templates/array-field-template';
52
+ import { BaseInputTemplate } from './templates/base-input-template';
53
+ import {
54
+ MoveUpButton,
55
+ MoveDownButton,
56
+ RemoveButton,
57
+ AddItemButton,
58
+ AddButton,
59
+ CopyButton,
60
+ } from './templates/button-template';
61
+ import { DescriptionFieldTemplate } from './templates/description-field-template';
62
+ import { FieldTemplate } from './templates/field-template';
63
+ import { ObjectFieldTemplate } from './templates/object-field-template';
64
+
65
+ export const LaunchViewContainer: ReactEditorComponent<any> = ({ resource }) => {
66
+ const { uri } = resource;
67
+ const schemaRegistry = useInjectable<IJSONSchemaRegistry>(IJSONSchemaRegistry);
68
+ const debugConfigurationManager = useInjectable<DebugConfigurationManager>(DebugConfigurationManager);
69
+ const launchService = useInjectable<LaunchService>(ILaunchService);
70
+ const commandService = useInjectable<CommandService>(CommandService);
71
+
72
+ const [currentConfigurationIndex, serCurrentConfigurationIndex] = useState<number>();
73
+ const [schemaContributions, setSchemaContributions] = useState<IJSONSchema>();
74
+ const [inputConfigurationItems, setInputConfigurationItems] = useState<ConfigurationItemsModel[]>([]);
75
+
76
+ useEffect(() => {
77
+ const disposed = new Disposable();
78
+
79
+ disposed.addDispose(
80
+ schemaRegistry.onDidChangeSchema((uri: string) => {
81
+ if (uri === launchExtensionSchemaUri) {
82
+ handleSchemaSnippets(schemaRegistry.getSchemaContributions());
83
+ }
84
+ }),
85
+ );
86
+
87
+ disposed.addDispose(
88
+ debugConfigurationManager.onDidChange(async () => {
89
+ handleInputConfigurationItems();
90
+ }),
91
+ );
92
+
93
+ handleSchemaSnippets(schemaRegistry.getSchemaContributions());
94
+ handleInputConfigurationItems();
95
+
96
+ return () => disposed.dispose();
97
+ }, []);
98
+
99
+ const fileUri = useMemo(() => uri.withScheme(Schemes.file), [uri]);
100
+
101
+ const handleSchemaSnippets = useCallback(
102
+ (contributions: ISchemaContributions) => {
103
+ const launchExtension = contributions.schemas[launchExtensionSchemaUri];
104
+
105
+ if (!launchExtension) {
106
+ return;
107
+ }
108
+
109
+ setSchemaContributions(launchExtension);
110
+ },
111
+ [schemaContributions],
112
+ );
113
+
114
+ const handleInputConfigurationItems = useCallback(() => {
115
+ const all = debugConfigurationManager.all;
116
+ if (!Array.isArray(all)) {
117
+ return;
118
+ }
119
+
120
+ setInputConfigurationItems(
121
+ all.map((config) => new ConfigurationItemsModel(config.configuration.name, config.configuration)),
122
+ );
123
+ }, []);
124
+
125
+ const snippetItems = useMemo(() => {
126
+ if (!schemaContributions) {
127
+ return [];
128
+ }
129
+
130
+ const snippets: IJSONSchemaSnippet[] = lodashGet(schemaContributions, [
131
+ 'properties',
132
+ 'configurations',
133
+ 'items',
134
+ 'defaultSnippets',
135
+ ] as (keyof IJSONSchema)[]);
136
+ return snippets || [];
137
+ }, [schemaContributions]);
138
+
139
+ const onSelectedConfiguration = useCallback((current: ConfigurationItemsModel, index: number) => {
140
+ const { configuration } = current;
141
+ if (!configuration) {
142
+ return;
143
+ }
144
+
145
+ launchService.nextNewFormData(configuration, false);
146
+
147
+ serCurrentConfigurationIndex(index);
148
+ }, []);
149
+
150
+ const currentSnippetItem = useMemo(() => {
151
+ if (inputConfigurationItems && !isUndefined(currentConfigurationIndex)) {
152
+ const current = inputConfigurationItems[currentConfigurationIndex];
153
+ if (!current) {
154
+ return undefined;
155
+ }
156
+
157
+ const { configuration, description, label } = current;
158
+ if (!configuration) {
159
+ return;
160
+ }
161
+
162
+ return {
163
+ body: configuration,
164
+ description,
165
+ label,
166
+ };
167
+ }
168
+ return undefined;
169
+ }, [inputConfigurationItems, currentConfigurationIndex]);
170
+
171
+ const onAddConfigurationItems = useCallback(
172
+ async (newItems: ConfigurationItemsModel) => {
173
+ const { configuration } = newItems;
174
+ await debugConfigurationManager.insertConfiguration(fileUri, configuration);
175
+ commandService.executeCommand(EDITOR_COMMANDS.SAVE_URI.id, fileUri);
176
+ },
177
+ [snippetItems],
178
+ );
179
+
180
+ const scheduleUpdateConfigurationsInResource = throttle(
181
+ async (data, currentConfigurationIndex) =>
182
+ await launchService.modifyConfigurationsInResource(fileUri, data, currentConfigurationIndex),
183
+ 100,
184
+ );
185
+
186
+ const onFormChange = useCallback(
187
+ async (data: IChangeEvent) => {
188
+ const { formData } = data;
189
+ if (!formData || isUndefined(currentConfigurationIndex)) {
190
+ return;
191
+ }
192
+
193
+ scheduleUpdateConfigurationsInResource(data, currentConfigurationIndex);
194
+ },
195
+ [currentConfigurationIndex, currentSnippetItem],
196
+ );
197
+
198
+ return (
199
+ <ComponentContextProvider value={{ getIcon, localize }}>
200
+ <div className={styles.launch_container}>
201
+ <SplitPanel
202
+ id='launch-container'
203
+ resizeHandleClassName={styles.devider}
204
+ className={styles.launch_panel}
205
+ direction={EDirection.LeftToRight}
206
+ >
207
+ <LaunchIndexs
208
+ data-sp-defaultSize={240}
209
+ data-sp-minSize={150}
210
+ inputConfigurationItems={inputConfigurationItems}
211
+ snippetItems={snippetItems}
212
+ onSelectedConfiguration={onSelectedConfiguration}
213
+ onAddConfigurationItems={onAddConfigurationItems}
214
+ currentConfigurationIndex={currentConfigurationIndex}
215
+ />
216
+ <LaunchBody
217
+ data-sp-flex={1}
218
+ snippetItem={currentSnippetItem}
219
+ schemaContributions={schemaContributions}
220
+ onChange={onFormChange}
221
+ />
222
+ </SplitPanel>
223
+ </div>
224
+ </ComponentContextProvider>
225
+ );
226
+ };
227
+
228
+ const LaunchIndexs = ({
229
+ snippetItems,
230
+ onSelectedConfiguration,
231
+ onAddConfigurationItems,
232
+ inputConfigurationItems,
233
+ currentConfigurationIndex,
234
+ }: {
235
+ snippetItems: IJSONSchemaSnippet[];
236
+ onSelectedConfiguration: (data: ConfigurationItemsModel, index: number) => void;
237
+ onAddConfigurationItems: (data: ConfigurationItemsModel) => void;
238
+ inputConfigurationItems: ConfigurationItemsModel[];
239
+ currentConfigurationIndex: number | undefined;
240
+ }) => {
241
+ const [menuOpen, setMenuOpen] = React.useState<boolean>(false);
242
+ const [configurationItems, setConfigurationItems] = useState<ConfigurationItemsModel[]>(inputConfigurationItems);
243
+
244
+ useEffect(() => {
245
+ setConfigurationItems([...inputConfigurationItems]);
246
+ }, [inputConfigurationItems]);
247
+
248
+ const handleConfigurationItemsClick = useCallback((data: ConfigurationItemsModel, index: number) => {
249
+ onSelectedConfiguration(data, index);
250
+ }, []);
251
+
252
+ const template = ({ data, index }) => (
253
+ <div
254
+ key={index}
255
+ className={cls(styles.configuration_item, currentConfigurationIndex === index ? styles.selected : '')}
256
+ onClick={() => handleConfigurationItemsClick(data, index)}
257
+ >
258
+ <div className={styles.configuration_wrapper}>
259
+ <span className={styles.configuration_description}>{(data as ConfigurationItemsModel).label}</span>
260
+ </div>
261
+ </div>
262
+ );
263
+
264
+ const handleMenuItemClick = useCallback(
265
+ (item: LabelMenuItemNode) => {
266
+ setMenuOpen(false);
267
+
268
+ const { label } = item;
269
+ const findItem = snippetItems.find((snippet) => snippet.label === label);
270
+ if (!findItem) {
271
+ return;
272
+ }
273
+
274
+ const { body } = findItem;
275
+ if (!isObject(body)) {
276
+ return;
277
+ }
278
+
279
+ // 将 body 里一些形如 ${1:xxxx} 这样的符号给过滤掉
280
+ const parseBody: DebugConfiguration = Object.keys(body).reduce((pre: DebugConfiguration, cur: string) => {
281
+ const curValue = body[cur];
282
+
283
+ if (typeof curValue === 'string') {
284
+ pre[cur] = parseSnippet(curValue);
285
+ } else if (Array.isArray(curValue)) {
286
+ pre[cur] = curValue.map((value: any) => {
287
+ if (typeof value == 'string') {
288
+ return parseSnippet(value);
289
+ }
290
+ return value;
291
+ });
292
+ }
293
+
294
+ return pre;
295
+ }, body);
296
+
297
+ const itemModel = new ConfigurationItemsModel(findItem.label!, parseBody);
298
+ itemModel.setDescription(findItem.description || '');
299
+
300
+ onAddConfigurationItems(itemModel);
301
+ },
302
+ [configurationItems, snippetItems],
303
+ );
304
+
305
+ const handleVisibleChange = (visible: boolean) => {
306
+ setMenuOpen(visible);
307
+ };
308
+
309
+ const snippetMenu = useMemo(
310
+ () => (
311
+ <MenuActionList
312
+ data={snippetItems.map((item) => new LabelMenuItemNode(item.label!))}
313
+ afterClick={(item: LabelMenuItemNode) => handleMenuItemClick(item)}
314
+ />
315
+ ),
316
+ [snippetItems, configurationItems],
317
+ );
318
+
319
+ return (
320
+ <div className={styles.launch_indexes_container}>
321
+ <AutoSizer className={styles.configuration_items_box}>
322
+ {({ width, height }) =>
323
+ configurationItems.length === 0 ? (
324
+ <div style={{ width }} className={styles.not_configuration_content}>
325
+ {localize('debug.action.no.configuration')}
326
+ </div>
327
+ ) : (
328
+ <RecycleList width={width} height={height} data={configurationItems} template={template} />
329
+ )
330
+ }
331
+ </AutoSizer>
332
+ <div className={styles.foot_box}>
333
+ <Button
334
+ className={styles.button}
335
+ placement={'topCenter'}
336
+ menu={snippetMenu}
337
+ moreVisible={menuOpen}
338
+ onVisibleChange={handleVisibleChange}
339
+ >
340
+ {localize('debug.action.add.configuration')}
341
+ </Button>
342
+ </div>
343
+ </div>
344
+ );
345
+ };
346
+
347
+ const Form = withTheme({
348
+ widgets: {
349
+ TextWidget,
350
+ SelectWidget,
351
+ CheckboxWidget,
352
+ },
353
+ fields: {
354
+ ObjectField,
355
+ },
356
+ });
357
+
358
+ const LaunchBody = ({
359
+ snippetItem,
360
+ schemaContributions,
361
+ onChange,
362
+ }: {
363
+ snippetItem?: IJSONSchemaSnippet;
364
+ schemaContributions?: IJSONSchema;
365
+ onChange: (data: IChangeEvent, id?: string) => void;
366
+ }) => {
367
+ if (!snippetItem) {
368
+ return <div className={styles.no_onfiguration}>{localize('debug.action.no.configuration')}</div>;
369
+ }
370
+
371
+ const launchService = useInjectable<LaunchService>(ILaunchService);
372
+
373
+ const schemaProperties: IJSONSchema | undefined = useMemo(() => {
374
+ const ajv = acquireAjv();
375
+ // 1. 先从 schema 中找出 oneOf 池
376
+ const oneOfPool: IJSONSchema[] =
377
+ lodashGet(schemaContributions, ['properties', 'configurations', 'items', 'oneOf'] as (keyof IJSONSchema)[]) || [];
378
+
379
+ // 2. 再从 snippetItem body 中找出符合条件的 oneOf(可能存在多个,如果有多个就只取第一个)
380
+ const findOneOf = oneOfPool.find((oneOf) => {
381
+ const { body } = snippetItem;
382
+ return ajv!.validate(oneOf, body);
383
+ });
384
+
385
+ if (findOneOf) {
386
+ launchService.setRawSchemaProperties(findOneOf);
387
+ return findOneOf;
388
+ }
389
+
390
+ return;
391
+ }, [snippetItem, schemaContributions]);
392
+
393
+ const schema: RJSFSchema | undefined = useMemo(() => {
394
+ if (!(schemaProperties && schemaProperties.properties)) {
395
+ return;
396
+ }
397
+
398
+ const { label, body, description } = snippetItem;
399
+ const { properties, required } = schemaProperties;
400
+
401
+ const snippetProperties = Object.keys(body).reduce((pre: IJSONSchemaMap, cur: string) => {
402
+ const curProp = properties![cur];
403
+
404
+ if (curProp?.type === 'array' && isUndefined(curProp?.items)) {
405
+ curProp.items = { type: 'string' };
406
+ }
407
+
408
+ // 如果 type 是数组,则取第一个
409
+ if (Array.isArray(curProp?.type)) {
410
+ curProp.type = curProp.type![0] || 'string';
411
+ }
412
+
413
+ // 去掉 anyof 中的空对象
414
+ if (Array.isArray(curProp?.anyOf)) {
415
+ curProp.anyOf = curProp.anyOf.filter((c) => Object.keys(c).length > 0);
416
+ }
417
+
418
+ // 如果 type 是 object 且存在 additionalProperties 时,固定将其设置为 additionalProperties: { type: 'string' }
419
+ if (curProp?.type === 'object' && !isUndefined(curProp?.additionalProperties)) {
420
+ curProp.additionalProperties = { type: 'string' };
421
+ }
422
+
423
+ // 将 markdownDescription 赋给 description
424
+ if (!curProp?.description && curProp?.markdownDescription) {
425
+ curProp.description = curProp.markdownDescription;
426
+ }
427
+
428
+ pre[cur] = curProp;
429
+ return pre;
430
+ }, {});
431
+
432
+ const schema = {
433
+ title: label,
434
+ type: 'object',
435
+ required,
436
+ description,
437
+ properties: snippetProperties,
438
+ } as StrictRJSFSchema;
439
+
440
+ launchService.nextNewSchema(schema);
441
+
442
+ return schema;
443
+ }, [snippetItem, schemaProperties]);
444
+
445
+ const hanldeAddItem = useCallback(
446
+ (item: LabelMenuItemNode) => {
447
+ if (!(schemaProperties && schemaProperties.properties)) {
448
+ return;
449
+ }
450
+
451
+ if (!(schema && schema.properties)) {
452
+ return;
453
+ }
454
+
455
+ const { label } = item;
456
+ launchService.addNewItem(label);
457
+ },
458
+ [snippetItem, schemaProperties, schema],
459
+ );
460
+
461
+ return (
462
+ <div className={styles.launch_schema_body_container}>
463
+ {schema && schemaProperties && (
464
+ <Form
465
+ formData={snippetItem.body}
466
+ schema={schema}
467
+ validator={validator}
468
+ fields={{ AnyOfField, OneOfField: AnyOfField, ArrayField }}
469
+ onChange={onChange}
470
+ templates={{
471
+ ArrayFieldTemplate,
472
+ ArrayFieldItemTemplate,
473
+ DescriptionFieldTemplate,
474
+ FieldTemplate,
475
+ ObjectFieldTemplate,
476
+ WrapIfAdditionalTemplate,
477
+ BaseInputTemplate,
478
+ TitleFieldTemplate: TitleField,
479
+ ButtonTemplates: {
480
+ MoveUpButton,
481
+ MoveDownButton,
482
+ RemoveButton,
483
+ SubmitButton: (
484
+ props: React.PropsWithChildren<SubmitButtonProps<unknown, RJSFSchema, GenericObjectType>>,
485
+ ) => <AddItemButton {...props} onAddClick={hanldeAddItem}></AddItemButton>,
486
+ AddButton,
487
+ CopyButton,
488
+ },
489
+ }}
490
+ />
491
+ )}
492
+ </div>
493
+ );
494
+ };
@@ -0,0 +1,24 @@
1
+ import { uuid } from '@opensumi/ide-core-common';
2
+
3
+ import { DebugConfiguration } from '../../../common';
4
+
5
+ export class ConfigurationItemsModel {
6
+ private _uniqueID: string;
7
+ private _description: string;
8
+
9
+ public get uniqueID(): string {
10
+ return this._uniqueID;
11
+ }
12
+
13
+ public get description(): string {
14
+ return this._description;
15
+ }
16
+
17
+ constructor(readonly label: string, readonly configuration: DebugConfiguration) {
18
+ this._uniqueID = uuid(6);
19
+ }
20
+
21
+ public setDescription(data: string): void {
22
+ this._description = data;
23
+ }
24
+ }
@@ -0,0 +1,77 @@
1
+ import {
2
+ ADDITIONAL_PROPERTY_FLAG,
3
+ FormContextType,
4
+ RJSFSchema,
5
+ StrictRJSFSchema,
6
+ WrapIfAdditionalTemplateProps,
7
+ } from '@rjsf/utils';
8
+ import React, { FocusEvent, useCallback } from 'react';
9
+
10
+ import { Input } from '@opensumi/ide-components';
11
+ import { formatLocalize } from '@opensumi/ide-core-common';
12
+
13
+ import styles from './json-templates.module.less';
14
+
15
+ export const WrapIfAdditionalTemplate = <
16
+ T = any,
17
+ S extends StrictRJSFSchema = RJSFSchema,
18
+ F extends FormContextType = any,
19
+ >(
20
+ props: WrapIfAdditionalTemplateProps<T, S, F>,
21
+ ) => {
22
+ const {
23
+ children,
24
+ classNames,
25
+ style,
26
+ disabled,
27
+ id,
28
+ label,
29
+ onKeyChange,
30
+ onDropPropertyClick,
31
+ readonly,
32
+ registry,
33
+ schema,
34
+ } = props;
35
+ const { readonlyAsDisabled = true } = registry.formContext;
36
+ const { templates } = registry;
37
+ const { RemoveButton } = templates.ButtonTemplates;
38
+ // 如果是用户手动添加 property 则存在该标识
39
+ const isPropertyFlag = ADDITIONAL_PROPERTY_FLAG in schema;
40
+
41
+ if (!isPropertyFlag) {
42
+ return (
43
+ <div className={classNames} style={style}>
44
+ {children}
45
+ </div>
46
+ );
47
+ }
48
+
49
+ const handleBlur = useCallback(
50
+ ({ target }: FocusEvent<HTMLInputElement>) => onKeyChange(target.value),
51
+ [onKeyChange],
52
+ );
53
+
54
+ return (
55
+ <div className={classNames} style={style}>
56
+ <div className={styles.additional_field_template}>
57
+ <div className={styles.form_additional_container}>
58
+ <div className={styles.form_additional}>
59
+ <Input
60
+ className={styles.form_control}
61
+ defaultValue={label}
62
+ value={label}
63
+ placeholder={formatLocalize('debug.launch.view.template.input.placeholder', 'Key')}
64
+ disabled={disabled || (readonlyAsDisabled && readonly)}
65
+ id={`${id}-key`}
66
+ name={`${id}-key`}
67
+ onBlur={!readonly ? handleBlur : undefined}
68
+ type='text'
69
+ />
70
+ </div>
71
+ <div className={styles.form_additional_children}>{children}</div>
72
+ <RemoveButton disabled={disabled || readonly} onClick={onDropPropertyClick(label)} registry={registry} />
73
+ </div>
74
+ </div>
75
+ </div>
76
+ );
77
+ };
@@ -0,0 +1,90 @@
1
+ import {
2
+ ArrayFieldTemplateItemType,
3
+ FieldTemplateProps,
4
+ FormContextType,
5
+ RJSFSchema,
6
+ StrictRJSFSchema,
7
+ } from '@rjsf/utils';
8
+ import cls from 'classnames';
9
+ import React, { Fragment, useMemo } from 'react';
10
+
11
+ import styles from './json-templates.module.less';
12
+
13
+ const BTN_GRP_STYLE = {
14
+ width: '100%',
15
+ };
16
+
17
+ const BTN_STYLE = {
18
+ width: 'calc(100% / 4)',
19
+ };
20
+
21
+ export const ArrayFieldItemTemplate = <
22
+ T = any,
23
+ S extends StrictRJSFSchema = RJSFSchema,
24
+ F extends FormContextType = any,
25
+ >(
26
+ props: ArrayFieldTemplateItemType<T, S, F>,
27
+ ) => {
28
+ const {
29
+ className,
30
+ children,
31
+ disabled,
32
+ hasCopy,
33
+ hasMoveDown,
34
+ hasMoveUp,
35
+ hasRemove,
36
+ hasToolbar,
37
+ index,
38
+ onCopyIndexClick,
39
+ onDropIndexClick,
40
+ onReorderClick,
41
+ readonly,
42
+ registry,
43
+ } = props;
44
+ const { CopyButton, MoveDownButton, MoveUpButton, RemoveButton } = registry.templates.ButtonTemplates;
45
+
46
+ const onCopyClick = useMemo(() => onCopyIndexClick(index), [index, onCopyIndexClick]);
47
+ const onRemoveClick = useMemo(() => onDropIndexClick(index), [index, onDropIndexClick]);
48
+ const onArrowUpClick = useMemo(() => onReorderClick(index, index - 1), [index, onReorderClick]);
49
+ const onArrowDownClick = useMemo(() => onReorderClick(index, index + 1), [index, onReorderClick]);
50
+
51
+ return (
52
+ <div key={`array-item-${index}`} className={cls(className, styles.array_field_item_template)}>
53
+ <div className={styles.control_field}>{React.cloneElement(children, { name: '' })}</div>
54
+
55
+ {hasToolbar && (
56
+ <div className={styles.toolbar}>
57
+ <div style={BTN_GRP_STYLE}>
58
+ {(hasMoveUp || hasMoveDown) && (
59
+ <MoveUpButton
60
+ disabled={disabled || readonly || !hasMoveUp}
61
+ onClick={onArrowUpClick}
62
+ style={BTN_STYLE}
63
+ registry={registry}
64
+ />
65
+ )}
66
+ {(hasMoveUp || hasMoveDown) && (
67
+ <MoveDownButton
68
+ disabled={disabled || readonly || !hasMoveDown}
69
+ onClick={onArrowDownClick}
70
+ style={BTN_STYLE}
71
+ registry={registry}
72
+ />
73
+ )}
74
+ {hasCopy && (
75
+ <CopyButton disabled={disabled || readonly} onClick={onCopyClick} style={BTN_STYLE} registry={registry} />
76
+ )}
77
+ {hasRemove && (
78
+ <RemoveButton
79
+ disabled={disabled || readonly}
80
+ onClick={onRemoveClick}
81
+ style={BTN_STYLE}
82
+ registry={registry}
83
+ />
84
+ )}
85
+ </div>
86
+ </div>
87
+ )}
88
+ </div>
89
+ );
90
+ };