@isothrum/editor 0.0.0-stage → 0.1.0
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/LICENSE +202 -0
- package/NOTICE +8 -0
- package/PUBLISHING.md +93 -0
- package/README.md +106 -2
- package/desktop-editor/editor.css +11 -0
- package/desktop-editor/index.html +14 -0
- package/desktop-editor/main.tsx +26 -0
- package/dist/desktop/editor.css +1 -0
- package/dist/desktop/editor.js +181 -0
- package/dist/desktop/fonts/geist-cyrillic-ext-wght-normal-RO72NYA2.woff2 +0 -0
- package/dist/desktop/fonts/geist-cyrillic-wght-normal-CK2XY27K.woff2 +0 -0
- package/dist/desktop/fonts/geist-latin-ext-wght-normal-XEQ56JUF.woff2 +0 -0
- package/dist/desktop/fonts/geist-latin-wght-normal-T72VVCUW.woff2 +0 -0
- package/dist/desktop/fonts/geist-mono-cyrillic-ext-wght-normal-QXKVIKFD.woff2 +0 -0
- package/dist/desktop/fonts/geist-mono-cyrillic-wght-normal-GOIAQAGU.woff2 +0 -0
- package/dist/desktop/fonts/geist-mono-latin-ext-wght-normal-HU3ZAWN6.woff2 +0 -0
- package/dist/desktop/fonts/geist-mono-latin-wght-normal-CJNQKXUG.woff2 +0 -0
- package/dist/desktop/fonts/geist-mono-symbols2-wght-normal-WZJJVLQO.woff2 +0 -0
- package/dist/desktop/fonts/geist-mono-vietnamese-wght-normal-KW5NM6YV.woff2 +0 -0
- package/dist/desktop/fonts/geist-vietnamese-wght-normal-Y2R7JZKV.woff2 +0 -0
- package/dist/desktop/fonts/shantell-sans-cyrillic-ext-wght-normal-ILPQWRJJ.woff2 +0 -0
- package/dist/desktop/fonts/shantell-sans-cyrillic-wght-normal-RKC6NDPM.woff2 +0 -0
- package/dist/desktop/fonts/shantell-sans-latin-ext-wght-normal-SNKHG3LM.woff2 +0 -0
- package/dist/desktop/fonts/shantell-sans-latin-wght-normal-7CHHGC3N.woff2 +0 -0
- package/dist/desktop/fonts/shantell-sans-vietnamese-wght-normal-IPFAQSBA.woff2 +0 -0
- package/dist/desktop/index.html +14 -0
- package/dist/desktop/styles.css +2 -0
- package/dist/desktop/wasm/isothrum_wasm.d.ts +60 -0
- package/dist/desktop/wasm/isothrum_wasm.js +312 -0
- package/dist/desktop/wasm/isothrum_wasm_bg.wasm +0 -0
- package/dist/index.js +7059 -0
- package/dist/index.js.map +7 -0
- package/dist/model.js +745 -0
- package/dist/model.js.map +7 -0
- package/dist/types/components/tool/canvas/cable-edge.d.ts +4 -0
- package/dist/types/components/tool/canvas/contexts.d.ts +12 -0
- package/dist/types/components/tool/canvas/device-icon.d.ts +17 -0
- package/dist/types/components/tool/canvas/inline-text.d.ts +15 -0
- package/dist/types/components/tool/canvas/lan-node.d.ts +8 -0
- package/dist/types/components/tool/canvas/machine-addresses.d.ts +14 -0
- package/dist/types/components/tool/canvas/machine-node.d.ts +4 -0
- package/dist/types/components/tool/canvas/note-node.d.ts +7 -0
- package/dist/types/components/tool/canvas/port-led.d.ts +10 -0
- package/dist/types/components/tool/canvas/router-node.d.ts +8 -0
- package/dist/types/components/tool/canvas/sketch.d.ts +50 -0
- package/dist/types/components/tool/canvas/status-dot.d.ts +5 -0
- package/dist/types/components/tool/canvas/switch-node.d.ts +8 -0
- package/dist/types/components/tool/canvas/use-measured-ports.d.ts +7 -0
- package/dist/types/components/tool/context-menus.d.ts +5 -0
- package/dist/types/components/tool/device-block.d.ts +12 -0
- package/dist/types/components/tool/editor-menu.d.ts +28 -0
- package/dist/types/components/tool/export/copy-button.d.ts +9 -0
- package/dist/types/components/tool/export/export-panel.d.ts +17 -0
- package/dist/types/components/tool/export/target-list.d.ts +15 -0
- package/dist/types/components/tool/floating-window.d.ts +13 -0
- package/dist/types/components/tool/flow-canvas.d.ts +6 -0
- package/dist/types/components/tool/hooks/use-cabling.d.ts +23 -0
- package/dist/types/components/tool/hooks/use-captures.d.ts +9 -0
- package/dist/types/components/tool/hooks/use-clipboard.d.ts +12 -0
- package/dist/types/components/tool/hooks/use-context-menus.d.ts +25 -0
- package/dist/types/components/tool/hooks/use-design.d.ts +10 -0
- package/dist/types/components/tool/hooks/use-desktop.d.ts +50 -0
- package/dist/types/components/tool/hooks/use-devices.d.ts +17 -0
- package/dist/types/components/tool/hooks/use-downloads.d.ts +9 -0
- package/dist/types/components/tool/hooks/use-editor.d.ts +609 -0
- package/dist/types/components/tool/hooks/use-engine.d.ts +9 -0
- package/dist/types/components/tool/hooks/use-history.d.ts +9 -0
- package/dist/types/components/tool/hooks/use-lab-actions.d.ts +25 -0
- package/dist/types/components/tool/hooks/use-lab-run.d.ts +25 -0
- package/dist/types/components/tool/hooks/use-lab.d.ts +18 -0
- package/dist/types/components/tool/hooks/use-lan-carry.d.ts +8 -0
- package/dist/types/components/tool/hooks/use-machine-actions.d.ts +26 -0
- package/dist/types/components/tool/hooks/use-placement.d.ts +27 -0
- package/dist/types/components/tool/hooks/use-project.d.ts +25 -0
- package/dist/types/components/tool/hooks/use-projects.d.ts +34 -0
- package/dist/types/components/tool/hooks/use-shared-link.d.ts +23 -0
- package/dist/types/components/tool/hooks/use-toast.d.ts +2 -0
- package/dist/types/components/tool/hooks/use-tools.d.ts +17 -0
- package/dist/types/components/tool/lab-canvas.d.ts +18 -0
- package/dist/types/components/tool/overlays.d.ts +5 -0
- package/dist/types/components/tool/projects-list.d.ts +9 -0
- package/dist/types/components/tool/text.d.ts +418 -0
- package/dist/types/components/tool/toolbar.d.ts +5 -0
- package/dist/types/components/tool/top-bars.d.ts +10 -0
- package/dist/types/components/tool/windows/conditions-fields.d.ts +6 -0
- package/dist/types/components/tool/windows/editor-windows.d.ts +5 -0
- package/dist/types/components/tool/windows/fields.d.ts +4 -0
- package/dist/types/components/tool/windows/lab-status.d.ts +6 -0
- package/dist/types/components/tool/windows/lab-windows.d.ts +13 -0
- package/dist/types/components/tool/windows/link-controls.d.ts +21 -0
- package/dist/types/components/tool/windows/machine-controls.d.ts +16 -0
- package/dist/types/components/tool/windows/machine-inspector.d.ts +11 -0
- package/dist/types/components/tool/windows/runs-fields.d.ts +18 -0
- package/dist/types/components/tool/windows/selected-windows.d.ts +21 -0
- package/dist/types/components/ui/button.d.ts +8 -0
- package/dist/types/components/ui/dropdown-menu.d.ts +21 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/lib/auth.d.ts +38 -0
- package/dist/types/lib/brand.d.ts +19 -0
- package/dist/types/lib/i18n.d.ts +19 -0
- package/dist/types/lib/tool/blocks.d.ts +35 -0
- package/dist/types/lib/tool/cables.d.ts +48 -0
- package/dist/types/lib/tool/clone.d.ts +12 -0
- package/dist/types/lib/tool/conditions.d.ts +31 -0
- package/dist/types/lib/tool/create.d.ts +22 -0
- package/dist/types/lib/tool/desktop.d.ts +63 -0
- package/dist/types/lib/tool/draft.d.ts +20 -0
- package/dist/types/lib/tool/engine.d.ts +33 -0
- package/dist/types/lib/tool/examples.d.ts +11 -0
- package/dist/types/lib/tool/export-targets.d.ts +21 -0
- package/dist/types/lib/tool/facing.d.ts +9 -0
- package/dist/types/lib/tool/geometry.d.ts +36 -0
- package/dist/types/lib/tool/gns3-cables.d.ts +17 -0
- package/dist/types/lib/tool/gns3-import.d.ts +15 -0
- package/dist/types/lib/tool/gns3-parts.d.ts +25 -0
- package/dist/types/lib/tool/issues.d.ts +12 -0
- package/dist/types/lib/tool/layout.d.ts +52 -0
- package/dist/types/lib/tool/live.d.ts +21 -0
- package/dist/types/lib/tool/logos.d.ts +7 -0
- package/dist/types/lib/tool/model.d.ts +173 -0
- package/dist/types/lib/tool/os.d.ts +20 -0
- package/dist/types/lib/tool/pins.d.ts +5 -0
- package/dist/types/lib/tool/placement.d.ts +21 -0
- package/dist/types/lib/tool/ports.d.ts +21 -0
- package/dist/types/lib/tool/presets.d.ts +21 -0
- package/dist/types/lib/tool/projects-api.d.ts +37 -0
- package/dist/types/lib/tool/router-ports.d.ts +22 -0
- package/dist/types/lib/tool/selection.d.ts +19 -0
- package/dist/types/lib/tool/storage.d.ts +25 -0
- package/dist/types/lib/tool/switch-edit.d.ts +17 -0
- package/dist/types/lib/tool/text/de.d.ts +2 -0
- package/dist/types/lib/tool/text/en.d.ts +429 -0
- package/dist/types/lib/tool/text/es.d.ts +2 -0
- package/dist/types/lib/tool/text/fr.d.ts +2 -0
- package/dist/types/lib/tool/text/index.d.ts +419 -0
- package/dist/types/lib/tool/topology.d.ts +2 -0
- package/dist/types/lib/tool/vlans.d.ts +24 -0
- package/dist/types/lib/utils.d.ts +2 -0
- package/dist/types/model.d.ts +13 -0
- package/package.json +88 -4
- package/scripts/build-desktop-editor.mjs +43 -0
- package/scripts/build-lib.mjs +38 -0
- package/src/components/tool/canvas/cable-edge.tsx +112 -0
- package/src/components/tool/canvas/contexts.ts +18 -0
- package/src/components/tool/canvas/device-icon.tsx +105 -0
- package/src/components/tool/canvas/inline-text.tsx +69 -0
- package/src/components/tool/canvas/lan-node.tsx +148 -0
- package/src/components/tool/canvas/machine-addresses.tsx +117 -0
- package/src/components/tool/canvas/machine-node.tsx +114 -0
- package/src/components/tool/canvas/note-node.tsx +109 -0
- package/src/components/tool/canvas/port-led.tsx +21 -0
- package/src/components/tool/canvas/router-node.tsx +114 -0
- package/src/components/tool/canvas/sketch.tsx +130 -0
- package/src/components/tool/canvas/status-dot.tsx +29 -0
- package/src/components/tool/canvas/switch-node.tsx +143 -0
- package/src/components/tool/canvas/use-measured-ports.ts +25 -0
- package/src/components/tool/context-menus.tsx +142 -0
- package/src/components/tool/device-block.tsx +107 -0
- package/src/components/tool/editor-menu.tsx +191 -0
- package/src/components/tool/export/copy-button.tsx +45 -0
- package/src/components/tool/export/export-panel.tsx +127 -0
- package/src/components/tool/export/target-list.tsx +87 -0
- package/src/components/tool/floating-window.tsx +69 -0
- package/src/components/tool/flow-canvas.tsx +138 -0
- package/src/components/tool/hooks/use-cabling.ts +66 -0
- package/src/components/tool/hooks/use-captures.ts +24 -0
- package/src/components/tool/hooks/use-clipboard.ts +54 -0
- package/src/components/tool/hooks/use-context-menus.ts +37 -0
- package/src/components/tool/hooks/use-design.ts +24 -0
- package/src/components/tool/hooks/use-desktop.ts +100 -0
- package/src/components/tool/hooks/use-devices.ts +58 -0
- package/src/components/tool/hooks/use-downloads.ts +42 -0
- package/src/components/tool/hooks/use-editor.ts +114 -0
- package/src/components/tool/hooks/use-engine.ts +29 -0
- package/src/components/tool/hooks/use-history.ts +107 -0
- package/src/components/tool/hooks/use-lab-actions.ts +57 -0
- package/src/components/tool/hooks/use-lab-run.ts +61 -0
- package/src/components/tool/hooks/use-lab.ts +32 -0
- package/src/components/tool/hooks/use-lan-carry.ts +43 -0
- package/src/components/tool/hooks/use-machine-actions.ts +57 -0
- package/src/components/tool/hooks/use-placement.ts +80 -0
- package/src/components/tool/hooks/use-project.ts +112 -0
- package/src/components/tool/hooks/use-projects.ts +85 -0
- package/src/components/tool/hooks/use-shared-link.ts +64 -0
- package/src/components/tool/hooks/use-toast.ts +16 -0
- package/src/components/tool/hooks/use-tools.ts +60 -0
- package/src/components/tool/lab-canvas.tsx +96 -0
- package/src/components/tool/overlays.tsx +104 -0
- package/src/components/tool/projects-list.tsx +96 -0
- package/src/components/tool/text.ts +9 -0
- package/src/components/tool/toolbar.tsx +106 -0
- package/src/components/tool/top-bars.tsx +90 -0
- package/src/components/tool/windows/conditions-fields.tsx +43 -0
- package/src/components/tool/windows/editor-windows.tsx +73 -0
- package/src/components/tool/windows/fields.ts +6 -0
- package/src/components/tool/windows/lab-status.tsx +68 -0
- package/src/components/tool/windows/lab-windows.tsx +130 -0
- package/src/components/tool/windows/link-controls.tsx +69 -0
- package/src/components/tool/windows/machine-controls.tsx +116 -0
- package/src/components/tool/windows/machine-inspector.tsx +83 -0
- package/src/components/tool/windows/runs-fields.tsx +127 -0
- package/src/components/tool/windows/selected-windows.tsx +147 -0
- package/src/components/ui/button.tsx +59 -0
- package/src/components/ui/dropdown-menu.tsx +185 -0
- package/src/index.ts +21 -0
- package/src/lib/auth.tsx +43 -0
- package/src/lib/brand.tsx +46 -0
- package/src/lib/i18n.ts +53 -0
- package/src/lib/tool/blocks.test.ts +64 -0
- package/src/lib/tool/blocks.ts +78 -0
- package/src/lib/tool/cable-wiring.test.ts +74 -0
- package/src/lib/tool/cables.test.ts +75 -0
- package/src/lib/tool/cables.ts +215 -0
- package/src/lib/tool/clone.test.ts +54 -0
- package/src/lib/tool/clone.ts +48 -0
- package/src/lib/tool/conditions.test.ts +170 -0
- package/src/lib/tool/conditions.ts +132 -0
- package/src/lib/tool/create.test.ts +67 -0
- package/src/lib/tool/create.ts +83 -0
- package/src/lib/tool/desktop.test.ts +59 -0
- package/src/lib/tool/desktop.ts +99 -0
- package/src/lib/tool/draft.test.ts +150 -0
- package/src/lib/tool/draft.ts +109 -0
- package/src/lib/tool/engine.test.ts +39 -0
- package/src/lib/tool/engine.ts +58 -0
- package/src/lib/tool/examples.test.ts +35 -0
- package/src/lib/tool/examples.ts +71 -0
- package/src/lib/tool/export-targets.test.ts +47 -0
- package/src/lib/tool/export-targets.ts +84 -0
- package/src/lib/tool/facing.test.ts +72 -0
- package/src/lib/tool/facing.ts +100 -0
- package/src/lib/tool/geometry.test.ts +80 -0
- package/src/lib/tool/geometry.ts +109 -0
- package/src/lib/tool/gns3-cables.test.ts +47 -0
- package/src/lib/tool/gns3-cables.ts +81 -0
- package/src/lib/tool/gns3-import.test.ts +102 -0
- package/src/lib/tool/gns3-import.ts +198 -0
- package/src/lib/tool/gns3-layout.test.ts +62 -0
- package/src/lib/tool/gns3-parts.test.ts +47 -0
- package/src/lib/tool/gns3-parts.ts +68 -0
- package/src/lib/tool/issues.test.ts +35 -0
- package/src/lib/tool/issues.ts +60 -0
- package/src/lib/tool/layout.test.ts +128 -0
- package/src/lib/tool/layout.ts +229 -0
- package/src/lib/tool/live.test.ts +46 -0
- package/src/lib/tool/live.ts +49 -0
- package/src/lib/tool/logos.test.ts +30 -0
- package/src/lib/tool/logos.ts +99 -0
- package/src/lib/tool/model.test.ts +128 -0
- package/src/lib/tool/model.ts +238 -0
- package/src/lib/tool/os.test.ts +45 -0
- package/src/lib/tool/os.ts +57 -0
- package/src/lib/tool/parity.test.ts +145 -0
- package/src/lib/tool/pins.test.ts +24 -0
- package/src/lib/tool/pins.ts +11 -0
- package/src/lib/tool/placement.test.ts +79 -0
- package/src/lib/tool/placement.ts +60 -0
- package/src/lib/tool/ports.test.ts +39 -0
- package/src/lib/tool/ports.ts +48 -0
- package/src/lib/tool/presets.test.ts +50 -0
- package/src/lib/tool/presets.ts +77 -0
- package/src/lib/tool/projects-api.test.ts +59 -0
- package/src/lib/tool/projects-api.ts +47 -0
- package/src/lib/tool/router-ports.test.ts +63 -0
- package/src/lib/tool/router-ports.ts +88 -0
- package/src/lib/tool/selection.test.ts +44 -0
- package/src/lib/tool/selection.ts +34 -0
- package/src/lib/tool/storage.test.ts +123 -0
- package/src/lib/tool/storage.ts +127 -0
- package/src/lib/tool/switch-edit.test.ts +49 -0
- package/src/lib/tool/switch-edit.ts +38 -0
- package/src/lib/tool/text/de.ts +358 -0
- package/src/lib/tool/text/en.ts +371 -0
- package/src/lib/tool/text/es.ts +358 -0
- package/src/lib/tool/text/fr.ts +358 -0
- package/src/lib/tool/text/index.ts +21 -0
- package/src/lib/tool/text/text.test.ts +33 -0
- package/src/lib/tool/topology.test.ts +108 -0
- package/src/lib/tool/topology.ts +116 -0
- package/src/lib/tool/vlans.test.ts +64 -0
- package/src/lib/tool/vlans.ts +79 -0
- package/src/lib/utils.ts +6 -0
- package/src/model.ts +13 -0
- package/src/test/arbitrary.ts +41 -0
- package/src/test/engine.ts +48 -0
- package/src/test/lab.ts +101 -0
- package/styles/globals.css +258 -0
- package/styles/theme.css +192 -0
- package/tsconfig.build.json +12 -0
- package/tsconfig.json +22 -0
- package/wasm/isothrum_wasm.d.ts +60 -0
- package/wasm/isothrum_wasm.js +312 -0
- package/wasm/isothrum_wasm_bg.wasm +0 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type LabLive, type SuspendedLink } from "../../../lib/tool/desktop.js";
|
|
2
|
+
/** Desktop only: the running lab now, machine by machine, with each one's ports. */
|
|
3
|
+
export declare function LabStatus({ live, cut }: {
|
|
4
|
+
live: LabLive;
|
|
5
|
+
cut: SuspendedLink[];
|
|
6
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { EditorModel } from "../hooks/use-editor";
|
|
2
|
+
/** Several things selected: what they are, and deleting them all. */
|
|
3
|
+
export declare function SelectionWindow({ e }: {
|
|
4
|
+
e: EditorModel;
|
|
5
|
+
}): import("react").JSX.Element;
|
|
6
|
+
/** The lab at a glance: how many containers, VMs, LANs and cables, and what to fix. */
|
|
7
|
+
export declare function StatusWindow({ e }: {
|
|
8
|
+
e: EditorModel;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
/** Desktop app: the lab running on this machine, its log, and starting it with the app. */
|
|
11
|
+
export declare function RunWindow({ e }: {
|
|
12
|
+
e: EditorModel;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Desktop only: capture a LAN's or a cable's traffic while the lab runs. */
|
|
2
|
+
export declare function CaptureControl({ network, running, file, capturing, onStart, onStop }: {
|
|
3
|
+
network: string;
|
|
4
|
+
running: boolean;
|
|
5
|
+
file: string | null | undefined;
|
|
6
|
+
capturing: boolean;
|
|
7
|
+
onStart: () => void;
|
|
8
|
+
onStop: () => void;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
/**
|
|
11
|
+
* Desktop only: suspend a link while the lab runs, as GNS3 does: a cable's ends (their ports,
|
|
12
|
+
* down) or, with `all`, every link of a LAN. `suspended` says so when it is.
|
|
13
|
+
*/
|
|
14
|
+
export declare function LinkControl({ running, busy, all, suspended, onSuspend, onResume }: {
|
|
15
|
+
running: boolean;
|
|
16
|
+
busy: boolean;
|
|
17
|
+
all?: boolean;
|
|
18
|
+
suspended: string | null;
|
|
19
|
+
onSuspend: () => void;
|
|
20
|
+
onResume: () => void;
|
|
21
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Snapshot } from "../../../lib/tool/desktop.js";
|
|
2
|
+
import type { MachineAction } from "../hooks/use-machine-actions";
|
|
3
|
+
interface Props {
|
|
4
|
+
state: string | undefined;
|
|
5
|
+
busy: boolean;
|
|
6
|
+
onConsole: () => void;
|
|
7
|
+
onDisplay: () => void;
|
|
8
|
+
onAction: (action: MachineAction) => void;
|
|
9
|
+
snapshots: Snapshot[];
|
|
10
|
+
onSnapshot: (label: string) => void;
|
|
11
|
+
onUse: (id: string | null) => void;
|
|
12
|
+
onDeleteSnapshot: (id: string) => void;
|
|
13
|
+
}
|
|
14
|
+
/** In the desktop app, for a machine of the running lab: its state, its controls, its snapshots. */
|
|
15
|
+
export declare function MachineControls(p: Props): import("react").JSX.Element;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type MachineData, type MachineNode } from "../../../lib/tool/model.js";
|
|
2
|
+
type Change = (patch: Partial<MachineData>) => void;
|
|
3
|
+
/** A machine's window: its name and kind, what it runs, its services, its cables. */
|
|
4
|
+
export declare function MachineInspector({ node, cables, onChange, onDelete, onSaveDevice }: {
|
|
5
|
+
node: MachineNode;
|
|
6
|
+
cables: string[];
|
|
7
|
+
onChange: Change;
|
|
8
|
+
onDelete: () => void;
|
|
9
|
+
onSaveDevice: () => void;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type MachineData } from "../../../lib/tool/model.js";
|
|
2
|
+
type Change = (patch: Partial<MachineData>) => void;
|
|
3
|
+
/** A container: its image (none to type for Dynamips), and a Cisco OS's fields or whether it idles. */
|
|
4
|
+
export declare function ContainerFields({ m, onChange }: {
|
|
5
|
+
m: MachineData;
|
|
6
|
+
onChange: Change;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
/** A VM: its OS and its provisioning steps. */
|
|
9
|
+
export declare function VmFields({ m, onChange }: {
|
|
10
|
+
m: MachineData;
|
|
11
|
+
onChange: Change;
|
|
12
|
+
}): import("react").JSX.Element;
|
|
13
|
+
/** A machine's services and whether the user lands on it (not an automatic router, nor an appliance). */
|
|
14
|
+
export declare function ServiceFields({ m, onChange }: {
|
|
15
|
+
m: MachineData;
|
|
16
|
+
onChange: Change;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type CableEdge, type LanNode, type MachineNode } from "../../../lib/tool/model.js";
|
|
2
|
+
import type { EditorModel } from "../hooks/use-editor";
|
|
3
|
+
/** A machine's window: the inspector, and (desktop app, lab running) its controls. */
|
|
4
|
+
export declare function MachineWindow({ e, node }: {
|
|
5
|
+
e: EditorModel;
|
|
6
|
+
node: MachineNode;
|
|
7
|
+
}): import("react").JSX.Element;
|
|
8
|
+
/**
|
|
9
|
+
* A LAN's window: how it behaves (its name and block are edited on the canvas itself), and in the
|
|
10
|
+
* desktop app capturing its traffic and suspending its links.
|
|
11
|
+
*/
|
|
12
|
+
export declare function LanWindow({ e, lan }: {
|
|
13
|
+
e: EditorModel;
|
|
14
|
+
lan: LanNode;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
16
|
+
/** A cable's window: the port at each end, how it behaves, and removing it. */
|
|
17
|
+
export declare function CableWindow({ e, edge, data }: {
|
|
18
|
+
e: EditorModel;
|
|
19
|
+
edge: CableEdge;
|
|
20
|
+
data: NonNullable<CableEdge["data"]>;
|
|
21
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
2
|
+
import { type VariantProps } from "class-variance-authority";
|
|
3
|
+
declare const buttonVariants: (props?: ({
|
|
4
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
5
|
+
size?: "icon" | "default" | "sm" | "xs" | "lg" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
declare function Button({ className, variant, size, ...props }: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>): import("react").JSX.Element;
|
|
8
|
+
export { Button, buttonVariants };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Menu as MenuPrimitive } from "@base-ui/react/menu";
|
|
3
|
+
declare function DropdownMenu({ ...props }: MenuPrimitive.Root.Props): React.JSX.Element;
|
|
4
|
+
declare function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props): React.JSX.Element;
|
|
5
|
+
declare function DropdownMenuContent({ align, alignOffset, side, sideOffset, className, ...props }: MenuPrimitive.Popup.Props & Pick<MenuPrimitive.Positioner.Props, "align" | "alignOffset" | "side" | "sideOffset">): React.JSX.Element;
|
|
6
|
+
declare function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props): React.JSX.Element;
|
|
7
|
+
declare function DropdownMenuLabel({ className, inset, ...props }: MenuPrimitive.GroupLabel.Props & {
|
|
8
|
+
inset?: boolean;
|
|
9
|
+
}): React.JSX.Element;
|
|
10
|
+
declare function DropdownMenuItem({ className, inset, variant, ...props }: MenuPrimitive.Item.Props & {
|
|
11
|
+
inset?: boolean;
|
|
12
|
+
variant?: "default" | "destructive";
|
|
13
|
+
}): React.JSX.Element;
|
|
14
|
+
declare function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props): React.JSX.Element;
|
|
15
|
+
declare function DropdownMenuSubTrigger({ className, inset, children, ...props }: MenuPrimitive.SubmenuTrigger.Props & {
|
|
16
|
+
inset?: boolean;
|
|
17
|
+
}): React.JSX.Element;
|
|
18
|
+
declare function DropdownMenuSubContent({ align, alignOffset, side, sideOffset, className, ...props }: React.ComponentProps<typeof DropdownMenuContent>): React.JSX.Element;
|
|
19
|
+
declare function DropdownMenuSeparator({ className, ...props }: MenuPrimitive.Separator.Props): React.JSX.Element;
|
|
20
|
+
declare function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<"span">): React.JSX.Element;
|
|
21
|
+
export { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuGroup, DropdownMenuLabel, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent, };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Isothrum lab editor as a reusable React component, plus the ports a host wires in (accounts,
|
|
3
|
+
* the product mark). The pure lab-model logic (no React) lives in the `./model` entry.
|
|
4
|
+
*/
|
|
5
|
+
export { LabCanvas, type LabCanvasProps } from "./components/tool/lab-canvas.js";
|
|
6
|
+
export { AuthClientProvider, useAuthClient, type AuthClient, type AuthSession, type AuthSessionUser, } from "./lib/auth.js";
|
|
7
|
+
export { BrandMarkProvider, DefaultBrandMark, useBrandMark, type BrandMark, type BrandMarkProps, } from "./lib/brand.js";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* The accounts surface the editor uses, injected by the host (the website wires Better Auth; the
|
|
4
|
+
* desktop app and the standalone editor leave it out and run with `accounts={false}`). Keeping it
|
|
5
|
+
* an injected port is what lets this package stay free of any auth implementation.
|
|
6
|
+
*/
|
|
7
|
+
export interface AuthSessionUser {
|
|
8
|
+
name?: string | null;
|
|
9
|
+
email: string;
|
|
10
|
+
}
|
|
11
|
+
export interface AuthSession {
|
|
12
|
+
user: AuthSessionUser;
|
|
13
|
+
}
|
|
14
|
+
export interface AuthClient {
|
|
15
|
+
/** React hook: the current session (or `null`), and whether it is still loading. */
|
|
16
|
+
useSession: () => {
|
|
17
|
+
data: AuthSession | null;
|
|
18
|
+
isPending: boolean;
|
|
19
|
+
};
|
|
20
|
+
signOut: () => Promise<unknown> | void;
|
|
21
|
+
signIn: {
|
|
22
|
+
oauth2: (options: {
|
|
23
|
+
providerId: string;
|
|
24
|
+
callbackURL: string;
|
|
25
|
+
errorCallbackURL: string;
|
|
26
|
+
}) => Promise<unknown> | void;
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
/** Provides the host's auth client to the editor. Omit it (or pass `null`) to run without accounts. */
|
|
30
|
+
export declare function AuthClientProvider({ client, children }: {
|
|
31
|
+
client: AuthClient | null;
|
|
32
|
+
children: ReactNode;
|
|
33
|
+
}): import("react").JSX.Element;
|
|
34
|
+
/**
|
|
35
|
+
* The injected auth client. It is present only where accounts are enabled; the editor reads it
|
|
36
|
+
* solely inside `accounts`-gated UI, so a missing client there is a wiring error, not a normal path.
|
|
37
|
+
*/
|
|
38
|
+
export declare function useAuthClient(): AuthClient;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* The product mark the empty canvas shows. It is a port so a host can inject its own mark while the
|
|
4
|
+
* package stays brand-neutral; the default below is the Isothrum mark (the geometry is shared with
|
|
5
|
+
* the website's favicon and OG images), themed by the host's `--primary` tokens.
|
|
6
|
+
*/
|
|
7
|
+
export interface BrandMarkProps {
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export type BrandMark = (props: BrandMarkProps) => ReactNode;
|
|
11
|
+
/** The default Isothrum mark, themed by `--primary`/`--primary-foreground`. */
|
|
12
|
+
export declare function DefaultBrandMark({ className }: BrandMarkProps): import("react").JSX.Element;
|
|
13
|
+
/** Lets a host replace the editor's product mark. Omit it to keep the default Isothrum mark. */
|
|
14
|
+
export declare function BrandMarkProvider({ mark, children }: {
|
|
15
|
+
mark: BrandMark;
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
/** The product mark in use (the injected one, or the default). */
|
|
19
|
+
export declare function useBrandMark(): BrandMark;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const LOCALES: readonly ["en", "fr", "es", "de"];
|
|
2
|
+
export declare const DEFAULT_LOCALE: "en";
|
|
3
|
+
export type Locale = (typeof LOCALES)[number];
|
|
4
|
+
/** Whether `value` names one of the site's locales. */
|
|
5
|
+
export declare function hasLocale(value: string): value is Locale;
|
|
6
|
+
/** Every locale but `locale`. */
|
|
7
|
+
export declare function otherLocales(locale: string): Locale[];
|
|
8
|
+
export declare const localeNames: Record<Locale, string>;
|
|
9
|
+
/**
|
|
10
|
+
* Replace (or insert) the locale segment in a pathname.
|
|
11
|
+
* "/en/blog/foo" + "fr" → "/fr/blog/foo"
|
|
12
|
+
* "/blog/foo" + "fr" → "/fr/blog/foo"
|
|
13
|
+
*/
|
|
14
|
+
export declare function withLocale(pathname: string, locale: Locale): string;
|
|
15
|
+
/**
|
|
16
|
+
* Build the absolute-URL hreflang map for a path that exists in every locale.
|
|
17
|
+
* Useful for static pages (homepage, /blog index, etc).
|
|
18
|
+
*/
|
|
19
|
+
export declare function hreflangFor(siteUrl: string, pathWithoutLocale: string): Record<string, string>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type Preset } from "./presets";
|
|
2
|
+
import type { EditorText } from "./text";
|
|
3
|
+
/** The toolbar's blocks: a switch, a router, a firewall, a container, a VM, and the saved devices. */
|
|
4
|
+
/** The switch tool's id in the toolbar (devices use their preset ids). */
|
|
5
|
+
export declare const SWITCH_TOOL = "switch";
|
|
6
|
+
/** The LAN tool's id in the toolbar. */
|
|
7
|
+
export declare const LAN_TOOL = "lan";
|
|
8
|
+
export declare const NOTE_TOOL = "note";
|
|
9
|
+
/** One kind a block places: a preset (a device), or the switch tool. */
|
|
10
|
+
export interface BlockOption {
|
|
11
|
+
tool: string;
|
|
12
|
+
label: string;
|
|
13
|
+
hint: string;
|
|
14
|
+
preset?: Preset;
|
|
15
|
+
key?: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface Block {
|
|
18
|
+
id: string;
|
|
19
|
+
label: string;
|
|
20
|
+
options: BlockOption[];
|
|
21
|
+
}
|
|
22
|
+
/** The blocks of the toolbar, each listing the kinds it places (the switch block starts with the switch tool). */
|
|
23
|
+
export declare function deviceBlocks(presets: Preset[], mine: Preset[], t: EditorText): Block[];
|
|
24
|
+
/** What the tool being placed is called, if any (a LAN, a switch, a note, or a device). */
|
|
25
|
+
export declare function toolLabel(tool: string | null, presets: Preset[], t: EditorText): {
|
|
26
|
+
label: string;
|
|
27
|
+
} | undefined;
|
|
28
|
+
/** Every device the toolbar can place: the built-in ones, then the saved ones. */
|
|
29
|
+
export declare const allPresets: (mine: Preset[]) => Preset[];
|
|
30
|
+
/** The line under the toolbar: what a click does now. */
|
|
31
|
+
export declare function hintFor(tool: string | null, label: string | undefined, state: {
|
|
32
|
+
hand: boolean;
|
|
33
|
+
nodes: number;
|
|
34
|
+
edges: number;
|
|
35
|
+
}, t: EditorText): string;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Connection } from "@xyflow/react";
|
|
2
|
+
import { type CableEdge, type LabNode, type LanNode } from "./model";
|
|
3
|
+
/**
|
|
4
|
+
* Cables saved with the old handles (one on each side of every machine) move onto the current
|
|
5
|
+
* ones: an appliance's single port, the top or bottom of other machines. LAN handles stay.
|
|
6
|
+
*/
|
|
7
|
+
export declare function migrateEdges(edges: CableEdge[], nodes: LabNode[]): CableEdge[];
|
|
8
|
+
/**
|
|
9
|
+
* The first free `eth<n>` on a machine, from `first`: an appliance on a LAN's edge uses eth0 on
|
|
10
|
+
* that LAN, so its cables start at eth1.
|
|
11
|
+
*/
|
|
12
|
+
export declare function nextPort(nodeId: string, edges: CableEdge[], first?: number): string;
|
|
13
|
+
/**
|
|
14
|
+
* The Isoloom network a cable became (`link-<n>`): cables between two machines are numbered in
|
|
15
|
+
* the order `toTopology` lists them. A cable to a LAN is that LAN.
|
|
16
|
+
*/
|
|
17
|
+
export declare function networkOfCable(edgeId: string, nodes: LabNode[], edges: CableEdge[]): string | null;
|
|
18
|
+
/** The names of a cable's ends that are machines (a LAN or a switch has no port to cut). */
|
|
19
|
+
export declare function machineEnds(edge: CableEdge, nodes: LabNode[]): string[];
|
|
20
|
+
/** What a cable's ends can plug into, by node id. */
|
|
21
|
+
export interface LabIndex {
|
|
22
|
+
lanIds: Set<string>;
|
|
23
|
+
switchIds: Set<string>;
|
|
24
|
+
routerIds: Set<string>;
|
|
25
|
+
}
|
|
26
|
+
/** A cable's two ends, as React Flow gives them (a connection being drawn, or a cable). */
|
|
27
|
+
interface Ends {
|
|
28
|
+
source: string;
|
|
29
|
+
target: string;
|
|
30
|
+
sourceHandle?: string | null;
|
|
31
|
+
targetHandle?: string | null;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Machine to machine, LAN or port. Never LAN to LAN or switch to LAN, and a switch or router
|
|
35
|
+
* port takes one cable, as on real gear. `ignore`: the cable being moved, whose ends don't count.
|
|
36
|
+
*/
|
|
37
|
+
export declare function canConnect(c: Ends, index: LabIndex, edges: CableEdge[], ignore?: string): boolean;
|
|
38
|
+
/** An appliance on a LAN's edge already uses eth0 there. */
|
|
39
|
+
export declare function onLanEdge(id: string, nodes: LabNode[], lans: LanNode[]): boolean;
|
|
40
|
+
/** A new cable for a connection, its ends labelled (`first(node)`: the first port to give). */
|
|
41
|
+
export declare function newCable(c: Connection, index: LabIndex, edges: CableEdge[], first: (node: string) => number): CableEdge;
|
|
42
|
+
/**
|
|
43
|
+
* The cables after `old` moved to `c`. A moved end gets the label of where it lands: the switch
|
|
44
|
+
* port, nothing on a LAN, or the machine's next free port. An end that stays put keeps its label
|
|
45
|
+
* (same machine: same port; where on its box the cable attaches is only drawing).
|
|
46
|
+
*/
|
|
47
|
+
export declare function reconnected(edges: CableEdge[], old: CableEdge, c: Connection, index: LabIndex, first: (node: string) => number): CableEdge[];
|
|
48
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { XYPosition } from "@xyflow/react";
|
|
2
|
+
import { type CableEdge, type LabNode } from "./model";
|
|
3
|
+
/**
|
|
4
|
+
* Copies of `picked` (and of the cables between them) ready to add to `existing`: new ids,
|
|
5
|
+
* moved by `offset`, fresh names (web1 -> web3), a LAN with its own free block, no fixed
|
|
6
|
+
* addresses (they would collide with the originals). VLANs keep their numbers: they are
|
|
7
|
+
* lab-wide.
|
|
8
|
+
*/
|
|
9
|
+
export declare function cloneLab(picked: LabNode[], edges: CableEdge[], existing: LabNode[], offset: XYPosition): {
|
|
10
|
+
nodes: LabNode[];
|
|
11
|
+
edges: CableEdge[];
|
|
12
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { LinkConditions } from "./model";
|
|
2
|
+
/** Isoloom's `tc` for a slow or lossy link, as the engine's topology takes it. */
|
|
3
|
+
export interface Tc {
|
|
4
|
+
delay?: string;
|
|
5
|
+
jitter?: string;
|
|
6
|
+
loss?: number;
|
|
7
|
+
rate?: string;
|
|
8
|
+
}
|
|
9
|
+
/** The conditions as Isoloom's `tc` takes them, or `undefined` when none is set. */
|
|
10
|
+
export declare function tcOf(c: LinkConditions | undefined): Tc | undefined;
|
|
11
|
+
/** A short summary for the canvas: `40 ms ±5 · 0.5% · 10 Mbit/s`. */
|
|
12
|
+
export declare function conditionsLabel(c: LinkConditions | undefined): string;
|
|
13
|
+
/** The `tc` fields written as a number and a unit: two times and a rate. */
|
|
14
|
+
type MeasuredField = "delay" | "jitter" | "rate";
|
|
15
|
+
/** A `tc` value the editor can't read: left out of the drawing and reported, never guessed. */
|
|
16
|
+
export interface TcProblem {
|
|
17
|
+
field: MeasuredField;
|
|
18
|
+
value: string;
|
|
19
|
+
}
|
|
20
|
+
/** A `tc` read back: the editor's numbers (none when nothing is set), and each value it couldn't read. */
|
|
21
|
+
export interface ReadConditions {
|
|
22
|
+
conditions: LinkConditions | undefined;
|
|
23
|
+
problems: TcProblem[];
|
|
24
|
+
}
|
|
25
|
+
/** Isoloom's `tc` back to the editor's numbers: the inverse of `tcOf`, every value it can't read reported. */
|
|
26
|
+
export declare function conditionsOf(tc: Tc | undefined): ReadConditions;
|
|
27
|
+
/** A problem in words, for the `tc` at path `at` in the topology: where, the value, the form it takes. */
|
|
28
|
+
export declare function tcProblemText(at: string, p: TcProblem): string;
|
|
29
|
+
/** The conditions a field edit leaves: a positive number, or the field cleared (none when all are). */
|
|
30
|
+
export declare function withCondition(value: LinkConditions | undefined, key: keyof LinkConditions, raw: string): LinkConditions | undefined;
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { XYPosition } from "@xyflow/react";
|
|
2
|
+
import { type LabNode, type LanData, type LanNode, type MachineNode, type NoteNode, type SwitchNode } from "./model";
|
|
3
|
+
import type { Preset } from "./presets";
|
|
4
|
+
/** New nodes, as the toolbar places them. */
|
|
5
|
+
export declare function newNote(position: XYPosition): NoteNode;
|
|
6
|
+
/** vlan10 and vlan20: a new switch's VLANs (ports 1–4 and 5–8, both on the trunk). */
|
|
7
|
+
export declare function twoVlans(): SwitchNode["data"];
|
|
8
|
+
/** A new switch with vlan10 on ports 1–4, vlan20 on ports 5–8, both on the trunk. */
|
|
9
|
+
export declare function newSwitch(center: XYPosition, nodes: LabNode[]): SwitchNode;
|
|
10
|
+
export declare function newMachine(preset: Preset, position: XYPosition, nodes: LabNode[]): MachineNode;
|
|
11
|
+
/** The third number of each LAN's 10.10.<n>.0/24 block. */
|
|
12
|
+
export declare function usedThirds(nodes: LabNode[]): Set<number>;
|
|
13
|
+
/** A new LAN centered on `center`, with the next free 10.10.<n>.0/24. */
|
|
14
|
+
export declare function newLan(center: XYPosition, nodes: LabNode[]): LanNode;
|
|
15
|
+
/**
|
|
16
|
+
* A LAN that hangs under a device placed at `center` (a router or a switch): the device sits on
|
|
17
|
+
* its top edge, toward the right, so the LAN's label (top left) stays clear and clickable.
|
|
18
|
+
*/
|
|
19
|
+
export declare function lanBelow(center: XYPosition, nodes: LabNode[], data?: Partial<LanData>, size?: {
|
|
20
|
+
w: number;
|
|
21
|
+
h: number;
|
|
22
|
+
}): LanNode;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The desktop app's commands (Isothrum desktop loads this editor in its window and exposes them
|
|
3
|
+
* on `window.__TAURI__`). In a browser there is no such object, and the desktop-only controls
|
|
4
|
+
* (Run, Stop, Capture) stay hidden.
|
|
5
|
+
*/
|
|
6
|
+
export type Invoke = <T>(command: string, args?: Record<string, unknown>) => Promise<T>;
|
|
7
|
+
export declare function desktop(): Invoke | null;
|
|
8
|
+
/**
|
|
9
|
+
* Whether the desktop app runs the lab on VMs (with Vagrant): it runs it on Docker whenever Isoloom
|
|
10
|
+
* generates its Docker files, which a machine drawn as a Linux VM has (its OS and steps build a
|
|
11
|
+
* container); only a lab with a machine that is a VM only (Windows, a playbook step) needs VMs.
|
|
12
|
+
*/
|
|
13
|
+
export declare function runsOnVms(hasVmNodes: boolean, plan: {
|
|
14
|
+
files: {
|
|
15
|
+
path: string;
|
|
16
|
+
}[];
|
|
17
|
+
} | null): boolean;
|
|
18
|
+
/** One machine now (desktop: `lab_live`): Docker's state, and its health when it has a check. */
|
|
19
|
+
export interface MachineLive {
|
|
20
|
+
state: string;
|
|
21
|
+
health: string;
|
|
22
|
+
}
|
|
23
|
+
/** One machine's port on one network now: up, down, or unknown (stopped, or a Cisco OS's). */
|
|
24
|
+
interface PortLive {
|
|
25
|
+
machine: string;
|
|
26
|
+
network: string;
|
|
27
|
+
up: boolean | null;
|
|
28
|
+
interface: string | null;
|
|
29
|
+
}
|
|
30
|
+
/** The running lab now. `probed`: the ports were read from the machines (not inferred). */
|
|
31
|
+
export interface LabLive {
|
|
32
|
+
machines: Record<string, MachineLive>;
|
|
33
|
+
ports: PortLive[];
|
|
34
|
+
probed: boolean;
|
|
35
|
+
}
|
|
36
|
+
/** A machine at a glance: up, on its way (starting, restarting), unhealthy, or down. */
|
|
37
|
+
export type Status = "up" | "starting" | "unhealthy" | "down";
|
|
38
|
+
export declare function machineStatus(m: MachineLive | undefined): Status;
|
|
39
|
+
/** A link cut while the lab runs: `machine`'s port on `network`, down. */
|
|
40
|
+
export interface SuspendedLink {
|
|
41
|
+
network: string;
|
|
42
|
+
machine: string;
|
|
43
|
+
}
|
|
44
|
+
/** A machine saved as an image (desktop: `docker commit`). */
|
|
45
|
+
export interface Snapshot {
|
|
46
|
+
id: string;
|
|
47
|
+
machine: string;
|
|
48
|
+
image: string;
|
|
49
|
+
label: string;
|
|
50
|
+
created: number;
|
|
51
|
+
in_use: boolean;
|
|
52
|
+
}
|
|
53
|
+
export interface DesktopInfo {
|
|
54
|
+
version: string;
|
|
55
|
+
docker: boolean;
|
|
56
|
+
vagrant?: boolean;
|
|
57
|
+
wireshark: boolean;
|
|
58
|
+
live_capture: boolean;
|
|
59
|
+
labs: string;
|
|
60
|
+
}
|
|
61
|
+
/** `docker compose ps --format json`: one JSON object per line. */
|
|
62
|
+
export declare function runningServices(ps: string): number;
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type CableEdge, type Design, type Draft, type LabNode } from "./model";
|
|
2
|
+
/** A lab as it is kept: in storage, in a saved project, or in a share link. */
|
|
3
|
+
/** Whether `v` is one of the canvas's looks. */
|
|
4
|
+
export declare const isDesign: (v: unknown) => v is Design;
|
|
5
|
+
/** A lab's nodes and cables as stored: the lab only, no UI state. */
|
|
6
|
+
export declare function storedNodes(nodes: LabNode[]): Pick<LabNode, "id" | "type" | "position" | "data" | "width" | "height">[];
|
|
7
|
+
export declare function storedEdges(edges: CableEdge[], data?: (e: CableEdge) => CableEdge["data"]): CableEdge[];
|
|
8
|
+
/**
|
|
9
|
+
* A draft from storage or a saved project, made current: LAN behavior, machines' OS names, today's cable handles.
|
|
10
|
+
* Null when it isn't a lab's shape (a node or a cable that isn't one, as a damaged store holds).
|
|
11
|
+
*/
|
|
12
|
+
export declare function normalizeDraft(d: unknown): Draft | null;
|
|
13
|
+
/** A draft without what is only UI state (selection, drag, measured sizes): what a save keeps. */
|
|
14
|
+
export declare function plainDraft(d: Draft): Draft;
|
|
15
|
+
/**
|
|
16
|
+
* A lab in a link: its JSON, deflated, in base64url, after `#lab=`. The part after `#` never
|
|
17
|
+
* reaches a server, so a shared lab stays as private as the editor (the link is the only copy).
|
|
18
|
+
*/
|
|
19
|
+
export declare function encodeLab(draft: Draft): Promise<string>;
|
|
20
|
+
export declare function decodeLab(code: string): Promise<Draft | null>;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Addresses } from "./router-ports";
|
|
2
|
+
/**
|
|
3
|
+
* The engine's JavaScript surface, from `public/wasm/isothrum_wasm.js` (built from
|
|
4
|
+
* `crates/isothrum-wasm`). Everything runs in the browser: nothing is sent to a server.
|
|
5
|
+
*/
|
|
6
|
+
export interface Engine {
|
|
7
|
+
default: () => Promise<unknown>;
|
|
8
|
+
plan_json: (topology: string) => string;
|
|
9
|
+
bundle: (topology: string) => Uint8Array;
|
|
10
|
+
/** The lab's own files (provisioning starters, appliance configurations), as JSON. */
|
|
11
|
+
own_files_json: (topology: string) => string;
|
|
12
|
+
bundle_target: (topology: string, targetDir: string) => Uint8Array;
|
|
13
|
+
}
|
|
14
|
+
export interface GeneratedFile {
|
|
15
|
+
path: string;
|
|
16
|
+
contents: string;
|
|
17
|
+
}
|
|
18
|
+
/** What the engine makes of a lab: isoloom.yml and every target's files, or what is wrong. */
|
|
19
|
+
export interface Plan {
|
|
20
|
+
ok: boolean;
|
|
21
|
+
error: string | null;
|
|
22
|
+
isoloom_yml: string | null;
|
|
23
|
+
problems: string[];
|
|
24
|
+
files: GeneratedFile[];
|
|
25
|
+
skipped: string[];
|
|
26
|
+
addresses: Addresses;
|
|
27
|
+
}
|
|
28
|
+
/** Loads and starts the engine. */
|
|
29
|
+
export declare function loadEngine(): Promise<Engine>;
|
|
30
|
+
/** The engine's plan for a topology; an engine crash becomes a plan with `error` (from `failed`). */
|
|
31
|
+
export declare function planOf(engine: Engine, topology: string, failed: (error: string) => string): Plan;
|
|
32
|
+
/** The lab's own files (provisioning starters, appliance configurations). */
|
|
33
|
+
export declare function ownFiles(engine: Engine, topology: string): GeneratedFile[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type Draft } from "./model";
|
|
2
|
+
/**
|
|
3
|
+
* A starting lab: an office LAN with a workstation, a servers LAN with a web server and a
|
|
4
|
+
* database, and a router cabled to both LANs.
|
|
5
|
+
*/
|
|
6
|
+
export declare function exampleLab(): Draft;
|
|
7
|
+
/**
|
|
8
|
+
* The VLAN example: a switch with vlan10 and vlan20, two PCs on vlan10, a server on vlan20, and a
|
|
9
|
+
* router on the trunk (router-on-a-stick: one address on each VLAN).
|
|
10
|
+
*/
|
|
11
|
+
export declare function vlanExample(): Draft;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { GeneratedFile } from "./engine";
|
|
2
|
+
/**
|
|
3
|
+
* The Isoloom outputs in a lab's zip, as the Export window lists them: how each is named for
|
|
4
|
+
* people, the one Isoloom command that starts it (from the unzipped folder), and the same thing
|
|
5
|
+
* with the tool itself.
|
|
6
|
+
*/
|
|
7
|
+
/** The words the names take (the editor's text). */
|
|
8
|
+
export interface TargetText {
|
|
9
|
+
containersAndVms: string;
|
|
10
|
+
oneVmPerMachine: string;
|
|
11
|
+
dockerOnOneVm: string;
|
|
12
|
+
}
|
|
13
|
+
export interface Target {
|
|
14
|
+
dir: string;
|
|
15
|
+
files: GeneratedFile[];
|
|
16
|
+
name: string;
|
|
17
|
+
isoloom: string | null;
|
|
18
|
+
run: string;
|
|
19
|
+
}
|
|
20
|
+
/** Generated files grouped by where they run: `.isoloom/<target>[/<cloud>]/…`. */
|
|
21
|
+
export declare function groupByTarget(files: GeneratedFile[], t: TargetText): Target[];
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type CableEdge, type LabNode, type LanNode, type Side } from "./model";
|
|
2
|
+
/** The sides ports face: an appliance's by its id, a switch's or router's ports by `<id>:<port>`. */
|
|
3
|
+
export declare function facingSides(nodes: LabNode[], edges: CableEdge[], lans: LanNode[]): Record<string, Side>;
|
|
4
|
+
/**
|
|
5
|
+
* The cables as drawn: each end attached where things are now (not where the cable was first
|
|
6
|
+
* drawn), and a cable on a VLAN (a switch access port, a VLAN area, a router port on it) in its
|
|
7
|
+
* color.
|
|
8
|
+
*/
|
|
9
|
+
export declare function shownCables(nodes: LabNode[], edges: CableEdge[], lans: LanNode[]): CableEdge[];
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { XYPosition } from "@xyflow/react";
|
|
2
|
+
import { type LabNode, type LanNode, type MachineNode, type Side } from "./model";
|
|
3
|
+
interface Rect {
|
|
4
|
+
x: number;
|
|
5
|
+
y: number;
|
|
6
|
+
w: number;
|
|
7
|
+
h: number;
|
|
8
|
+
}
|
|
9
|
+
/** The area a LAN covers on the canvas. */
|
|
10
|
+
export declare function lanRect(l: LanNode): Rect;
|
|
11
|
+
/** Whether `p` lies within `r`, borders included, give or take `slack`. */
|
|
12
|
+
export declare function within(r: Rect, p: XYPosition, slack?: number): boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Where an appliance at `position` should go: centered on the nearest LAN border within reach
|
|
15
|
+
* (half inside, half outside), or where it is when no border is near.
|
|
16
|
+
*/
|
|
17
|
+
export declare function snapToLanEdge(position: XYPosition, lans: LanNode[], size?: {
|
|
18
|
+
w: number;
|
|
19
|
+
h: number;
|
|
20
|
+
}): XYPosition;
|
|
21
|
+
/** The LAN border an appliance sits on, if any: the side of the LAN, so its port faces out. */
|
|
22
|
+
export declare function sideOnLan(m: MachineNode, lans: LanNode[]): Side | null;
|
|
23
|
+
/** The LAN an appliance sits on the border of, and which border: its inside and outside. */
|
|
24
|
+
export declare function lanUnder(m: MachineNode, lans: LanNode[]): {
|
|
25
|
+
lan: LanNode;
|
|
26
|
+
side: Side;
|
|
27
|
+
} | null;
|
|
28
|
+
/** Whether a point is inside a LAN's area (not on its border). */
|
|
29
|
+
export declare function insideLan(p: XYPosition, l: LanNode): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The LANs a machine sits in: its center is inside the area (or on its border). A hidden LAN's
|
|
32
|
+
* area isn't drawn, so it doesn't take machines by position, except routers and firewalls on
|
|
33
|
+
* its edge; machines join it through its switch's ports or a cable.
|
|
34
|
+
*/
|
|
35
|
+
export declare function lansAround(m: MachineNode, nodes: LabNode[]): LanNode[];
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type CableEdge, type LabNode, type LanNode, type MachineNode } from "./model";
|
|
2
|
+
/** A GNS3 project's links as cables: machine to machine, or machine to the LAN its switch became. */
|
|
3
|
+
export interface Gns3Wiring {
|
|
4
|
+
links: [string, string][];
|
|
5
|
+
/** The machines and the LANs, by GNS3 node id. */
|
|
6
|
+
machines: Map<string, MachineNode>;
|
|
7
|
+
lanOf: Map<string, LanNode>;
|
|
8
|
+
/** Every node of the lab so far (the LANs among them). */
|
|
9
|
+
nodes: LabNode[];
|
|
10
|
+
/** A GNS3 LAN's size: which side of it faces a machine goes by its proportions. */
|
|
11
|
+
lanSize: {
|
|
12
|
+
w: number;
|
|
13
|
+
h: number;
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
/** The cables of the project's links (each machine–LAN pair once); hides the LANs that would mislead. */
|
|
17
|
+
export declare function gns3Cables(w: Gns3Wiring): CableEdge[];
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opening a GNS3 project (.gns3, the JSON GNS3 saves) as a lab. GNS3 draws switches as boxes
|
|
3
|
+
* that machines plug into; here they become LANs, the machines cabled to their edge. Docker
|
|
4
|
+
* nodes keep their image, QEMU/VirtualBox/VMware nodes become VMs (the OS guessed from the
|
|
5
|
+
* image), VPCS becomes a small container, Cisco routers (Dynamips, IOU) automatic routers, a NAT
|
|
6
|
+
* or cloud gives its LAN the internet, and text drawings become notes. What can't come across
|
|
7
|
+
* (an IOS configuration, a node type with no equivalent) is reported, not silently dropped.
|
|
8
|
+
*/
|
|
9
|
+
import { type Gns3Text } from "./gns3-parts";
|
|
10
|
+
import { type Draft } from "./model";
|
|
11
|
+
/** `text`: the editor's words for what goes wrong (warnings and errors are shown as they are). */
|
|
12
|
+
export declare function fromGns3(source: string, text: Gns3Text): {
|
|
13
|
+
lab: Draft;
|
|
14
|
+
warnings: string[];
|
|
15
|
+
};
|