@skyvexsoftware/stratos-sdk 0.6.0 → 0.7.4
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/README.md +7 -5
- package/dist/icons.d.ts +13 -5
- package/dist/icons.js +13 -5
- package/dist/index.js +4 -1
- package/dist/shims/react-dom-client.js +1 -1
- package/dist/shims/react-dom.js +1 -1
- package/dist/shims/react-jsx-dev-runtime.js +1 -1
- package/dist/shims/react-jsx-runtime.js +1 -1
- package/dist/shims/react.js +1 -1
- package/dist/ui/alert-dialog.js +1 -1
- package/dist/ui/card.js +3 -3
- package/dist/ui/dialog.js +2 -2
- package/dist/ui/input.js +1 -1
- package/dist/ui/label.js +1 -1
- package/dist/ui/radio-group.js +1 -1
- package/dist/ui/select.js +3 -3
- package/dist/ui/slider.js +1 -1
- package/dist/ui/tabs.js +2 -2
- package/dist/ui/textarea.js +1 -1
- package/dist/vite/externals.d.ts +7 -6
- package/dist/vite/externals.js +6 -16
- package/dist/vite/hmr-base-rewrite.js +41 -10
- package/dist/vite/plugin-config.d.ts +9 -10
- package/dist/vite/plugin-config.js +52 -109
- package/dist/vite/stratos-dev-server.js +12 -13
- package/dist/vite/stratos-externals.d.ts +11 -0
- package/dist/vite/stratos-externals.js +118 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -172,15 +172,17 @@ Available: Button, Card, Dialog, Input, Label, Select, Badge, Separator, Tabs, T
|
|
|
172
172
|
|
|
173
173
|
### Icons
|
|
174
174
|
|
|
175
|
-
|
|
175
|
+
Import icons directly from `lucide-react` — they're tree-shaken, so only the icons you use are added to your bundle:
|
|
176
176
|
|
|
177
177
|
```tsx
|
|
178
|
-
import {
|
|
179
|
-
|
|
180
|
-
const Icon = STRATOS_ICONS["Helicopter"];
|
|
178
|
+
import { Plane, Map, Settings, Helicopter } from "lucide-react";
|
|
181
179
|
```
|
|
182
180
|
|
|
183
|
-
|
|
181
|
+
The SDK's Vite config shims `react`, `react-dom`, and their jsx subpaths so every copy of React in your plugin graph (including lucide-react's internals) resolves to the shell's single instance.
|
|
182
|
+
|
|
183
|
+
If you need dynamic lookup (e.g. icons chosen by name from a remote config), `import { icons } from "lucide-react"` gives you the full map — at the cost of bundling the whole set into your plugin. Prefer a curated static map when possible.
|
|
184
|
+
|
|
185
|
+
Earlier SDK versions exposed `STRATOS_ICONS` and `STRATOS_ICON_NAMES` as convenience re-exports of lucide's `icons` object. Those exports are still available but **deprecated** — prefer the patterns above in new code.
|
|
184
186
|
|
|
185
187
|
### Types
|
|
186
188
|
|
package/dist/icons.d.ts
CHANGED
|
@@ -1,13 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Re-exports
|
|
2
|
+
* Re-exports of lucide-react's icon registry.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* @deprecated Since SDK 0.7.2. Import from `lucide-react` directly — static
|
|
5
|
+
* imports tree-shake, and the SDK's Vite config shims `react` so lucide's
|
|
6
|
+
* internals resolve to the shell's React instance (no bundle duplication,
|
|
7
|
+
* no two-React crashes). For genuinely dynamic name→component lookup, use
|
|
8
|
+
* `import { icons } from "lucide-react"` which costs ~60 KB gzipped in your
|
|
9
|
+
* plugin bundle — prefer a curated static map where you can.
|
|
6
10
|
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
11
|
+
* Retained as a thin re-export so existing plugin bundles that were built
|
|
12
|
+
* against SDK 0.6.x and earlier keep working when core upgrades the SDK.
|
|
13
|
+
* Safe to remove in a future major release once no shipped plugin references
|
|
14
|
+
* these exports.
|
|
9
15
|
*/
|
|
10
16
|
import { icons } from "lucide-react";
|
|
17
|
+
/** @deprecated Import from `lucide-react` directly. See file docstring. */
|
|
11
18
|
export declare const STRATOS_ICONS: typeof icons;
|
|
19
|
+
/** @deprecated Import from `lucide-react` directly. See file docstring. */
|
|
12
20
|
export declare const STRATOS_ICON_NAMES: string[];
|
|
13
21
|
//# sourceMappingURL=icons.d.ts.map
|
package/dist/icons.js
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Re-exports
|
|
2
|
+
* Re-exports of lucide-react's icon registry.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* @deprecated Since SDK 0.7.2. Import from `lucide-react` directly — static
|
|
5
|
+
* imports tree-shake, and the SDK's Vite config shims `react` so lucide's
|
|
6
|
+
* internals resolve to the shell's React instance (no bundle duplication,
|
|
7
|
+
* no two-React crashes). For genuinely dynamic name→component lookup, use
|
|
8
|
+
* `import { icons } from "lucide-react"` which costs ~60 KB gzipped in your
|
|
9
|
+
* plugin bundle — prefer a curated static map where you can.
|
|
6
10
|
*
|
|
7
|
-
* -
|
|
8
|
-
*
|
|
11
|
+
* Retained as a thin re-export so existing plugin bundles that were built
|
|
12
|
+
* against SDK 0.6.x and earlier keep working when core upgrades the SDK.
|
|
13
|
+
* Safe to remove in a future major release once no shipped plugin references
|
|
14
|
+
* these exports.
|
|
9
15
|
*/
|
|
10
16
|
import { icons } from "lucide-react";
|
|
17
|
+
/** @deprecated Import from `lucide-react` directly. See file docstring. */
|
|
11
18
|
export const STRATOS_ICONS = icons;
|
|
19
|
+
/** @deprecated Import from `lucide-react` directly. See file docstring. */
|
|
12
20
|
export const STRATOS_ICON_NAMES = Object.keys(icons).sort();
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,10 @@ export { useSocket, useSimulatorData, useProtocolUrl, useNotifications, useSyste
|
|
|
22
22
|
export { SOCKET_EVENTS } from "./shared-types/socket-events";
|
|
23
23
|
// ── UI Primitives ──────────────────────────────────────────────────────
|
|
24
24
|
export { AlertDialog, AlertDialogPortal, AlertDialogOverlay, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogAction, AlertDialogCancel, Badge, badgeVariants, Button, buttonVariants, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, Input, Label, RadioGroup, RadioGroupItem, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Slider, Switch, Tabs, TabsContent, TabsList, TabsTrigger, Textarea, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, } from "./ui";
|
|
25
|
-
// ── Icons
|
|
25
|
+
// ── Icons (deprecated) ────────────────────────────────────────────────
|
|
26
|
+
// Kept as a thin re-export of lucide-react's icons registry so plugin
|
|
27
|
+
// bundles built against earlier SDK versions keep working when core
|
|
28
|
+
// upgrades. New code should import from lucide-react directly.
|
|
26
29
|
export { STRATOS_ICONS, STRATOS_ICON_NAMES } from "./icons";
|
|
27
30
|
// ── Utilities ──────────────────────────────────────────────────────────
|
|
28
31
|
export { cn } from "./utils/cn";
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
const __m = globalThis.__stratos_modules__?.["react-dom/client"];
|
|
7
7
|
if (!__m)
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error('Stratos: window.__stratos_modules__["react-dom/client"] is not available. The shell must initialize it before plugin modules evaluate.');
|
|
9
9
|
export default __m.default ?? __m;
|
|
10
10
|
export const createRoot = __m.createRoot;
|
|
11
11
|
export const hydrateRoot = __m.hydrateRoot;
|
package/dist/shims/react-dom.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
const __m = globalThis.__stratos_modules__?.["react-dom"];
|
|
7
7
|
if (!__m)
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error('Stratos: window.__stratos_modules__["react-dom"] is not available. The shell must initialize it before plugin modules evaluate.');
|
|
9
9
|
export default __m.default ?? __m;
|
|
10
10
|
export const __DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = __m.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
|
11
11
|
export const createPortal = __m.createPortal;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
const __m = globalThis.__stratos_modules__?.["react/jsx-dev-runtime"];
|
|
7
7
|
if (!__m)
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error('Stratos: window.__stratos_modules__["react/jsx-dev-runtime"] is not available. The shell must initialize it before plugin modules evaluate.');
|
|
9
9
|
export default __m.default ?? __m;
|
|
10
10
|
export const Fragment = __m.Fragment;
|
|
11
11
|
export const jsxDEV = __m.jsxDEV;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
const __m = globalThis.__stratos_modules__?.["react/jsx-runtime"];
|
|
7
7
|
if (!__m)
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error('Stratos: window.__stratos_modules__["react/jsx-runtime"] is not available. The shell must initialize it before plugin modules evaluate.');
|
|
9
9
|
export default __m.default ?? __m;
|
|
10
10
|
export const Fragment = __m.Fragment;
|
|
11
11
|
export const jsx = __m.jsx;
|
package/dist/shims/react.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
6
6
|
const __m = globalThis.__stratos_modules__?.["react"];
|
|
7
7
|
if (!__m)
|
|
8
|
-
throw new Error(
|
|
8
|
+
throw new Error('Stratos: window.__stratos_modules__["react"] is not available. The shell must initialize it before plugin modules evaluate.');
|
|
9
9
|
export default __m.default ?? __m;
|
|
10
10
|
export const __CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE = __m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
|
|
11
11
|
export const __COMPILER_RUNTIME = __m.__COMPILER_RUNTIME;
|
package/dist/ui/alert-dialog.js
CHANGED
|
@@ -8,7 +8,7 @@ const AlertDialogTrigger = AlertDialogPrimitive.Trigger;
|
|
|
8
8
|
const AlertDialogPortal = AlertDialogPrimitive.Portal;
|
|
9
9
|
const AlertDialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(AlertDialogPrimitive.Overlay, { className: cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80", className), ...props, ref: ref })));
|
|
10
10
|
AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
|
|
11
|
-
const AlertDialogContent = React.forwardRef(({ className, ...props }, ref) => (_jsxs(AlertDialogPortal, { children: [_jsx(AlertDialogOverlay, {}), _jsx(AlertDialogPrimitive.Content, { ref: ref, className: cn("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed
|
|
11
|
+
const AlertDialogContent = React.forwardRef(({ className, ...props }, ref) => (_jsxs(AlertDialogPortal, { children: [_jsx(AlertDialogOverlay, {}), _jsx(AlertDialogPrimitive.Content, { ref: ref, className: cn("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg", className), ...props })] })));
|
|
12
12
|
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
|
|
13
13
|
const AlertDialogHeader = ({ className, ...props }) => (_jsx("div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props }));
|
|
14
14
|
AlertDialogHeader.displayName = "AlertDialogHeader";
|
package/dist/ui/card.js
CHANGED
|
@@ -4,10 +4,10 @@ function Card({ className, ...props }) {
|
|
|
4
4
|
return (_jsx("div", { "data-slot": "card", className: cn("bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", className), ...props }));
|
|
5
5
|
}
|
|
6
6
|
function CardHeader({ className, ...props }) {
|
|
7
|
-
return (_jsx("div", { "data-slot": "card-header", className: cn("@container/card-header
|
|
7
|
+
return (_jsx("div", { "data-slot": "card-header", className: cn("@container/card-header has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6 grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6", className), ...props }));
|
|
8
8
|
}
|
|
9
9
|
function CardTitle({ className, ...props }) {
|
|
10
|
-
return (_jsx("div", { "data-slot": "card-title", className: cn("leading-none
|
|
10
|
+
return (_jsx("div", { "data-slot": "card-title", className: cn("font-semibold leading-none", className), ...props }));
|
|
11
11
|
}
|
|
12
12
|
function CardDescription({ className, ...props }) {
|
|
13
13
|
return (_jsx("div", { "data-slot": "card-description", className: cn("text-muted-foreground text-sm", className), ...props }));
|
|
@@ -19,6 +19,6 @@ function CardContent({ className, ...props }) {
|
|
|
19
19
|
return (_jsx("div", { "data-slot": "card-content", className: cn("px-6", className), ...props }));
|
|
20
20
|
}
|
|
21
21
|
function CardFooter({ className, ...props }) {
|
|
22
|
-
return (_jsx("div", { "data-slot": "card-footer", className: cn("
|
|
22
|
+
return (_jsx("div", { "data-slot": "card-footer", className: cn("[.border-t]:pt-6 flex items-center px-6", className), ...props }));
|
|
23
23
|
}
|
|
24
24
|
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent, };
|
package/dist/ui/dialog.js
CHANGED
|
@@ -9,7 +9,7 @@ const DialogPortal = DialogPrimitive.Portal;
|
|
|
9
9
|
const DialogClose = DialogPrimitive.Close;
|
|
10
10
|
const DialogOverlay = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Overlay, { ref: ref, className: cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80", className), ...props })));
|
|
11
11
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
12
|
-
const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] bg-background fixed
|
|
12
|
+
const DialogContent = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(DialogPortal, { children: [_jsx(DialogOverlay, {}), _jsxs(DialogPrimitive.Content, { ref: ref, className: cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] bg-background fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg", className), ...props, children: [children, _jsxs(DialogPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground focus:outline-hidden absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none", children: [_jsx(X, { className: "h-4 w-4" }), _jsx("span", { className: "sr-only", children: "Close" })] })] })] })));
|
|
13
13
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
14
14
|
function DialogHeader({ className, ...props }) {
|
|
15
15
|
return (_jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props }));
|
|
@@ -17,7 +17,7 @@ function DialogHeader({ className, ...props }) {
|
|
|
17
17
|
function DialogFooter({ className, ...props }) {
|
|
18
18
|
return (_jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props }));
|
|
19
19
|
}
|
|
20
|
-
const DialogTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Title, { ref: ref, className: cn("text-lg leading-none
|
|
20
|
+
const DialogTitle = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Title, { ref: ref, className: cn("text-lg font-semibold leading-none tracking-tight", className), ...props })));
|
|
21
21
|
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
22
22
|
const DialogDescription = React.forwardRef(({ className, ...props }, ref) => (_jsx(DialogPrimitive.Description, { ref: ref, className: cn("text-muted-foreground text-sm", className), ...props })));
|
|
23
23
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
package/dist/ui/input.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../utils/cn";
|
|
3
3
|
function Input({ className, type, ...props }) {
|
|
4
|
-
return (_jsx("input", { type: type, "data-slot": "input", className: cn("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base
|
|
4
|
+
return (_jsx("input", { type: type, "data-slot": "input", className: cn("file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input shadow-xs flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base outline-none transition-[color,box-shadow] file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className), ...props }));
|
|
5
5
|
}
|
|
6
6
|
export { Input };
|
package/dist/ui/label.js
CHANGED
|
@@ -2,6 +2,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
3
3
|
import { cn } from "../utils/cn";
|
|
4
4
|
function Label({ className, ...props }) {
|
|
5
|
-
return (_jsx(LabelPrimitive.Root, { "data-slot": "label", className: cn("flex items-center gap-2 text-sm leading-none
|
|
5
|
+
return (_jsx(LabelPrimitive.Root, { "data-slot": "label", className: cn("flex select-none items-center gap-2 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50", className), ...props }));
|
|
6
6
|
}
|
|
7
7
|
export { Label };
|
package/dist/ui/radio-group.js
CHANGED
|
@@ -5,6 +5,6 @@ import { Circle } from "lucide-react";
|
|
|
5
5
|
import { cn } from "../utils/cn";
|
|
6
6
|
const RadioGroup = React.forwardRef(({ className, ...props }, ref) => (_jsx(RadioGroupPrimitive.Root, { className: cn("grid gap-2", className), ...props, ref: ref })));
|
|
7
7
|
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
8
|
-
const RadioGroupItem = React.forwardRef(({ className, ...props }, ref) => (_jsx(RadioGroupPrimitive.Item, { ref: ref, className: cn("border-primary text-primary focus-visible:ring-ring aspect-square h-4 w-4 rounded-full border shadow-sm focus
|
|
8
|
+
const RadioGroupItem = React.forwardRef(({ className, ...props }, ref) => (_jsx(RadioGroupPrimitive.Item, { ref: ref, className: cn("border-primary text-primary focus-visible:ring-ring focus:outline-hidden aspect-square h-4 w-4 rounded-full border shadow-sm focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50", className), ...props, children: _jsx(RadioGroupPrimitive.Indicator, { className: "flex items-center justify-center", children: _jsx(Circle, { className: "fill-primary h-2.5 w-2.5" }) }) })));
|
|
9
9
|
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
10
10
|
export { RadioGroup, RadioGroupItem };
|
package/dist/ui/select.js
CHANGED
|
@@ -6,7 +6,7 @@ import { cn } from "../utils/cn";
|
|
|
6
6
|
const Select = SelectPrimitive.Root;
|
|
7
7
|
const SelectGroup = SelectPrimitive.Group;
|
|
8
8
|
const SelectValue = SelectPrimitive.Value;
|
|
9
|
-
const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn("border-input bg-background ring-offset-background placeholder:text-muted-foreground focus:ring-ring flex h-10 w-full items-center justify-between rounded-md border px-3 py-2 text-sm focus:ring-2 focus:ring-offset-2
|
|
9
|
+
const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn("border-input bg-background ring-offset-background placeholder:text-muted-foreground focus:ring-ring focus:outline-hidden flex h-10 w-full items-center justify-between rounded-md border px-3 py-2 text-sm focus:ring-2 focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDown, { className: "h-4 w-4 opacity-50" }) })] })));
|
|
10
10
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
11
11
|
const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.ScrollUpButton, { ref: ref, className: cn("flex cursor-default items-center justify-center py-1", className), ...props, children: _jsx(ChevronUp, { className: "h-4 w-4" }) })));
|
|
12
12
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
@@ -17,9 +17,9 @@ const SelectContent = React.forwardRef(({ className, children, position = "poppe
|
|
|
17
17
|
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1", className), position: position, ...props, children: [_jsx(SelectScrollUpButton, {}), _jsx(SelectPrimitive.Viewport, { className: cn("p-1", position === "popper" &&
|
|
18
18
|
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"), children: children }), _jsx(SelectScrollDownButton, {})] }) })));
|
|
19
19
|
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
20
|
-
const SelectLabel = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Label, { ref: ref, className: cn("py-1.5 pr-2
|
|
20
|
+
const SelectLabel = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Label, { ref: ref, className: cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className), ...props })));
|
|
21
21
|
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
22
|
-
const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Item, { ref: ref, className: cn("focus:bg-accent focus:text-accent-foreground relative flex w-full cursor-default items-center rounded-sm py-1.5 pr-2
|
|
22
|
+
const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Item, { ref: ref, className: cn("focus:bg-accent focus:text-accent-foreground outline-hidden relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm data-[disabled]:pointer-events-none data-[disabled]:opacity-50", className), ...props, children: [_jsx("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: _jsx(SelectPrimitive.ItemIndicator, { children: _jsx(Check, { className: "h-4 w-4" }) }) }), _jsx(SelectPrimitive.ItemText, { children: children })] })));
|
|
23
23
|
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
24
24
|
const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.Separator, { ref: ref, className: cn("bg-muted -mx-1 my-1 h-px", className), ...props })));
|
|
25
25
|
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
package/dist/ui/slider.js
CHANGED
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
4
4
|
import { cn } from "../utils/cn";
|
|
5
|
-
const Slider = React.forwardRef(({ className, ...props }, ref) => (_jsxs(SliderPrimitive.Root, { ref: ref, className: cn("relative flex w-full touch-none items-center
|
|
5
|
+
const Slider = React.forwardRef(({ className, ...props }, ref) => (_jsxs(SliderPrimitive.Root, { ref: ref, className: cn("relative flex w-full touch-none select-none items-center", className), ...props, children: [_jsx(SliderPrimitive.Track, { className: "bg-primary/20 relative h-1.5 w-full grow overflow-hidden rounded-full", children: _jsx(SliderPrimitive.Range, { className: "bg-primary absolute h-full" }) }), _jsx(SliderPrimitive.Thumb, { className: "border-primary/50 bg-background focus-visible:ring-ring focus-visible:outline-hidden block h-4 w-4 rounded-full border shadow-sm transition-colors focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50" })] })));
|
|
6
6
|
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
7
7
|
export { Slider };
|
package/dist/ui/tabs.js
CHANGED
|
@@ -5,8 +5,8 @@ import { cn } from "../utils/cn";
|
|
|
5
5
|
const Tabs = TabsPrimitive.Root;
|
|
6
6
|
const TabsList = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.List, { ref: ref, className: cn("bg-muted text-muted-foreground inline-flex h-10 items-center justify-center rounded-md p-1", className), ...props })));
|
|
7
7
|
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
8
|
-
const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, className: cn("ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground inline-flex items-center justify-center rounded-sm px-3 py-1.5 text-sm font-medium
|
|
8
|
+
const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, className: cn("ring-offset-background focus-visible:ring-ring data-[state=active]:bg-background data-[state=active]:text-foreground focus-visible:outline-hidden inline-flex items-center justify-center whitespace-nowrap rounded-sm px-3 py-1.5 text-sm font-medium transition-all focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:shadow-sm", className), ...props })));
|
|
9
9
|
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
10
|
-
const TabsContent = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Content, { ref: ref, className: cn("ring-offset-background focus-visible:ring-ring mt-2 focus-visible:ring-2 focus-visible:ring-offset-2
|
|
10
|
+
const TabsContent = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Content, { ref: ref, className: cn("ring-offset-background focus-visible:ring-ring focus-visible:outline-hidden mt-2 focus-visible:ring-2 focus-visible:ring-offset-2", className), ...props })));
|
|
11
11
|
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
12
12
|
export { Tabs, TabsList, TabsTrigger, TabsContent };
|
package/dist/ui/textarea.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { cn } from "../utils/cn";
|
|
3
3
|
function Textarea({ className, ...props }) {
|
|
4
|
-
return (_jsx("textarea", { "data-slot": "textarea", className: cn("border-input bg-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 flex min-h-[60px] w-full rounded-md border px-3 py-2 text-base
|
|
4
|
+
return (_jsx("textarea", { "data-slot": "textarea", className: cn("border-input bg-background placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 shadow-xs flex min-h-[60px] w-full rounded-md border px-3 py-2 text-base outline-none transition-[color,box-shadow] focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className), ...props }));
|
|
5
5
|
}
|
|
6
6
|
export { Textarea };
|
package/dist/vite/externals.d.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Re-exports `UI_EXTERNALS` from the standalone stratos-externals module.
|
|
3
|
+
* Kept for backwards compatibility with SDK consumers importing from
|
|
4
|
+
* `./externals.js`. The canonical definition lives in `stratos-externals.ts`
|
|
5
|
+
* so that `@sdk/stratos-externals` can be imported by tests without dragging
|
|
6
|
+
* in the rest of the SDK's Vite plugin graph.
|
|
6
7
|
*/
|
|
7
|
-
export
|
|
8
|
-
export type UIExternal
|
|
8
|
+
export { UI_EXTERNALS } from "./stratos-externals.js";
|
|
9
|
+
export type { UIExternal } from "./stratos-externals.js";
|
|
9
10
|
//# sourceMappingURL=externals.d.ts.map
|
package/dist/vite/externals.js
CHANGED
|
@@ -1,18 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
2
|
+
* Re-exports `UI_EXTERNALS` from the standalone stratos-externals module.
|
|
3
|
+
* Kept for backwards compatibility with SDK consumers importing from
|
|
4
|
+
* `./externals.js`. The canonical definition lives in `stratos-externals.ts`
|
|
5
|
+
* so that `@sdk/stratos-externals` can be imported by tests without dragging
|
|
6
|
+
* in the rest of the SDK's Vite plugin graph.
|
|
6
7
|
*/
|
|
7
|
-
export
|
|
8
|
-
"react",
|
|
9
|
-
"react-dom",
|
|
10
|
-
"react/jsx-runtime",
|
|
11
|
-
"@tanstack/react-router",
|
|
12
|
-
"@tanstack/react-query",
|
|
13
|
-
"@skyvexsoftware/stratos-sdk",
|
|
14
|
-
"sonner",
|
|
15
|
-
"socket.io-client",
|
|
16
|
-
"maplibre-gl",
|
|
17
|
-
"react-map-gl/maplibre",
|
|
18
|
-
];
|
|
8
|
+
export { UI_EXTERNALS } from "./stratos-externals.js";
|
|
@@ -22,12 +22,36 @@
|
|
|
22
22
|
* /@vite/client imports added by importAnalysis (which runs after all
|
|
23
23
|
* user transforms)
|
|
24
24
|
*/
|
|
25
|
+
// Virtual module that installs the React Fast Refresh globals. Must be
|
|
26
|
+
// imported as a SIDE EFFECT at the top of the plugin's entry so ESM
|
|
27
|
+
// evaluates it before any sibling (child-component) module — whose
|
|
28
|
+
// plugin-react epilogue asserts `window.$RefreshReg$` exists.
|
|
29
|
+
const PREAMBLE_VIRTUAL_ID = "/@stratos-refresh-preamble";
|
|
30
|
+
const PREAMBLE_RESOLVED_ID = "\0stratos-refresh-preamble";
|
|
25
31
|
export function hmrBaseRewrite() {
|
|
26
32
|
let devOrigin = "";
|
|
27
33
|
return {
|
|
28
34
|
name: "stratos-hmr-base-rewrite",
|
|
29
35
|
apply: "serve",
|
|
30
36
|
enforce: "post",
|
|
37
|
+
resolveId(source) {
|
|
38
|
+
if (source === PREAMBLE_VIRTUAL_ID)
|
|
39
|
+
return PREAMBLE_RESOLVED_ID;
|
|
40
|
+
return null;
|
|
41
|
+
},
|
|
42
|
+
load(id) {
|
|
43
|
+
if (id !== PREAMBLE_RESOLVED_ID)
|
|
44
|
+
return null;
|
|
45
|
+
if (!devOrigin)
|
|
46
|
+
return null;
|
|
47
|
+
return [
|
|
48
|
+
`import RefreshRuntime from "${devOrigin}/@react-refresh";`,
|
|
49
|
+
`RefreshRuntime.injectIntoGlobalHook(window);`,
|
|
50
|
+
`window.$RefreshReg$ = () => {};`,
|
|
51
|
+
`window.$RefreshSig$ = () => (type) => type;`,
|
|
52
|
+
`window.__vite_plugin_react_preamble_installed__ = true;`,
|
|
53
|
+
].join("\n");
|
|
54
|
+
},
|
|
31
55
|
configureServer(server) {
|
|
32
56
|
server.httpServer?.once("listening", () => {
|
|
33
57
|
const addr = server.httpServer?.address();
|
|
@@ -91,16 +115,23 @@ export function hmrBaseRewrite() {
|
|
|
91
115
|
// (catches imports from @vitejs/plugin-react and CSS transforms)
|
|
92
116
|
patched = patched.replace(/(from\s+["'])(\/(?:@vite\/[^"']+|@react-refresh))(["'])/g, `$1${devOrigin}$2$3`);
|
|
93
117
|
patched = patched.replace(/(import\s*\(\s*["'])(\/(?:@vite\/[^"']+|@react-refresh))(["'])/g, `$1${devOrigin}$2$3`);
|
|
94
|
-
// 3. Inject
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
118
|
+
// 3. Inject the Fast Refresh preamble as a SIDE-EFFECT IMPORT at the
|
|
119
|
+
// top of the entry. Prepending the preamble inline doesn't work:
|
|
120
|
+
// ESM hoists all imports and evaluates them depth-first BEFORE any
|
|
121
|
+
// top-level code runs, so every child component's plugin-react
|
|
122
|
+
// epilogue (`if (!window.$RefreshReg$) throw ...`) fires before
|
|
123
|
+
// the entry's top-level preamble sets those globals. A sibling
|
|
124
|
+
// import evaluates *fully* before the next sibling begins, so
|
|
125
|
+
// putting the preamble as the FIRST import means it's installed
|
|
126
|
+
// before any component module evaluates.
|
|
127
|
+
//
|
|
128
|
+
// Strip query string first: the shell appends `?t=<timestamp>` for
|
|
129
|
+
// cache-busting, and Vite passes the id through with the query — so
|
|
130
|
+
// a raw `endsWith` check misses every shell load.
|
|
131
|
+
const idPath = id.split("?")[0];
|
|
132
|
+
if (idPath.endsWith("/src/ui/index.tsx") ||
|
|
133
|
+
idPath.endsWith("/src/ui/index.ts")) {
|
|
134
|
+
patched = `import "${devOrigin}${PREAMBLE_VIRTUAL_ID}";\n${patched}`;
|
|
104
135
|
}
|
|
105
136
|
if (patched !== code) {
|
|
106
137
|
return { code: patched, map: null };
|
|
@@ -15,19 +15,11 @@
|
|
|
15
15
|
* background: { entry: 'src/background/index.ts' },
|
|
16
16
|
* });
|
|
17
17
|
*/
|
|
18
|
-
import type {
|
|
18
|
+
import type { UserConfig } from "vite";
|
|
19
19
|
import { UI_EXTERNALS } from "./externals.js";
|
|
20
|
+
import { stratosExternals } from "./stratos-externals.js";
|
|
20
21
|
/** Modules external in background builds (available in Electron main process) */
|
|
21
22
|
declare const BG_EXTERNALS: string[];
|
|
22
|
-
/**
|
|
23
|
-
* Rollup plugin that transforms ESM import statements for externalized modules
|
|
24
|
-
* into runtime lookups from window.__stratos_modules__.
|
|
25
|
-
*
|
|
26
|
-
* This allows plugin UI bundles to remain valid ES modules that can be loaded
|
|
27
|
-
* via dynamic import() while resolving shared dependencies from the shell's
|
|
28
|
-
* global registry.
|
|
29
|
-
*/
|
|
30
|
-
declare function stratosExternals(): Plugin;
|
|
31
23
|
export type PluginBuildOptions = {
|
|
32
24
|
/** Plugin root directory. Defaults to process.cwd(). */
|
|
33
25
|
pluginDir?: string;
|
|
@@ -48,5 +40,12 @@ export type PluginBuildOptions = {
|
|
|
48
40
|
* - "background" → builds the background module (Node.js, ESM)
|
|
49
41
|
*/
|
|
50
42
|
export declare function createPluginConfig(options: PluginBuildOptions): UserConfig;
|
|
43
|
+
/**
|
|
44
|
+
* Shared background build configuration — used both for the production
|
|
45
|
+
* build (createBackgroundConfig below) and the dev hot-rebuilder in
|
|
46
|
+
* stratos-dev-server. Extracted so dev and prod can never drift on
|
|
47
|
+
* aliases, externals, or output layout.
|
|
48
|
+
*/
|
|
49
|
+
export declare function backgroundBuildOptions(pluginDir: string, entry: string): Pick<UserConfig, "root" | "resolve" | "build">;
|
|
51
50
|
export { UI_EXTERNALS, BG_EXTERNALS, stratosExternals };
|
|
52
51
|
//# sourceMappingURL=plugin-config.d.ts.map
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import * as fs from "fs";
|
|
19
19
|
import * as path from "path";
|
|
20
|
-
import MagicString from "magic-string";
|
|
21
20
|
import { UI_EXTERNALS } from "./externals.js";
|
|
21
|
+
import { stratosExternals } from "./stratos-externals.js";
|
|
22
22
|
import { serveExternals } from "./serve-externals.js";
|
|
23
23
|
import { stratosDevServer } from "./stratos-dev-server.js";
|
|
24
24
|
import { cssInject } from "./css-inject.js";
|
|
@@ -55,99 +55,6 @@ const NODE_BUILTINS = [
|
|
|
55
55
|
"worker_threads",
|
|
56
56
|
"zlib",
|
|
57
57
|
];
|
|
58
|
-
/**
|
|
59
|
-
* Rollup plugin that transforms ESM import statements for externalized modules
|
|
60
|
-
* into runtime lookups from window.__stratos_modules__.
|
|
61
|
-
*
|
|
62
|
-
* This allows plugin UI bundles to remain valid ES modules that can be loaded
|
|
63
|
-
* via dynamic import() while resolving shared dependencies from the shell's
|
|
64
|
-
* global registry.
|
|
65
|
-
*/
|
|
66
|
-
function stratosExternals() {
|
|
67
|
-
return {
|
|
68
|
-
name: "stratos-externals",
|
|
69
|
-
renderChunk(code) {
|
|
70
|
-
const s = new MagicString(code);
|
|
71
|
-
for (const modId of UI_EXTERNALS) {
|
|
72
|
-
const escaped = modId.replace(/[-/\\^$*+?.()|[\]{}@]/g, "\\$&");
|
|
73
|
-
const global = `window.__stratos_modules__[${JSON.stringify(modId)}]`;
|
|
74
|
-
const patterns = [
|
|
75
|
-
// 1. import Default, { named } from 'mod';
|
|
76
|
-
[
|
|
77
|
-
new RegExp(`import\\s+([\\w$]+)\\s*,\\s*\\{([^}]+)\\}\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
78
|
-
(_, def, names) => {
|
|
79
|
-
const destructured = names.replace(/([\w$]+)\s+as\s+([\w$]+)/g, "$1: $2");
|
|
80
|
-
return `const ${def} = ${global}.default || ${global};\nconst {${destructured}} = ${global};`;
|
|
81
|
-
},
|
|
82
|
-
],
|
|
83
|
-
// 2. import { named } from 'mod';
|
|
84
|
-
[
|
|
85
|
-
new RegExp(`import\\s*\\{([^}]+)\\}\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
86
|
-
(_, names) => {
|
|
87
|
-
const destructured = names.replace(/([\w$]+)\s+as\s+([\w$]+)/g, "$1: $2");
|
|
88
|
-
return `const {${destructured}} = ${global};`;
|
|
89
|
-
},
|
|
90
|
-
],
|
|
91
|
-
// 3. import * as ns from 'mod';
|
|
92
|
-
[
|
|
93
|
-
new RegExp(`import\\s+\\*\\s+as\\s+([\\w$]+)\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
94
|
-
(_, name) => `const ${name} = ${global};`,
|
|
95
|
-
],
|
|
96
|
-
// 4. import Default from 'mod';
|
|
97
|
-
[
|
|
98
|
-
new RegExp(`import\\s+([\\w$]+)\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
99
|
-
(_, def) => `const ${def} = ${global}.default || ${global};`,
|
|
100
|
-
],
|
|
101
|
-
// 5. import 'mod';
|
|
102
|
-
[new RegExp(`import\\s+['"]${escaped}['"]\\s*;?`, "g"), () => ""],
|
|
103
|
-
// 6. export { name } from 'mod';
|
|
104
|
-
[
|
|
105
|
-
new RegExp(`export\\s*\\{([^}]+)\\}\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
106
|
-
(_, names) => {
|
|
107
|
-
const parts = names.split(",").map((n) => n.trim());
|
|
108
|
-
const decls = [];
|
|
109
|
-
const exportNames = [];
|
|
110
|
-
for (const part of parts) {
|
|
111
|
-
const asMatch = part.match(/^([\w$]+)\s+as\s+([\w$]+)$/);
|
|
112
|
-
if (asMatch) {
|
|
113
|
-
decls.push(`const ${asMatch[2]} = ${global}[${JSON.stringify(asMatch[1])}];`);
|
|
114
|
-
exportNames.push(asMatch[2]);
|
|
115
|
-
}
|
|
116
|
-
else {
|
|
117
|
-
exportNames.push(part);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
if (decls.length > 0) {
|
|
121
|
-
return `${decls.join("\n")}\nconst {${exportNames.join(", ")}} = ${global};\nexport {${exportNames.join(", ")}};`;
|
|
122
|
-
}
|
|
123
|
-
return `const {${exportNames.join(", ")}} = ${global};\nexport {${exportNames.join(", ")}};`;
|
|
124
|
-
},
|
|
125
|
-
],
|
|
126
|
-
];
|
|
127
|
-
// Collect all matches first, then apply in reverse order to preserve offsets
|
|
128
|
-
const matches = [];
|
|
129
|
-
for (const [re, replacer] of patterns) {
|
|
130
|
-
re.lastIndex = 0;
|
|
131
|
-
let match;
|
|
132
|
-
while ((match = re.exec(code)) !== null) {
|
|
133
|
-
matches.push({
|
|
134
|
-
start: match.index,
|
|
135
|
-
end: match.index + match[0].length,
|
|
136
|
-
replacement: replacer(match[0], ...match.slice(1)),
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// Apply in reverse so earlier offsets stay valid
|
|
141
|
-
matches
|
|
142
|
-
.sort((a, b) => b.start - a.start)
|
|
143
|
-
.forEach((m) => s.overwrite(m.start, m.end, m.replacement));
|
|
144
|
-
}
|
|
145
|
-
if (!s.hasChanged())
|
|
146
|
-
return null;
|
|
147
|
-
return { code: s.toString(), map: s.generateMap({ hires: true }) };
|
|
148
|
-
},
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
58
|
/**
|
|
152
59
|
* Rollup plugin that copies plugin.json and assets/ to dist/ after the build.
|
|
153
60
|
* Only runs during the UI build (not background) to avoid duplicate copies.
|
|
@@ -204,6 +111,34 @@ export function createPluginConfig(options) {
|
|
|
204
111
|
}
|
|
205
112
|
function createUIConfig(pluginDir, entry, extraConfig) {
|
|
206
113
|
const isProduction = process.env.NODE_ENV === "production";
|
|
114
|
+
// Merge user-supplied resolve.alias with our React shims. We always use
|
|
115
|
+
// the array form because the shim aliases rely on regex matchers for
|
|
116
|
+
// exact-subpath matching (e.g. `react` vs `react/jsx-runtime`). User
|
|
117
|
+
// aliases can come in either form, so normalise object form into array
|
|
118
|
+
// entries first.
|
|
119
|
+
const userAlias = extraConfig?.resolve?.alias;
|
|
120
|
+
const userAliasArray = Array.isArray(userAlias)
|
|
121
|
+
? userAlias
|
|
122
|
+
: userAlias
|
|
123
|
+
? Object.entries(userAlias).map(([find, replacement]) => ({
|
|
124
|
+
find,
|
|
125
|
+
replacement: replacement,
|
|
126
|
+
}))
|
|
127
|
+
: [];
|
|
128
|
+
// Alias resolution order:
|
|
129
|
+
// 1. React shim aliases — must win; swapping them would break the
|
|
130
|
+
// single-React invariant.
|
|
131
|
+
// 2. User-supplied aliases — can override the default `@/` below.
|
|
132
|
+
// 3. Default `@/` → `src/` — the convention every plugin wants, so
|
|
133
|
+
// they don't have to wire it up in each vite.config.ts.
|
|
134
|
+
const mergedAlias = [
|
|
135
|
+
...reactShimAliases(),
|
|
136
|
+
...userAliasArray,
|
|
137
|
+
{ find: /^@\//, replacement: path.resolve(pluginDir, "src") + "/" },
|
|
138
|
+
];
|
|
139
|
+
// Strip resolve and plugins out of extraConfig before spreading, since we
|
|
140
|
+
// merge those explicitly below.
|
|
141
|
+
const { resolve: _omitResolve, plugins: _omitPlugins, ...restExtra } = extraConfig ?? {};
|
|
207
142
|
return {
|
|
208
143
|
root: pluginDir,
|
|
209
144
|
// Skip WebSocket token validation so /@vite/client can connect from
|
|
@@ -220,18 +155,9 @@ function createUIConfig(pluginDir, entry, extraConfig) {
|
|
|
220
155
|
host: "localhost",
|
|
221
156
|
},
|
|
222
157
|
},
|
|
223
|
-
resolve: {
|
|
224
|
-
// Redirect React (and friends) to shim modules that proxy to
|
|
225
|
-
// window.__stratos_modules__. Applies during source transforms AND
|
|
226
|
-
// esbuild pre-bundling, so any third-party dep that imports React
|
|
227
|
-
// (lucide-react, radix, etc.) resolves to the shell's single instance —
|
|
228
|
-
// avoiding the two-React "Cannot read properties of null (reading
|
|
229
|
-
// 'useContext')" crash.
|
|
230
|
-
alias: reactShimAliases(),
|
|
231
|
-
},
|
|
232
158
|
optimizeDeps: {
|
|
233
159
|
// Exclude non-React externals from pre-bundling (they come from the
|
|
234
|
-
// shell). React subpaths are handled by the alias
|
|
160
|
+
// shell). React subpaths are handled by the alias below — their imports
|
|
235
161
|
// are rewritten to shim files, which esbuild can bundle normally.
|
|
236
162
|
exclude: UI_EXTERNALS.filter((id) => !id.startsWith("react") && id !== "react-dom"),
|
|
237
163
|
},
|
|
@@ -254,8 +180,13 @@ function createUIConfig(pluginDir, entry, extraConfig) {
|
|
|
254
180
|
jsx: "automatic",
|
|
255
181
|
jsxImportSource: "react",
|
|
256
182
|
},
|
|
257
|
-
//
|
|
258
|
-
|
|
183
|
+
// Shallow-merge remaining extra config (server, optimizeDeps, build,
|
|
184
|
+
// etc.). resolve and plugins are merged explicitly below.
|
|
185
|
+
...restExtra,
|
|
186
|
+
resolve: {
|
|
187
|
+
...extraConfig?.resolve,
|
|
188
|
+
alias: mergedAlias,
|
|
189
|
+
},
|
|
259
190
|
plugins: [
|
|
260
191
|
serveExternals(),
|
|
261
192
|
hmrBaseRewrite(),
|
|
@@ -267,10 +198,20 @@ function createUIConfig(pluginDir, entry, extraConfig) {
|
|
|
267
198
|
],
|
|
268
199
|
};
|
|
269
200
|
}
|
|
270
|
-
|
|
271
|
-
|
|
201
|
+
/**
|
|
202
|
+
* Shared background build configuration — used both for the production
|
|
203
|
+
* build (createBackgroundConfig below) and the dev hot-rebuilder in
|
|
204
|
+
* stratos-dev-server. Extracted so dev and prod can never drift on
|
|
205
|
+
* aliases, externals, or output layout.
|
|
206
|
+
*/
|
|
207
|
+
export function backgroundBuildOptions(pluginDir, entry) {
|
|
272
208
|
return {
|
|
273
209
|
root: pluginDir,
|
|
210
|
+
resolve: {
|
|
211
|
+
alias: [
|
|
212
|
+
{ find: /^@\//, replacement: path.resolve(pluginDir, "src") + "/" },
|
|
213
|
+
],
|
|
214
|
+
},
|
|
274
215
|
build: {
|
|
275
216
|
outDir: path.resolve(pluginDir, "dist/background"),
|
|
276
217
|
emptyOutDir: true,
|
|
@@ -281,7 +222,6 @@ function createBackgroundConfig(pluginDir, entry) {
|
|
|
281
222
|
},
|
|
282
223
|
rollupOptions: {
|
|
283
224
|
external: (id) => {
|
|
284
|
-
// Bundle the SDK helpers subpath (createPlugin) into the output
|
|
285
225
|
if (id === "@skyvexsoftware/stratos-sdk/helpers")
|
|
286
226
|
return false;
|
|
287
227
|
if (id === "@skyvexsoftware/stratos-sdk")
|
|
@@ -298,4 +238,7 @@ function createBackgroundConfig(pluginDir, entry) {
|
|
|
298
238
|
},
|
|
299
239
|
};
|
|
300
240
|
}
|
|
241
|
+
function createBackgroundConfig(pluginDir, entry) {
|
|
242
|
+
return backgroundBuildOptions(pluginDir, entry);
|
|
243
|
+
}
|
|
301
244
|
export { UI_EXTERNALS, BG_EXTERNALS, stratosExternals };
|
|
@@ -5,6 +5,7 @@ import * as fs from "fs";
|
|
|
5
5
|
import * as path from "path";
|
|
6
6
|
import { build } from "vite";
|
|
7
7
|
import { io as ioClient } from "socket.io-client";
|
|
8
|
+
import { backgroundBuildOptions } from "./plugin-config.js";
|
|
8
9
|
/**
|
|
9
10
|
* Vite plugin that auto-connects a plugin's dev server to a running Stratos
|
|
10
11
|
* app. Only active in serve (dev) mode.
|
|
@@ -94,10 +95,17 @@ export function stratosDevServer(options) {
|
|
|
94
95
|
const devUrl = getDevUrl();
|
|
95
96
|
const distPath = path.resolve(pluginDir, "dist");
|
|
96
97
|
console.log(`[stratos-dev-server] Connected to Stratos (localhost:${stratosPort})`);
|
|
98
|
+
// Stratos's dev-plugin-server-listener only starts the background
|
|
99
|
+
// module when "background" is in this array. Advertise it whenever
|
|
100
|
+
// src/background/ exists.
|
|
101
|
+
const capabilities = ["ui", "hot-reload"];
|
|
102
|
+
if (fs.existsSync(path.resolve(pluginDir, "src/background"))) {
|
|
103
|
+
capabilities.push("background");
|
|
104
|
+
}
|
|
97
105
|
socket.emit("dev:plugin-connect", {
|
|
98
106
|
manifest,
|
|
99
107
|
devUrl,
|
|
100
|
-
capabilities
|
|
108
|
+
capabilities,
|
|
101
109
|
distPath,
|
|
102
110
|
sourceRoot: pluginDir,
|
|
103
111
|
wsToken,
|
|
@@ -125,20 +133,11 @@ export function stratosDevServer(options) {
|
|
|
125
133
|
let bgDebounce = null;
|
|
126
134
|
async function rebuildBackground() {
|
|
127
135
|
try {
|
|
136
|
+
// Reuse the same options the production build uses so dev rebuilds
|
|
137
|
+
// get the `@/` alias, electron/node externals, etc.
|
|
128
138
|
await build({
|
|
129
139
|
configFile: false,
|
|
130
|
-
|
|
131
|
-
build: {
|
|
132
|
-
lib: {
|
|
133
|
-
entry: "src/background/index.ts",
|
|
134
|
-
formats: ["es"],
|
|
135
|
-
fileName: () => "index.js",
|
|
136
|
-
},
|
|
137
|
-
outDir: path.resolve(pluginDir, "dist/background"),
|
|
138
|
-
emptyOutDir: true,
|
|
139
|
-
minify: false,
|
|
140
|
-
sourcemap: false,
|
|
141
|
-
},
|
|
140
|
+
...backgroundBuildOptions(pluginDir, "src/background/index.ts"),
|
|
142
141
|
logLevel: "warn",
|
|
143
142
|
});
|
|
144
143
|
const bundlePath = path.resolve(pluginDir, "dist/background/index.js");
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* Canonical list of modules provided by the Stratos shell at runtime via
|
|
4
|
+
* `window.__stratos_modules__`. Plugin builds mark these as Rollup externals
|
|
5
|
+
* so imports survive bundling, and `stratosExternals` rewrites them into
|
|
6
|
+
* runtime lookups against the shell's global registry at render time.
|
|
7
|
+
*/
|
|
8
|
+
export declare const UI_EXTERNALS: readonly ["react", "react-dom", "react/jsx-runtime", "@tanstack/react-router", "@tanstack/react-query", "@skyvexsoftware/stratos-sdk", "sonner", "socket.io-client", "maplibre-gl", "react-map-gl/maplibre"];
|
|
9
|
+
export type UIExternal = (typeof UI_EXTERNALS)[number];
|
|
10
|
+
export declare function stratosExternals(): Plugin;
|
|
11
|
+
//# sourceMappingURL=stratos-externals.d.ts.map
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Rollup plugin that rewrites ESM import statements for shell-provided
|
|
3
|
+
* modules into `window.__stratos_modules__` lookups at render time.
|
|
4
|
+
*
|
|
5
|
+
* Plugin builds mark shared deps (react, tanstack, the SDK, etc.) as Rollup
|
|
6
|
+
* externals so imports survive bundling; this `renderChunk` pass then turns
|
|
7
|
+
* each surviving `import ... from "mod"` into a runtime lookup against the
|
|
8
|
+
* global registry the shell sets up, keeping the plugin's ESM output valid.
|
|
9
|
+
*
|
|
10
|
+
* Lives in its own file (not plugin-config.ts) so tests can import
|
|
11
|
+
* `stratosExternals` + `UI_EXTERNALS` without dragging in the rest of the
|
|
12
|
+
* SDK's Vite plugin graph — which keeps cross-package TypeScript resolution
|
|
13
|
+
* from walking into unrelated files outside consumers' rootDir.
|
|
14
|
+
*/
|
|
15
|
+
import MagicString from "magic-string";
|
|
16
|
+
/**
|
|
17
|
+
* Canonical list of modules provided by the Stratos shell at runtime via
|
|
18
|
+
* `window.__stratos_modules__`. Plugin builds mark these as Rollup externals
|
|
19
|
+
* so imports survive bundling, and `stratosExternals` rewrites them into
|
|
20
|
+
* runtime lookups against the shell's global registry at render time.
|
|
21
|
+
*/
|
|
22
|
+
export const UI_EXTERNALS = [
|
|
23
|
+
"react",
|
|
24
|
+
"react-dom",
|
|
25
|
+
"react/jsx-runtime",
|
|
26
|
+
"@tanstack/react-router",
|
|
27
|
+
"@tanstack/react-query",
|
|
28
|
+
"@skyvexsoftware/stratos-sdk",
|
|
29
|
+
"sonner",
|
|
30
|
+
"socket.io-client",
|
|
31
|
+
"maplibre-gl",
|
|
32
|
+
"react-map-gl/maplibre",
|
|
33
|
+
];
|
|
34
|
+
export function stratosExternals() {
|
|
35
|
+
return {
|
|
36
|
+
name: "stratos-externals",
|
|
37
|
+
renderChunk(code) {
|
|
38
|
+
const s = new MagicString(code);
|
|
39
|
+
for (const modId of UI_EXTERNALS) {
|
|
40
|
+
const escaped = modId.replace(/[-/\\^$*+?.()|[\]{}@]/g, "\\$&");
|
|
41
|
+
const global = `window.__stratos_modules__[${JSON.stringify(modId)}]`;
|
|
42
|
+
const patterns = [
|
|
43
|
+
// 1. import Default, { named } from 'mod';
|
|
44
|
+
[
|
|
45
|
+
new RegExp(`import\\s+([\\w$]+)\\s*,\\s*\\{([^}]+)\\}\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
46
|
+
(_, def, names) => {
|
|
47
|
+
const destructured = names.replace(/([\w$]+)\s+as\s+([\w$]+)/g, "$1: $2");
|
|
48
|
+
return `const ${def} = ${global}.default || ${global};\nconst {${destructured}} = ${global};`;
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
// 2. import { named } from 'mod';
|
|
52
|
+
[
|
|
53
|
+
new RegExp(`import\\s*\\{([^}]+)\\}\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
54
|
+
(_, names) => {
|
|
55
|
+
const destructured = names.replace(/([\w$]+)\s+as\s+([\w$]+)/g, "$1: $2");
|
|
56
|
+
return `const {${destructured}} = ${global};`;
|
|
57
|
+
},
|
|
58
|
+
],
|
|
59
|
+
// 3. import * as ns from 'mod';
|
|
60
|
+
[
|
|
61
|
+
new RegExp(`import\\s+\\*\\s+as\\s+([\\w$]+)\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
62
|
+
(_, name) => `const ${name} = ${global};`,
|
|
63
|
+
],
|
|
64
|
+
// 4. import Default from 'mod';
|
|
65
|
+
[
|
|
66
|
+
new RegExp(`import\\s+([\\w$]+)\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
67
|
+
(_, def) => `const ${def} = ${global}.default || ${global};`,
|
|
68
|
+
],
|
|
69
|
+
// 5. import 'mod';
|
|
70
|
+
[new RegExp(`import\\s+['"]${escaped}['"]\\s*;?`, "g"), () => ""],
|
|
71
|
+
// 6. export { name } from 'mod';
|
|
72
|
+
[
|
|
73
|
+
new RegExp(`export\\s*\\{([^}]+)\\}\\s+from\\s+['"]${escaped}['"]\\s*;?`, "g"),
|
|
74
|
+
(_, names) => {
|
|
75
|
+
const parts = names.split(",").map((n) => n.trim());
|
|
76
|
+
const decls = [];
|
|
77
|
+
const exportNames = [];
|
|
78
|
+
for (const part of parts) {
|
|
79
|
+
const asMatch = part.match(/^([\w$]+)\s+as\s+([\w$]+)$/);
|
|
80
|
+
if (asMatch) {
|
|
81
|
+
decls.push(`const ${asMatch[2]} = ${global}[${JSON.stringify(asMatch[1])}];`);
|
|
82
|
+
exportNames.push(asMatch[2]);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
exportNames.push(part);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (decls.length > 0) {
|
|
89
|
+
return `${decls.join("\n")}\nconst {${exportNames.join(", ")}} = ${global};\nexport {${exportNames.join(", ")}};`;
|
|
90
|
+
}
|
|
91
|
+
return `const {${exportNames.join(", ")}} = ${global};\nexport {${exportNames.join(", ")}};`;
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
];
|
|
95
|
+
// Collect all matches first, then apply in reverse order to preserve offsets
|
|
96
|
+
const matches = [];
|
|
97
|
+
for (const [re, replacer] of patterns) {
|
|
98
|
+
re.lastIndex = 0;
|
|
99
|
+
let match;
|
|
100
|
+
while ((match = re.exec(code)) !== null) {
|
|
101
|
+
matches.push({
|
|
102
|
+
start: match.index,
|
|
103
|
+
end: match.index + match[0].length,
|
|
104
|
+
replacement: replacer(match[0], ...match.slice(1)),
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
// Apply in reverse so earlier offsets stay valid
|
|
109
|
+
matches
|
|
110
|
+
.sort((a, b) => b.start - a.start)
|
|
111
|
+
.forEach((m) => s.overwrite(m.start, m.end, m.replacement));
|
|
112
|
+
}
|
|
113
|
+
if (!s.hasChanged())
|
|
114
|
+
return null;
|
|
115
|
+
return { code: s.toString(), map: s.generateMap({ hires: true }) };
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|