Skip to content

Import Tooling

The Vendor_Module:: notation is a first-class part of the MageObsidian Components workflow, not just a build-time convenience. Three pieces of tooling make it pleasant and safe to use: editor autocomplete, a live dev watcher, and a fail-loud guard.

You do not configure any of this β€” the build sets it up. This page explains what it does so the behavior is not surprising.


Editor Autocomplete (jsconfig.json)

On every build (and live in dev) the engine writes a jsconfig.json at the theme source root that teaches the editor how to resolve Vendor_Module:: specifiers. Each specifier is mapped to the real source file it resolves to, derived from the exact same inheritance map the build uses β€” so what the editor sees always matches what the build produces.

What you get in VS Code (with the Vue/Volar extension) or PhpStorm:

  • Autocomplete for Vendor_Module:: import paths.
  • Go-to-definition (Ctrl/Cmd+click) jumps straight to the actual .vue/.js file, even when the file lives in another module or a parent theme.
  • Both the full form (Vendor_Module::components/Card) and the shorthand (Vendor_Module::Card) resolve.
  • A "*" wildcard also points npm packages (vue, @heroicons/..., pinia, …) at the build harness's node_modules, so those resolve in the editor too.

Important: The generated jsconfig.json is managed by the build β€” it carries a // Generated by mage-obsidian marker on the first line, is git-ignored, and is rewritten on every build. Do not edit it. If a hand-written jsconfig.json (without the marker) already exists, the build leaves it untouched and warns you; remove it so the build can take over.

Tip: After the first build (or if resolution looks stale), run Restart TS Server in your editor so it re-reads the regenerated jsconfig.json.

Containers and mounts

When the build runs inside a container but you edit the files at a different host path (a bind-mount), the absolute paths baked into jsconfig.json would point at container paths the editor cannot open. Set MAGE_OBSIDIAN_TYPES_PATH_MAP to remap them:

# from=>to[,from2=>to2]; longest prefix wins
MAGE_OBSIDIAN_TYPES_PATH_MAP=/var/www/html/vite=>/home/me/project/component-modern-frontend/vite,/var/www/html=>/home/me/project/magento-root

When the build and the editor share a filesystem, leave it unset β€” the identity mapping is correct.


Live Dev Watcher

The inheritance map is computed once when the dev server starts and cached. Adding or removing a .vue/.js source would normally be invisible until a restart β€” both to the runtime resolver and to the editor jsconfig.json.

A dev-only watcher fixes that. When you create or delete a component or JS source under a watched directory (every opted-in module's web dir, plus the theme and its parent chain), it:

  1. Invalidates the cached inheritance map for the theme.
  2. Rewrites the persisted resolution map (so Vendor_Module:: resolves the new file at runtime).
  3. Regenerates the theme jsconfig.json (so the editor sees it too).

It logs sources changed β€” refreshed <theme> import resolution. Changes are debounced and writes are idempotent, so editing file contents (as opposed to adding/removing files) does not trigger it β€” Vite's own HMR handles that.


Fail-Loud Guard

A Vendor_Module:: specifier that does not resolve used to be silently externalized by the bundler, only to break at runtime with no clear cause. A guard now runs last in the resolver chain: if a :: specifier reaches it, none of the real resolvers could handle it β€” a typo or a missing file β€” so it throws a build/dev error instead.

The error names the unresolved specifier, the importer, and the closest valid alternatives:

1
2
3
4
5
[mage-obsidian] Unresolved import "Acme_Catalog::ProductsCard".
  imported by: .../components/Page.vue
  Did you mean:
    - Acme_Catalog::ProductCard
    - Acme_Catalog::products/Card

For an asset path, it tells you exactly where the file was expected:

1
2
3
4
[mage-obsidian] Unresolved import "Acme_Catalog::assets/logo.svg".
  imported by: .../components/Header.vue
  Asset not found. Expected a theme override at <theme>/Acme_Catalog/web/assets/logo.svg
  or the module at <module>/view/frontend/web/assets/logo.svg.

And when nothing is registered under the namespace at all, it reminds you to enable the module/theme and regenerate the contract:

  Nothing is registered under "Acme_Catalog". Is the module/theme enabled and
  compatible, and the contract regenerated (bin/magento mage-obsidian:frontend:config --generate)?

Key Notes

  • jsconfig.json is generated, git-ignored, and must not be hand-edited.
  • Use Restart TS Server after the first build to pick up autocomplete.
  • A broken :: import fails the build with suggestions β€” it never silently ships.
  • The dev watcher keeps autocomplete and runtime resolution in sync as you add/remove files, no restart needed.