@skyvexsoftware/stratos-sdk 0.1.5 → 0.1.6

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.
@@ -29,13 +29,16 @@ declare const BG_EXTERNALS: string[];
29
29
  */
30
30
  declare function stratosExternals(): Plugin;
31
31
  export type PluginBuildOptions = {
32
- pluginDir: string;
32
+ /** Plugin root directory. Defaults to process.cwd(). */
33
+ pluginDir?: string;
33
34
  ui?: {
34
35
  entry: string;
35
36
  };
36
37
  background?: {
37
38
  entry: string;
38
39
  };
40
+ /** Extra Vite config to merge (plugins, css, etc.) */
41
+ vite?: UserConfig;
39
42
  };
40
43
  /**
41
44
  * Create a Vite config for building a Stratos plugin.
@@ -157,26 +157,20 @@ function copyDirSync(src, dest) {
157
157
  * - "background" → builds the background module (Node.js, ESM)
158
158
  */
159
159
  export function createPluginConfig(options) {
160
- const { pluginDir, ui, background } = options;
160
+ const { pluginDir = process.cwd(), ui, background, vite: extraConfig, } = options;
161
161
  const target = process.env.BUILD_TARGET;
162
162
  if (target === "background" && background) {
163
163
  return createBackgroundConfig(pluginDir, background.entry);
164
164
  }
165
165
  if (ui) {
166
- return createUIConfig(pluginDir, ui.entry);
166
+ return createUIConfig(pluginDir, ui.entry, extraConfig);
167
167
  }
168
168
  throw new Error("No build target. Provide a ui entry or set BUILD_TARGET=background.");
169
169
  }
170
- function createUIConfig(pluginDir, entry) {
170
+ function createUIConfig(pluginDir, entry, extraConfig) {
171
171
  const isProduction = process.env.NODE_ENV === "production";
172
172
  return {
173
173
  root: pluginDir,
174
- plugins: [
175
- serveExternals(),
176
- stratosDevServer({ pluginDir }),
177
- stratosExternals(),
178
- copyPluginAssets(pluginDir),
179
- ],
180
174
  server: {
181
175
  cors: {
182
176
  origin: [
@@ -185,6 +179,14 @@ function createUIConfig(pluginDir, entry) {
185
179
  /^http:\/\/localhost:\d+$/,
186
180
  ],
187
181
  },
182
+ hmr: {
183
+ // When modules are loaded via stratos-dev:// protocol, Vite's HMR
184
+ // client needs to connect back to THIS dev server's WebSocket directly.
185
+ // Without this, it would try to derive the WS URL from the custom
186
+ // protocol scheme, which doesn't work.
187
+ protocol: "ws",
188
+ host: "localhost",
189
+ },
188
190
  },
189
191
  optimizeDeps: {
190
192
  exclude: [
@@ -212,6 +214,15 @@ function createUIConfig(pluginDir, entry) {
212
214
  jsx: "automatic",
213
215
  jsxImportSource: "react",
214
216
  },
217
+ // Merge extra config: plugins are concatenated, other keys shallow-merged
218
+ ...extraConfig,
219
+ plugins: [
220
+ serveExternals(),
221
+ stratosDevServer({ pluginDir }),
222
+ stratosExternals(),
223
+ copyPluginAssets(pluginDir),
224
+ ...(extraConfig?.plugins ?? []),
225
+ ],
215
226
  };
216
227
  }
217
228
  function createBackgroundConfig(pluginDir, entry) {
@@ -19,7 +19,7 @@ export function serveExternals() {
19
19
  return {
20
20
  name: "stratos-serve-externals",
21
21
  apply: "serve",
22
- enforce: "pre",
22
+ enforce: "post",
23
23
  transform(code, id) {
24
24
  // Only process JS/TS source files
25
25
  const ext = id.slice(id.lastIndexOf("."));
@@ -69,6 +69,23 @@ export function serveExternals() {
69
69
  // 6. Side-effect imports: import "pkg"
70
70
  result = result.replace(new RegExp(`import\\s+['"]${escaped}['"]\\s*;?`, "g"), `// (stratos-serve-externals: side-effect import of "${modId}" removed)`);
71
71
  }
72
+ // Second pass: catch Vite-resolved paths like
73
+ // import { jsxDEV } from "/node_modules/react/jsx-dev-runtime.js?v=..."
74
+ // These are injected by esbuild's JSX transform after our source-level pass.
75
+ for (const modId of EXTERNAL_PACKAGES) {
76
+ // Convert package name to a path pattern: "react/jsx-dev-runtime" -> "react/jsx-dev-runtime"
77
+ const pathPattern = modId.replace(/\//g, "/");
78
+ const global = `window.__stratos_modules__[${JSON.stringify(modId)}]`;
79
+ // Match: import { x } from "/node_modules/{pkg}.js?v=..." or "/{pkg}?..."
80
+ const resolvedRe = new RegExp(`import\\s*\\{([^}]+)\\}\\s+from\\s+['"][^'"]*/${escapeRegExp(pathPattern)}(?:\\.js)?(?:\\?[^'"]*)?['"]\\s*;?`, "g");
81
+ result = result.replace(resolvedRe, (_, names) => {
82
+ const destructured = names.replace(/([\w$]+)\s+as\s+([\w$]+)/g, "$1: $2");
83
+ return `const {${destructured}} = ${global};`;
84
+ });
85
+ // Match: import Default from "/node_modules/{pkg}.js?v=..."
86
+ const resolvedDefaultRe = new RegExp(`import\\s+([\\w$]+)\\s+from\\s+['"][^'"]*/${escapeRegExp(pathPattern)}(?:\\.js)?(?:\\?[^'"]*)?['"]\\s*;?`, "g");
87
+ result = result.replace(resolvedDefaultRe, (_, def) => `const ${def} = ${global}.default || ${global};`);
88
+ }
72
89
  if (result === code)
73
90
  return null;
74
91
  return { code: result, map: null };
@@ -20,6 +20,9 @@ import { io as ioClient } from "socket.io-client";
20
20
  */
21
21
  export function stratosDevServer(options) {
22
22
  const { pluginDir } = options;
23
+ // Shared state between configureServer and handleHotUpdate hooks
24
+ let socket = null;
25
+ let pluginId = "unknown";
23
26
  return {
24
27
  name: "stratos-dev-server",
25
28
  apply: "serve",
@@ -28,7 +31,6 @@ export function stratosDevServer(options) {
28
31
  (process.env.STRATOS_PORT
29
32
  ? parseInt(process.env.STRATOS_PORT, 10)
30
33
  : 2066);
31
- let socket = null;
32
34
  let retryTimeout = null;
33
35
  let retryDelay = 3000;
34
36
  const MAX_RETRY_DELAY = 30000;
@@ -41,7 +43,7 @@ export function stratosDevServer(options) {
41
43
  catch {
42
44
  console.error("[stratos-dev-server] Failed to read plugin.json at", manifestPath);
43
45
  }
44
- const pluginId = manifest.id ?? "unknown";
46
+ pluginId = manifest.id ?? "unknown";
45
47
  function clearRetry() {
46
48
  if (retryTimeout) {
47
49
  clearTimeout(retryTimeout);
@@ -186,6 +188,19 @@ export function stratosDevServer(options) {
186
188
  connect();
187
189
  });
188
190
  },
191
+ // Notify Stratos when UI source files change so it can reload the plugin
192
+ handleHotUpdate({ file }) {
193
+ // Only signal for UI source changes (not background, not config files)
194
+ if (file.includes("/src/") && !file.includes("/src/background/")) {
195
+ if (socket?.connected) {
196
+ console.log(`[stratos-dev-server] UI source changed: ${path.basename(file)}`);
197
+ socket.emit("dev:plugin-ui-updated", {
198
+ pluginId,
199
+ timestamp: Date.now(),
200
+ });
201
+ }
202
+ }
203
+ },
189
204
  };
190
205
  }
191
206
  //# sourceMappingURL=stratos-dev-server.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyvexsoftware/stratos-sdk",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Plugin SDK for Stratos — types, hooks, and UI components",
5
5
  "author": {
6
6
  "name": "Skyvex Software",