Skip to content

Commit 9efb386

Browse files
Merge commit 'eb632d2b37072ef7d9b8be33c7913fbacbbb82b1' into staging
2 parents 2ff99a1 + eb632d2 commit 9efb386

25 files changed

Lines changed: 849 additions & 501 deletions

.cursor/rules/fsd.mdc

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
---
2+
description: FSD migration agent. Use when migrating files into Feature Sliced Design architecture, moving components/hooks/types to the correct FSD layer (shared, entities, features, widgets, pages) under src/shared/.
3+
alwaysApply: false
4+
---
5+
# FSD Migration Command
6+
7+
You are an FSD migration agent. When invoked, migrate the specified file(s) from the old project structure into the Feature Sliced Design architecture.
8+
9+
## Project Context
10+
11+
- All FSD layers live under `src/shared/` (shared, entities, features, widgets, pages)
12+
- Use `@AppBuilderLib/` alias for imports to avoid conflicts with the nested `shared/` folder
13+
- The alias `@AppBuilderLib` resolves to `src/shared/` (configured in vite.config.ts)
14+
- Old code lives in: `components/`, `hooks/`, `store/`, `types/`, `utils/`, `modules/`, `pages/`
15+
- FSD layers already in use: `shared/`, `entities/`, `features/`, `widgets/`
16+
17+
## FSD Layers
18+
19+
| Layer | Purpose |
20+
|-------|---------|
21+
| `shared/` | Reusable code with no business logic (ui, lib, config) |
22+
| `entities/` | Business entities (data models, their UI representations) |
23+
| `features/` | User-facing features with business logic |
24+
| `widgets/` | Composite UI blocks combining multiple features/entities |
25+
| `pages/` | Full page compositions |
26+
27+
## FSD Segments (inside each slice)
28+
29+
| Segment | Contents |
30+
|---------|----------|
31+
| `ui/` | React components (`.tsx` with JSX) |
32+
| `model/` | Stores (zustand), hooks with business logic |
33+
| `api/` | API calls, SDK wrappers |
34+
| `lib/` | Pure utility functions |
35+
| `config/` | TypeScript types, constants, configuration |
36+
37+
## Workflow
38+
39+
### Step 1: Analyze the target file
40+
41+
Read the file the user wants to migrate. Understand its role (UI component, hook, store, types, utility).
42+
43+
### Step 2: Scan for related files
44+
45+
Before proposing the migration, search for closely related files that should move together:
46+
47+
1. **Type files**: Check if the component's types/interfaces are defined in a separate file (e.g., in `types/` folder). Search by component name and type names used in the file.
48+
2. **Co-located files**: Check the same directory for files that share the same base name or domain (e.g., `ComponentName.tsx` + `ComponentName.types.ts` + `useComponentName.ts`).
49+
3. **Dedicated hooks**: If the component uses a hook defined nearby, include it.
50+
4. **Barrel exports**: Check if the file is re-exported from an `index.ts` — that index may need updating.
51+
52+
### Step 3: Determine FSD destination
53+
54+
For each file (and its related files), determine:
55+
- **Layer**: shared / entities / features / widgets / pages
56+
- **Slice**: functional domain (e.g., notifications, parameters, viewport, exports)
57+
- **Segment**: ui / model / api / lib / config
58+
59+
**Analyze consumers**: Search for all files that import the target file. If the file is predominantly imported by a specific FSD slice (e.g., most consumers are in `entities/parameter/`), this is a strong signal that the file belongs in that slice. Consumer distribution should influence the destination more than the file's directory of origin.
60+
61+
Target path pattern: `src/shared/{layer}/{slice}/{segment}/{FileName}`
62+
63+
### Step 4: Present migration plan (WAIT FOR CONFIRMATION)
64+
65+
Show a concise summary in this format:
66+
67+
```
68+
Migration Plan:
69+
70+
1. ComponentName.tsx
71+
FROM: src/shared/components/shapediver/exports/ComponentName.tsx
72+
TO: src/shared/features/exports/ui/ComponentName.tsx
73+
74+
2. ComponentName.types.ts (related types)
75+
FROM: src/shared/types/components/ComponentName.ts
76+
TO: src/shared/features/exports/config/ComponentName.types.ts
77+
78+
Imports to update: ~N files
79+
80+
Confirm? (yes / no / modify)
81+
```
82+
83+
**DO NOT proceed until the user confirms.**
84+
85+
### Step 5: Execute migration (one file at a time)
86+
87+
For each file in the plan:
88+
89+
1. Create the target directory if needed (`mkdir -p`)
90+
2. **Move the file using `git mv`** inside the submodule (`src/shared`):
91+
```bash
92+
cd src/shared && git mv old/path/File.tsx new/path/File.tsx
93+
```
94+
This preserves git history and shows the move as a rename (`R`) instead of delete+add.
95+
**NEVER use `cp` + `delete`** — git won't detect the rename and will show `D` + `A`.
96+
3. Update internal imports within the moved file (use `@AppBuilderLib/` alias)
97+
4. Find ALL files that import the moved file (search the entire `src/` tree)
98+
5. Update imports in every dependent file to point to the new path
99+
6. **Create or update barrel `index.ts` files** (see Barrel Index Rules below)
100+
7. Clean up empty directories and stale barrel exports from the old location
101+
102+
After each file, briefly report:
103+
```
104+
Moved 1/2: ComponentName.tsx
105+
- Updated imports in N files
106+
- Old file removed
107+
```
108+
109+
### Step 6: Verify
110+
111+
After all files are moved, check that there are no broken imports referencing the old paths.
112+
113+
## Barrel Index Rules
114+
115+
Every FSD slice must have a public API exposed through `index.ts` files. Create them at two levels:
116+
117+
### Segment level: `{layer}/{slice}/{segment}/index.ts`
118+
Re-exports everything from files in that segment:
119+
```ts
120+
// entities/parameter/config/index.ts
121+
export * from "./propsParameter";
122+
```
123+
124+
### Slice level: `{layer}/{slice}/index.ts`
125+
Re-exports everything from all segments of the slice:
126+
```ts
127+
// entities/parameter/index.ts
128+
export * from "./config";
129+
export * from "./model";
130+
export * from "./ui";
131+
```
132+
133+
### Rules
134+
- Always create both levels when migrating into a new slice
135+
- If the segment `index.ts` already exists, **add** the new export — do not overwrite
136+
- If the slice `index.ts` already exists, **add** the new segment export if missing
137+
- After creating barrel files, also check if the old source had a barrel that re-exported the moved file — remove that stale export
138+
- Consumers should prefer importing from the slice level: `@AppBuilderLib/entities/parameter` instead of `@AppBuilderLib/entities/parameter/config/propsParameter`
139+
140+
## Import Path Rules
141+
142+
- Always use `@AppBuilderLib/` prefix for cross-slice imports
143+
- Pattern: `@AppBuilderLib/{layer}/{slice}/{segment}/{file}`
144+
- Examples:
145+
- `@AppBuilderLib/features/notifications/model/useNotificationStore`
146+
- `@AppBuilderLib/shared/ui/icon`
147+
- `@AppBuilderLib/entities/stargate/ui/StargateInput`
148+
- For intra-slice imports, use relative paths
149+
150+
## Key Rules
151+
152+
1. **Always check for related files** — types, hooks, constants that belong with the target
153+
2. **Never move without confirmation** — always show the plan first
154+
3. **Preserve original file names** — do not rename files during migration
155+
4. **Update ALL imports** — search the entire codebase for references
156+
5. **Use @AppBuilderLib alias** — never use relative paths crossing slice boundaries
157+
6. **One file at a time** — move, update imports, verify, then proceed to next

.eslintrc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"prettier"
4747
],
4848
"rules": {
49+
"@typescript-eslint/no-explicit-any": 0,
4950
"import/order": 0
5051
}
5152
}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
sentryconfig.local.ts
2525
modelstorage.local.ts
26+
viewer.local.ts
2627
modelstorage.slugs.ts
2728

2829
npm-debug.log*

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,11 @@ Install dependencies:
118118

119119
```pnpm i```
120120

121+
Install submodule:
122+
123+
```git submodule init```
124+
```git submodule update```
125+
121126
Start local development server:
122127

123128
```pnpm start```

package.json

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,18 @@
1818
"@shapediver/sdk.geometry-api-sdk-v2": "3.1.0",
1919
"@shapediver/sdk.platform-api-sdk-v1": "2.29.5",
2020
"@shapediver/sdk.stargate-sdk-v1": "1.6.2",
21-
"@shapediver/viewer.features.attribute-visualization": "3.15.12",
22-
"@shapediver/viewer.features.drawing-tools": "3.15.12",
23-
"@shapediver/viewer.features.gumball": "3.15.12",
24-
"@shapediver/viewer.features.interaction": "3.15.12",
25-
"@shapediver/viewer.session": "3.15.12",
26-
"@shapediver/viewer.shared.global-access-objects": "3.15.12",
27-
"@shapediver/viewer.shared.types": "3.15.12",
21+
"@shapediver/viewer.features.attribute-visualization": "3.16.1",
22+
"@shapediver/viewer.features.drawing-tools": "3.16.1",
23+
"@shapediver/viewer.features.interaction": "3.16.1",
24+
"@shapediver/viewer.features.transformation-tools": "3.16.1",
25+
"@shapediver/viewer.session": "3.16.1",
26+
"@shapediver/viewer.shared.global-access-objects": "3.16.1",
27+
"@shapediver/viewer.shared.types": "3.16.1",
2828
"@shapediver/viewer.utils.mime-type": "1.1.0",
29-
"@shapediver/viewer.viewport": "3.15.12",
29+
"@shapediver/viewer.viewport": "3.16.1",
30+
"@tanstack/match-sorter-utils": "8.19.4",
31+
"@tanstack/react-table": "8.21.3",
32+
"@tanstack/react-virtual": "3.13.23",
3033
"gl-matrix": "3.4.4",
3134
"immer": "10.2.0",
3235
"langfuse": "3.38.6",
@@ -52,6 +55,7 @@
5255
"optimize": "tsc && vite optimize --force",
5356
"preview": "vite preview",
5457
"eslint": "eslint .",
58+
"eslint-fix": "eslint --fix .",
5559
"prettier": "prettier --write ./src/ ./*.ts",
5660
"test": "jest",
5761
"convert-slug-data": "tsx ./scripts/convertSlugData.ts",
@@ -133,4 +137,4 @@
133137
"node"
134138
]
135139
}
136-
}
140+
}

0 commit comments

Comments
 (0)