| name | fantasia-two-level-architecture |
| description | Migrates Fantasia Archive features to two-level functions + managers layout: pure scripts/functions/, *_manager.ts wiring (underscore suffix, e.g. dialogFoo_manager.ts), thin Vue SFCs. Use when refactoring features, fixing fa-two-level ESLint violations, or adding new UI. |
Two-level functions + managers
Migrate one feature
- Add
scripts/functions/ — pure logic; import type from app/types/** only; inject deps from manager
- Add
scripts/<feature>_manager.ts — wiring only; create… factories; no top-level functions/classes (fa-two-level/manager-wiring-only)
- Thin
.vue: props, child imports, one use… from manager
- Delete legacy
scripts/*.ts beside functions/
- Update
_tests; add functions/_tests
- Dev scoped gate on feature (fantasia-dev-scoped-verify); full
yarn testbatch:verify before commit
Fix common ESLint messages
| Message | Fix |
|---|
| functions/ value imports | Move to *_manager.ts, pass as arg |
| Legacy script beside functions/ | Merge into functions/ + manager or delete |
| Vue script import allowlist | Expose via manager return |
| Import functions/ only from manager | Manager (tests excepted) |
| Re-export shim | Delete; import real manager/functions |
| manager-wiring-only | Bodies in functions/ or *Wiring.ts |
| manager-wiring-only (class) | Class in non-manager sibling |
| manager-wiring-only (arrow const) | Factory arg object or *Wiring.ts |
| functions-only-type-imports | Keep orchestration in scripts/ sibling — not functions/ |
Vue imports functions/ | Use domain barrel (faDragDrop_manager, dom_manager) when present |
*Wiring.ts vs *_manager.ts
*_manager.ts — factory + export const only.
*Wiring.ts — export function + document / window / fs; examples: faInterfaceTextDirectionApplyWiring.ts, faDragDropDocumentDragCursorWiring.ts, faProjectFilePathHardeningWiring.ts.
MainLayout: attachWindowKeydownListener / detachWindowKeydownListener injected from mainLayout_manager.ts into createMainLayout.
Domain barrels (src/scripts/<domain>/)
faDragDrop_manager.ts, dom_manager.ts — public API for Vue; re-export functions/ + wiring.
Pinia stores
src/stores/S_*.ts = manager. Pure logic in src/stores/functions/. Bridge scripts may import stores/functions/.
- Return
readonly(ref) for external session state; mutate in actions only.
S_FaActiveProject: openGeneration mutex; stale open → 'superseded' (T_faActiveProjectOpenFlowOutcome).
Audit checklist (all *_manager.ts)
- Grep — no
export function, module function, class, top-level const x = () =>
yarn lint:eslint — fa-two-level/manager-wiring-only
- Factory arg property arrows OK
- Classes +
sessionDeps in *Session.ts, *Wiring.ts, *Bound.ts
- Electron Node
fs bind: factory in functions/, export const in *Wiring.ts (e.g. faProjectFilePathHardeningWiring.ts)
Shared types (types/)
Level-1 functions/**: import type from app/types/** only. Managers export values; types from app/types/.... See types-folder.mdc.
Electron
Same under src-electron/mainScripts/<area>/: functions/, <area>_manager.ts, *Wiring.ts, IPC registrars import domain *_manager.ts. Keep contentBridgeAPIs/ thin.
Related