@vc-shell/vc-app-skill 2.0.0-alpha.32 → 2.0.0-alpha.33
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 +15 -0
- package/package.json +1 -1
- package/runtime/VERSION +1 -1
- package/runtime/agents/migration-agent.md +83 -0
- package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
- package/runtime/knowledge/docs/core/composables/useBladeForm/useBladeForm.docs.md +55 -1
- package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +102 -0
- package/runtime/knowledge/docs/ui/components/atoms/vc-card/vc-card.docs.md +4 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +4 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-group/vc-radio-group.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +5 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +7 -0
- package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +30 -0
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +28 -0
- package/runtime/knowledge/migration-prompts/blade-form-migration.md +246 -0
- package/runtime/knowledge/migration-prompts/blade-props-migration.md +195 -0
- package/runtime/knowledge/migration-prompts/notifications-migration.md +218 -0
- package/runtime/knowledge/migration-prompts/nswag-migration.md +248 -0
- package/runtime/knowledge/migration-prompts/widgets-migration.md +157 -0
- package/runtime/vc-app.md +126 -0
- package/runtime/knowledge/docs/core/constants/constants.docs.md +0 -185
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nswag-migration
|
|
3
|
+
description: AI transformation rules for NSwag class→interface DTO migration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# NSwag API Client Migration: Class to Interface
|
|
7
|
+
|
|
8
|
+
You are tasked with fixing TypeScript errors caused by migrating NSwag-generated API clients from class-based to interface-based data models.
|
|
9
|
+
|
|
10
|
+
**Context:**
|
|
11
|
+
- API Client CLASSES (e.g., `*Client` classes) remain unchanged — they still have constructors
|
|
12
|
+
- DATA MODEL types (DTOs, Commands, Queries, etc.) are now INTERFACES instead of classes
|
|
13
|
+
- Interfaces cannot be instantiated with `new` — use object literals with type assertions instead
|
|
14
|
+
|
|
15
|
+
## RULE 1: Import Name Changes (Remove "I" Prefix)
|
|
16
|
+
|
|
17
|
+
**Error:** `error TS2724: has no exported member named 'IXxx'. Did you mean 'Xxx'?`
|
|
18
|
+
|
|
19
|
+
**Fix:** Remove the "I" prefix from all data model interface imports.
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// BEFORE
|
|
23
|
+
import { IOffer, ISeller, ISearchQuery } from "@your-api-package";
|
|
24
|
+
|
|
25
|
+
// AFTER
|
|
26
|
+
import { Offer, Seller, SearchQuery } from "@your-api-package";
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Also update all type annotations in the file:
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
// BEFORE
|
|
33
|
+
const item = ref<IOffer>(...);
|
|
34
|
+
function process(data: IOffer): IOffer { ... }
|
|
35
|
+
|
|
36
|
+
// AFTER
|
|
37
|
+
const item = ref<Offer>(...);
|
|
38
|
+
function process(data: Offer): Offer { ... }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## RULE 2: Class Instantiation → Object Literals
|
|
42
|
+
|
|
43
|
+
**Error:** `error TS2693: 'Xxx' only refers to a type, but is being used as a value here`
|
|
44
|
+
|
|
45
|
+
**Fix:** Replace `new TypeName({...})` with `{...} as TypeName` or typed variable declaration.
|
|
46
|
+
|
|
47
|
+
**Pattern A — Command/Query objects:**
|
|
48
|
+
|
|
49
|
+
```typescript
|
|
50
|
+
// BEFORE
|
|
51
|
+
const command = new CreateCommand({
|
|
52
|
+
id: "123",
|
|
53
|
+
name: "Test",
|
|
54
|
+
details: new Details({ value: 100 }),
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// AFTER
|
|
58
|
+
const command: CreateCommand = {
|
|
59
|
+
id: "123",
|
|
60
|
+
name: "Test",
|
|
61
|
+
details: { value: 100 } as Details,
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Pattern B — Search/Query criteria:**
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
// BEFORE
|
|
69
|
+
const criteria = new SearchQuery({
|
|
70
|
+
take: 20,
|
|
71
|
+
skip: 0,
|
|
72
|
+
sort: "name:asc",
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
// AFTER
|
|
76
|
+
const criteria: SearchQuery = {
|
|
77
|
+
take: 20,
|
|
78
|
+
skip: 0,
|
|
79
|
+
sort: "name:asc",
|
|
80
|
+
};
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Pattern C — Empty/default objects:**
|
|
84
|
+
|
|
85
|
+
```typescript
|
|
86
|
+
// BEFORE
|
|
87
|
+
const item = ref<IEntity>(new Entity());
|
|
88
|
+
|
|
89
|
+
// AFTER
|
|
90
|
+
const item = ref<Entity>({} as Entity);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
**Pattern D — Nested objects:**
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
// BEFORE
|
|
97
|
+
const data = ref(new Parent({ child: new Child() }));
|
|
98
|
+
|
|
99
|
+
// AFTER
|
|
100
|
+
const data = ref<Parent>({
|
|
101
|
+
child: {} as Child,
|
|
102
|
+
} as Parent);
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Pattern E — With Vue reactive():**
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// BEFORE
|
|
109
|
+
const item = ref<Order>(reactive(new Order()));
|
|
110
|
+
|
|
111
|
+
// AFTER
|
|
112
|
+
const item = ref<Order>(reactive({} as Order));
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## RULE 3: Factory Functions for Framework Callbacks
|
|
116
|
+
|
|
117
|
+
**Error:** `error TS2693: 'PropertyValue' only refers to a type, but is being used as a value here`
|
|
118
|
+
|
|
119
|
+
When a framework function expects a constructor function (callable with `new`), create factory functions:
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// BEFORE — Framework expects constructor
|
|
123
|
+
const { loadItems } = useFrameworkHook<Type1, Type2>(
|
|
124
|
+
fetchFunction,
|
|
125
|
+
ItemClass,
|
|
126
|
+
OtherClass,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// AFTER — Create factory functions
|
|
130
|
+
const createItem = (data?: Partial<ItemType>): ItemType =>
|
|
131
|
+
({ ...data } as ItemType);
|
|
132
|
+
|
|
133
|
+
const createOther = (data?: Partial<OtherType>): OtherType =>
|
|
134
|
+
({ ...data } as OtherType);
|
|
135
|
+
|
|
136
|
+
const { loadItems } = useFrameworkHook<Type1, Type2>(
|
|
137
|
+
fetchFunction,
|
|
138
|
+
createItem,
|
|
139
|
+
createOther,
|
|
140
|
+
);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## RULE 4: Image Import Conflict with Global DOM Type
|
|
144
|
+
|
|
145
|
+
**Error:** `error TS2866: Import 'Image' conflicts with global value used in this file`
|
|
146
|
+
|
|
147
|
+
**Fix:** Use type-only import or rename:
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
// BEFORE
|
|
151
|
+
import { Image, Entity } from "@your-api-package";
|
|
152
|
+
|
|
153
|
+
// AFTER — Option 1: Type-only import
|
|
154
|
+
import { type Image, Entity } from "@your-api-package";
|
|
155
|
+
|
|
156
|
+
// AFTER — Option 2: Rename import
|
|
157
|
+
import { Image as ApiImage, Entity } from "@your-api-package";
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## RULE 5: Implicit Any Types
|
|
161
|
+
|
|
162
|
+
**Error:** `error TS7006: Parameter 'x' implicitly has an 'any' type`
|
|
163
|
+
|
|
164
|
+
**Fix:** Add explicit type annotations to callback parameters:
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// BEFORE
|
|
168
|
+
items.map((x) => x.id)
|
|
169
|
+
items.filter((item) => item.active)
|
|
170
|
+
data.forEach((d) => process(d))
|
|
171
|
+
|
|
172
|
+
// AFTER
|
|
173
|
+
items.map((x: ItemType) => x.id)
|
|
174
|
+
items.filter((item: ItemType) => item.active)
|
|
175
|
+
data.forEach((d: DataType) => process(d))
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## RULE 6: Type Mismatch in Function Arguments
|
|
179
|
+
|
|
180
|
+
**Error:** `error TS2345: Argument of type 'X' is not assignable to parameter of type 'Y'`
|
|
181
|
+
|
|
182
|
+
Check if the function signature expects a different type (often an ID instead of a full object):
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
// BEFORE
|
|
186
|
+
someFunction(asset) // asset is full object
|
|
187
|
+
|
|
188
|
+
// AFTER
|
|
189
|
+
someFunction(asset.id) // pass the id property
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Important Notes
|
|
193
|
+
|
|
194
|
+
1. **API Client Classes are NOT affected** — Do NOT modify client classes like `*Client`. They remain classes with constructors:
|
|
195
|
+
```typescript
|
|
196
|
+
const { getApiClient } = useApiClient(MyApiClient); // No change needed
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
2. **Spread operators work with interfaces:**
|
|
200
|
+
```typescript
|
|
201
|
+
const updated = { ...existingItem, name: "New Name" }; // Works fine
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
3. **Required properties must be provided** when using type assertions:
|
|
205
|
+
```typescript
|
|
206
|
+
const details: ItemDetails = {
|
|
207
|
+
sku: item.sku || "",
|
|
208
|
+
...otherProps,
|
|
209
|
+
};
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
4. **Generic type parameters need updating too:**
|
|
213
|
+
```typescript
|
|
214
|
+
// BEFORE
|
|
215
|
+
const { action } = useAsync<ISearchQuery>(...)
|
|
216
|
+
|
|
217
|
+
// AFTER
|
|
218
|
+
const { action } = useAsync<SearchQuery>(...)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
5. **Interfaces with all optional properties** can use empty object:
|
|
222
|
+
```typescript
|
|
223
|
+
const query: SearchQuery = {}; // OK if all properties are optional
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
6. **Interfaces with required properties** need those properties:
|
|
227
|
+
```typescript
|
|
228
|
+
const item: Item = { id: "default" }; // Must provide 'id'
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## Quick Reference Table
|
|
232
|
+
|
|
233
|
+
| Error Code | Pattern | Fix |
|
|
234
|
+
|------------|---------|-----|
|
|
235
|
+
| TS2724 | `IXxx` not found | Remove "I" prefix from import |
|
|
236
|
+
| TS2693 | Type used as value | Replace `new Type({})` with `{} as Type` |
|
|
237
|
+
| TS2866 | Import conflicts with global | Use `type` import or rename |
|
|
238
|
+
| TS7006 | Implicit any | Add explicit type annotation |
|
|
239
|
+
| TS2345 | Type not assignable | Check if property (like `.id`) should be passed |
|
|
240
|
+
|
|
241
|
+
## Verification
|
|
242
|
+
|
|
243
|
+
After making changes:
|
|
244
|
+
|
|
245
|
+
1. Run TypeScript compiler: `npx tsc --noEmit` or `npx vue-tsc --noEmit`
|
|
246
|
+
2. Verify no new errors were introduced
|
|
247
|
+
3. Build the project to ensure everything compiles
|
|
248
|
+
4. Test affected functionality if possible
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: widgets-migration
|
|
3
|
+
description: AI transformation rules for useWidgets→useBladeWidgets migration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Widget Migration: useWidgets → useBladeWidgets
|
|
7
|
+
|
|
8
|
+
Migrate blade widgets from the imperative `useWidgets()` + `registerWidget()` API to the declarative `useBladeWidgets()` composable. The new API eliminates manual registration/cleanup and removes the need for per-widget `.vue` components when they only render a standard sidebar item.
|
|
9
|
+
|
|
10
|
+
## RULE 1: Create Widget Composable
|
|
11
|
+
|
|
12
|
+
For each blade that calls `registerWidget()`, create a `widgets/useXxxWidgets.ts` composable.
|
|
13
|
+
|
|
14
|
+
**BEFORE:**
|
|
15
|
+
|
|
16
|
+
```typescript
|
|
17
|
+
// In XxxDetails.vue <script setup>
|
|
18
|
+
import { useWidgets, useBlade } from "@vc-shell/framework";
|
|
19
|
+
import type { BladeInstance } from "@vc-shell/framework";
|
|
20
|
+
import { onMounted, onUnmounted } from "vue";
|
|
21
|
+
import OffersWidget from "../widgets/OffersWidget.vue";
|
|
22
|
+
|
|
23
|
+
const { registerWidget, clearBladeWidgets } = useWidgets();
|
|
24
|
+
const { openBlade } = useBlade();
|
|
25
|
+
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
registerWidget(
|
|
28
|
+
{
|
|
29
|
+
id: "OffersWidget",
|
|
30
|
+
component: OffersWidget,
|
|
31
|
+
props: {
|
|
32
|
+
count: offersCount,
|
|
33
|
+
onClick: () => openBlade({ name: "OffersList", options: { productId: entity.value.id } }),
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
bladeContext.id,
|
|
37
|
+
);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
onUnmounted(() => {
|
|
41
|
+
clearBladeWidgets(bladeContext.id);
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**AFTER:**
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// widgets/useProductWidgets.ts
|
|
49
|
+
import { useBladeWidgets, useBlade } from "@vc-shell/framework";
|
|
50
|
+
import type { UseBladeWidgetsReturn } from "@vc-shell/framework";
|
|
51
|
+
import { computed, type Ref } from "vue";
|
|
52
|
+
|
|
53
|
+
interface UseProductWidgetsOptions {
|
|
54
|
+
item: Ref<Product | undefined>;
|
|
55
|
+
isVisible: Ref<boolean> | boolean;
|
|
56
|
+
offersCount: Ref<number>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export function useProductWidgets(options: UseProductWidgetsOptions): UseBladeWidgetsReturn {
|
|
60
|
+
const { item, isVisible, offersCount } = options;
|
|
61
|
+
const { openBlade } = useBlade();
|
|
62
|
+
|
|
63
|
+
return useBladeWidgets([
|
|
64
|
+
{
|
|
65
|
+
id: "OffersWidget",
|
|
66
|
+
icon: "lucide-tag",
|
|
67
|
+
title: "PRODUCTS.WIDGETS.OFFERS.TITLE",
|
|
68
|
+
badge: computed(() => offersCount.value),
|
|
69
|
+
isVisible,
|
|
70
|
+
onClick: () =>
|
|
71
|
+
openBlade({
|
|
72
|
+
name: "OffersList",
|
|
73
|
+
options: { productId: item.value?.id },
|
|
74
|
+
}),
|
|
75
|
+
onRefresh: async () => {
|
|
76
|
+
// load offers count logic here
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
]);
|
|
80
|
+
}
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## RULE 2: Replace Usage in Blade Page
|
|
84
|
+
|
|
85
|
+
Import the new composable and destructure `{ refreshAll }`.
|
|
86
|
+
|
|
87
|
+
**BEFORE:**
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// XxxDetails.vue <script setup>
|
|
91
|
+
import { useWidgets } from "@vc-shell/framework";
|
|
92
|
+
import OffersWidget from "../widgets/OffersWidget.vue";
|
|
93
|
+
import AssociationsWidget from "../widgets/AssociationsWidget.vue";
|
|
94
|
+
|
|
95
|
+
const { registerWidget, clearBladeWidgets } = useWidgets();
|
|
96
|
+
|
|
97
|
+
onMounted(() => {
|
|
98
|
+
registerWidget({ id: "OffersWidget", component: OffersWidget, props: { ... } }, bladeId);
|
|
99
|
+
registerWidget({ id: "AssociationsWidget", component: AssociationsWidget, props: { ... } }, bladeId);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
onUnmounted(() => {
|
|
103
|
+
clearBladeWidgets(bladeId);
|
|
104
|
+
});
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**AFTER:**
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// XxxDetails.vue <script setup>
|
|
111
|
+
import { useProductWidgets } from "../widgets/useProductWidgets";
|
|
112
|
+
|
|
113
|
+
const isExisting = computed(() => !!param.value);
|
|
114
|
+
|
|
115
|
+
const { refreshAll } = useProductWidgets({
|
|
116
|
+
item: entity,
|
|
117
|
+
isVisible: isExisting,
|
|
118
|
+
offersCount,
|
|
119
|
+
});
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## RULE 3: Remove Widget .vue Components
|
|
123
|
+
|
|
124
|
+
Delete widget `.vue` files that only render a standard sidebar item (icon + title + badge + click handler). These are replaced by the declarative config in `useBladeWidgets()`.
|
|
125
|
+
|
|
126
|
+
**Keep** the `.vue` component only if it has custom rendering beyond the standard widget layout.
|
|
127
|
+
|
|
128
|
+
**Delete:**
|
|
129
|
+
- `widgets/OffersWidget.vue` (if it only shows icon, title, badge, click)
|
|
130
|
+
- `widgets/AssociationsWidget.vue` (same)
|
|
131
|
+
|
|
132
|
+
**Keep:**
|
|
133
|
+
- `widgets/CustomChartWidget.vue` (has custom chart rendering)
|
|
134
|
+
|
|
135
|
+
## RULE 4: Remove Old Imports
|
|
136
|
+
|
|
137
|
+
Remove these imports that are no longer needed:
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// REMOVE all of these:
|
|
141
|
+
import { useWidgets } from "@vc-shell/framework";
|
|
142
|
+
import type { BladeInstance } from "@vc-shell/framework"; // if only used for widgets
|
|
143
|
+
import { registerWidget, unregisterWidget, clearBladeWidgets } from "...";
|
|
144
|
+
import { onUnmounted } from "vue"; // if only used for widget cleanup
|
|
145
|
+
import OffersWidget from "../widgets/OffersWidget.vue"; // deleted component
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Verification
|
|
149
|
+
|
|
150
|
+
After migration:
|
|
151
|
+
|
|
152
|
+
1. Run `npx tsc --noEmit` to verify no TypeScript errors
|
|
153
|
+
2. Confirm widgets appear in the blade sidebar
|
|
154
|
+
3. Confirm badge counts update reactively
|
|
155
|
+
4. Confirm clicking a widget opens the correct child blade
|
|
156
|
+
5. Confirm widgets are hidden when `isVisible` is false (e.g., on "create new" blades)
|
|
157
|
+
6. Confirm no console errors about widget registration/cleanup on blade close
|
package/runtime/vc-app.md
CHANGED
|
@@ -53,6 +53,7 @@ Parse `$ARGUMENTS` to determine the subcommand:
|
|
|
53
53
|
| `generate ...` | Section: `/vc-app generate` |
|
|
54
54
|
| `promote <moduleName>` | Section: `/vc-app promote` |
|
|
55
55
|
| `design ...` | Section: `/vc-app design` |
|
|
56
|
+
| `migrate` | Section: `/vc-app migrate` |
|
|
56
57
|
| empty / `help` / `--help` | Section: Help |
|
|
57
58
|
|
|
58
59
|
If no arguments match, show the help section.
|
|
@@ -73,6 +74,7 @@ Commands:
|
|
|
73
74
|
/vc-app generate Generate a full UI module from intent (list/details blades, composables, locales)
|
|
74
75
|
/vc-app promote <name> Transition a prototype module from mock data to real API client
|
|
75
76
|
/vc-app design [prompt] Generate a full application from a free-text description (multi-module)
|
|
77
|
+
/vc-app migrate Migrate existing app to latest @vc-shell/framework (CLI + AI)
|
|
76
78
|
|
|
77
79
|
Examples:
|
|
78
80
|
/vc-app create
|
|
@@ -1415,3 +1417,127 @@ Additional context:
|
|
|
1415
1417
|
```
|
|
1416
1418
|
|
|
1417
1419
|
The agent will read its own instruction file, load any required knowledge/pattern files, execute its generation rules, perform its self-check, and report back.
|
|
1420
|
+
|
|
1421
|
+
---
|
|
1422
|
+
|
|
1423
|
+
## /vc-app migrate
|
|
1424
|
+
|
|
1425
|
+
Fully automatic migration to the latest @vc-shell/framework version. Runs the CLI migrator for mechanical transforms, installs updated dependencies, then uses AI to complete manual migrations.
|
|
1426
|
+
|
|
1427
|
+
### Step 1: Pre-flight checks
|
|
1428
|
+
|
|
1429
|
+
1. Verify `@vc-shell/framework` exists in package.json (dependencies or devDependencies). If not found, stop: "This doesn't appear to be a vc-shell project."
|
|
1430
|
+
2. Run `git status --porcelain` — if output is non-empty, warn: "You have uncommitted changes. Commit or stash before migrating." Ask user to confirm before proceeding.
|
|
1431
|
+
3. Read current framework version from package.json for display.
|
|
1432
|
+
|
|
1433
|
+
### Step 2: Run CLI migrator
|
|
1434
|
+
|
|
1435
|
+
Resolve the migrate CLI binary. Run this shell snippet and use the result:
|
|
1436
|
+
|
|
1437
|
+
```bash
|
|
1438
|
+
if [ -n "$VC_SHELL_MIGRATE_CLI" ] && [ -f "$VC_SHELL_MIGRATE_CLI" ]; then
|
|
1439
|
+
echo "node $VC_SHELL_MIGRATE_CLI"
|
|
1440
|
+
elif [ -f "./node_modules/@vc-shell/migrate/dist/cli.js" ]; then
|
|
1441
|
+
echo "node ./node_modules/@vc-shell/migrate/dist/cli.js"
|
|
1442
|
+
else
|
|
1443
|
+
echo "npx @vc-shell/migrate"
|
|
1444
|
+
fi
|
|
1445
|
+
```
|
|
1446
|
+
|
|
1447
|
+
Priority:
|
|
1448
|
+
1. **Env override:** `VC_SHELL_MIGRATE_CLI` env var
|
|
1449
|
+
2. **Project node_modules:** `./node_modules/@vc-shell/migrate/dist/cli.js`
|
|
1450
|
+
3. **npx fallback:** `npx @vc-shell/migrate`
|
|
1451
|
+
|
|
1452
|
+
Run:
|
|
1453
|
+
|
|
1454
|
+
```bash
|
|
1455
|
+
{resolved_migrate_command} --update-deps
|
|
1456
|
+
```
|
|
1457
|
+
|
|
1458
|
+
Display the output to the user. If the command fails, stop and show the error.
|
|
1459
|
+
|
|
1460
|
+
### Step 3: Install dependencies
|
|
1461
|
+
|
|
1462
|
+
Run:
|
|
1463
|
+
|
|
1464
|
+
```bash
|
|
1465
|
+
yarn install
|
|
1466
|
+
```
|
|
1467
|
+
|
|
1468
|
+
If yarn fails (version conflicts, missing packages), stop and show the error. Dependencies must resolve before AI migration can type-check.
|
|
1469
|
+
|
|
1470
|
+
### Step 4: Parse migration report
|
|
1471
|
+
|
|
1472
|
+
Read `MIGRATION_REPORT.md` from project root.
|
|
1473
|
+
|
|
1474
|
+
Parse the "Manual Migration Required" section. Extract each topic heading and the affected files listed under it.
|
|
1475
|
+
|
|
1476
|
+
Map topic headings to migration prompt files and pattern files:
|
|
1477
|
+
|
|
1478
|
+
| Report Heading contains | Migration Prompt | Pattern |
|
|
1479
|
+
|---|---|---|
|
|
1480
|
+
| Widget | `{KNOWLEDGE_BASE}/migration-prompts/widgets-migration.md` | `{KNOWLEDGE_BASE}/patterns/blade-widget.md` |
|
|
1481
|
+
| Form Management / useBladeForm | `{KNOWLEDGE_BASE}/migration-prompts/blade-form-migration.md` | `{KNOWLEDGE_BASE}/patterns/form-validation.md` |
|
|
1482
|
+
| Injection Key | `{KNOWLEDGE_BASE}/migration-prompts/blade-props-migration.md` | `{KNOWLEDGE_BASE}/patterns/blade-navigation.md` |
|
|
1483
|
+
| NSwag / DTO / Clone-then-mutate | `{KNOWLEDGE_BASE}/migration-prompts/nswag-migration.md` | — |
|
|
1484
|
+
| Reusable Blade Components | `{KNOWLEDGE_BASE}/migration-prompts/blade-props-migration.md` | `{KNOWLEDGE_BASE}/patterns/child-blade-flow.md` |
|
|
1485
|
+
| Notification | `{KNOWLEDGE_BASE}/migration-prompts/notifications-migration.md` | `{KNOWLEDGE_BASE}/patterns/signalr-notifications.md` |
|
|
1486
|
+
|
|
1487
|
+
Build the `topics` array for the migration-agent, including only topics that appear in the report.
|
|
1488
|
+
|
|
1489
|
+
### Step 5: Dispatch migration-agent
|
|
1490
|
+
|
|
1491
|
+
If there are topics to process, dispatch the migration-agent subagent:
|
|
1492
|
+
|
|
1493
|
+
**Agent:** `{SKILL_DIR}/agents/migration-agent.md`
|
|
1494
|
+
|
|
1495
|
+
**Input:**
|
|
1496
|
+
|
|
1497
|
+
```json
|
|
1498
|
+
{
|
|
1499
|
+
"cwd": "<project root>",
|
|
1500
|
+
"reportPath": "<path to MIGRATION_REPORT.md>",
|
|
1501
|
+
"topics": [
|
|
1502
|
+
{
|
|
1503
|
+
"name": "<topic name>",
|
|
1504
|
+
"affectedFiles": ["src/path/to/file.vue"],
|
|
1505
|
+
"migrationPromptPath": "<absolute path to migration prompt>",
|
|
1506
|
+
"patternPath": "<absolute path to pattern file or null>"
|
|
1507
|
+
}
|
|
1508
|
+
]
|
|
1509
|
+
}
|
|
1510
|
+
```
|
|
1511
|
+
|
|
1512
|
+
### Step 6: Type-check verification
|
|
1513
|
+
|
|
1514
|
+
After migration-agent completes, run:
|
|
1515
|
+
|
|
1516
|
+
```bash
|
|
1517
|
+
npx vue-tsc --noEmit
|
|
1518
|
+
```
|
|
1519
|
+
|
|
1520
|
+
If there are remaining TypeScript errors:
|
|
1521
|
+
1. Show the errors to the user
|
|
1522
|
+
2. Attempt to fix iteratively — read each error, fix the file, re-check (max 3 rounds)
|
|
1523
|
+
|
|
1524
|
+
### Step 7: Update report and summarize
|
|
1525
|
+
|
|
1526
|
+
Update `MIGRATION_REPORT.md`:
|
|
1527
|
+
- For each topic the agent successfully completed, add ✅ to the heading
|
|
1528
|
+
- Add a "Completed by AI" section listing what was done
|
|
1529
|
+
|
|
1530
|
+
Print summary to user:
|
|
1531
|
+
|
|
1532
|
+
```
|
|
1533
|
+
Migration complete!
|
|
1534
|
+
|
|
1535
|
+
Mechanical (CLI): {N} files
|
|
1536
|
+
AI-assisted: {M} files across {T} topics
|
|
1537
|
+
Remaining issues: {R} (see MIGRATION_REPORT.md)
|
|
1538
|
+
|
|
1539
|
+
Next steps:
|
|
1540
|
+
1. Review the changes: git diff
|
|
1541
|
+
2. Run: yarn build
|
|
1542
|
+
3. Test the application
|
|
1543
|
+
```
|