@archie/devtools
v0.1.12
Published
DevTools for Archie generated applications - Route synchronization and editor communication
Downloads
13,445
Readme
@archie/devtools
Devtools runtime for Archie-generated applications.
Public API
This package exposes only two supported entrypoints:
@archie/devtools->archieDevTools@archie/devtools/client->ArchieDevToolProvider,ArchieDevToolProviderProps
Everything else is internal implementation detail.
Usage
1. Configure the Vite plugin
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { archieDevTools } from '@archie/devtools';
export default defineConfig({
plugins: [react(), archieDevTools()],
});2. Bootstrap the app runtime
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { ArchieDevToolProvider } from '@archie/devtools/client';
import App, { router } from './App';
createRoot(document.getElementById('root')!).render(
<StrictMode>
<ArchieDevToolProvider router={router}>
<App />
</ArchieDevToolProvider>
</StrictMode>,
);3. Export the router
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
export const router = createBrowserRouter([
// routes
]);
export default function App() {
return <RouterProvider router={router} />;
}Responsibilities
archieDevTools()handles compile-time editor metadata and internal DnD scope injection.ArchieDevToolProviderhandles runtime bootstrap: DnD provider, route sync, sanitizer install, and inspector initialization.
Requirements
- React 18+
- React Router DOM 6.4+
- Vite 5+
Deploy order
Changes to babel-plugin-editor-meta.ts's __editorMeta prop shape and
inspector.standalone.js's meta-read paths have a load-bearing publish
order — see docs/deploy-order.md.
Identidad data-vid, NodeMeta, protocolo 1.x
babelPluginEditorMeta ahora LEE data-vid (persistido en el source por el
stamper de Genesis, /^[a-z0-9]{6,8}$/) en vez de derivar la identidad de
file:line:col:componentName, que se invalida en cada escritura del source.
Cuando el elemento tiene data-vid, __editorMeta.nodeId === __editorMeta.vid
y el plugin también emite los campos de NodeMeta
(@8base-archie/editor-protocol): dynamicType, isKitOrigin, isChrome,
containerKind y, cuando aplica, lockReason. parentNodeId usa el vid
del padre cuando existe.
Sin data-vid, el plugin cae al direccionamiento legado SOLO cuando la
opción allowLegacyIds es true (default en esta versión — transicional,
se eliminará más adelante); con allowLegacyIds: false el elemento no se
instrumenta.
El plugin nunca estampa data-vid en runtime (eso lo hace el stamper de
Genesis). El plugin Vite (archieDevTools()) solo VALIDA: en dev, un
JSXOpeningElement sin data-vid dispara un warning una vez por archivo
(onMissingVid en babel-plugin-editor-meta.ts).
En runtime, node-key.ts resuelve la identidad con la prioridad
meta.vid → data-vid del DOM → (legado) meta.nodeId → runtime:N, y
fiber-bridge.ts expone getNodeMeta(el), que valida el NodeMeta
ensamblado contra NodeMetaSchema antes de devolverlo. structural-policy.ts
añade isNonDraggableNodeMeta, isNonDroppableNodeMeta y
computeDroppableSet sobre esos mismos campos.
El handshake (INSPECTOR_SCRIPT_LOADED/CAPABILITIES_RESULT) añade
editorProtocolVersion (el PROTOCOL_VERSION semver del paquete de
contrato — un campo NUEVO, nunca superpuesto al protocolVersion numérico
existente que archie-app ya compara estrictamente) y las capabilities
vidIdentity, nodeMeta, refusals. ELEMENT_SELECTED añade vid y
nodeMeta. El vocabulario REFUSED{code, cause, vid} está disponible
(refuseNode en inspector.standalone.js) para cuando un host rechaza un
gesto de arrastre/drop fuera de política.
Consume @8base-archie/editor-protocol como fuente única del contrato
(Vid, NodeMeta, LockReason, los schemas Zod) — ver
src/types/editor-meta.ts, que re-exporta esos tipos en vez de duplicarlos.
data-vid en build de producción
En vite build (command === 'build'), archieDevTools() elimina el
atributo JSX data-vid del código generado — nada en el pipeline de deploy
lo hace por su cuenta, y el atributo no aporta nada en runtime (la identidad
sigue disponible vía __editorMeta.vid, que no se toca). Solo vite dev
conserva data-vid sin cambios: este plugin corre en transform, así que
vite preview sirve el dist/ ya construido por vite build y por lo
tanto NO conserva data-vid — es el mismo build de producción, no un
comando propio de este plugin. Opt-out explícito:
archieDevTools({ stripVidsInBuild: false })Local linking
pnpm add file:../archie-devtoolsAfter changing the library:
pnpm buildDevelopment
pnpm test
pnpm typecheckTests follow a colocated-by-feature convention:
- small modules keep
*.test.ts(x)beside the source file - larger subsystems may use a local
__tests__/folder next to the feature src/client/dnd/design-mode/__tests__/is the reference pattern for multi-file feature coverage
Release notes
0.1.9
Fixes the arrange-session-changed index for a move onto a screen's own
root (0.1.8's screen-root translation) so it matches the direct
ELEMENT_MOVED event.
- Screen-root move index.
recordCommittedMove'safterpayload (the oneserializeArrangeChangereads asevent.payload.after.indexfor thearrange-session-changedchange entry) carried the raw DOM-child index (command.to.index) even when the drop resolved to a screen-root target, instead ofscreenRootTarget.index— the position remapped to count only the screen's own root children. The directelement-movedruntime event already used the remapped index; only the session-change payload lagged. In the common case (no runtime-injected chrome interleaved among a screen's root children) the two indices coincide and nothing broke; the mismatch only surfaced when chrome sat between screen-root children and the drop slot was valid but not adjacent to the chrome node.
0.1.8
Fixes two related cases where a palette drop or an in-canvas move could land somewhere the host would later discard, instead of refusing the gesture up front:
- Screen-root translation. A drop/insert that lands inside the app
shell's children-slot container (kit-internal/chrome,
containerKind: 'expression'— the element that renders{children}) between the screen's own root nodes now translates to a screen-root target instead of an ordinary container insert. The wire message (ELEMENT_INSERTED/ELEMENT_MOVED, andarrange-session-changed's per-change entries) carriesscreenRootFile(the screen's file) and anindexremapped to the position among the screen's own root children —containerVidis unchanged, still the observed DOM container. - Text/expression containers, and every other chrome/kit-internal
container. Any OTHER drop/insert into app-shell/kit chrome, or into a
non-plain (
containerKind !== 'plain') element such as a text-bearing<p>/<h3>/<span>, now refuses the gesture instead of completing — the engine falls back to the nearest enclosing PLAIN container under the pointer when one exists (e.g. the card<div>wrapping a paragraph), or refuses the gesture entirely when none does. This also fixes a gap where the external-palette-insert path (useExternalDragLoop.ts) never applied theNodeMeta-derived chrome/kit-origin/non-plain blocking at all, unlike the in-canvas move path — every palette drop onto text or app-shell chrome used to be accepted and silently discarded by the host afterward.
The screenRootFile wire field is additive: a host whose own
@8base-archie/editor-protocol copy has not yet added
DropMessage.screenRootFile simply ignores it. This package does not
construct InsertOp/MoveOp itself, and does not import any
@8base-archie/editor-protocol schema at runtime (only two plain constants,
VID_ATTR/VID_PATTERN — everything else is import type), so it carries
no dependency-version coupling to this change.
0.1.5
Treats a JSX comment ({/* ... */}) as a plain container, not an expression
one — a container whose only non-element child is a comment now gets
containerKind: 'plain' instead of 'expression'. This is coupled to
archie-code-generation (acg) PR #416: acg's own container-kind handling
must already treat {/* ... */} the same way before this version is
deployed, or containers that used to agree between the two will disagree
once 0.1.5 ships. No code-level gate enforces the pairing — deploy acg #416
first (or together with this version), not after.
