@skyvexsoftware/stratos-sdk 0.7.3 → 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.
@@ -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("Stratos: window.__stratos_modules__[\"react-dom/client\"] is not available. The shell must initialize it before plugin modules evaluate.");
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;
@@ -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("Stratos: window.__stratos_modules__[\"react-dom\"] is not available. The shell must initialize it before plugin modules evaluate.");
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("Stratos: window.__stratos_modules__[\"react/jsx-dev-runtime\"] is not available. The shell must initialize it before plugin modules evaluate.");
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("Stratos: window.__stratos_modules__[\"react/jsx-runtime\"] is not available. The shell must initialize it before plugin modules evaluate.");
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;
@@ -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("Stratos: window.__stratos_modules__[\"react\"] is not available. The shell must initialize it before plugin modules evaluate.");
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;
@@ -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 React Fast Refresh preamble into the entry file.
95
- if (id.endsWith("/src/ui/index.tsx") || id.endsWith("/src/ui/index.ts")) {
96
- const preamble = [
97
- `import __StratosRefresh__ from "${devOrigin}/@react-refresh";`,
98
- `__StratosRefresh__.injectIntoGlobalHook(window);`,
99
- `window.$RefreshReg$ = () => {};`,
100
- `window.$RefreshSig$ = () => (type) => type;`,
101
- `window.__vite_plugin_react_preamble_installed__ = true;`,
102
- ].join("\n");
103
- patched = preamble + "\n" + patched;
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 };
@@ -40,5 +40,12 @@ export type PluginBuildOptions = {
40
40
  * - "background" → builds the background module (Node.js, ESM)
41
41
  */
42
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">;
43
50
  export { UI_EXTERNALS, BG_EXTERNALS, stratosExternals };
44
51
  //# sourceMappingURL=plugin-config.d.ts.map
@@ -198,14 +198,16 @@ function createUIConfig(pluginDir, entry, extraConfig) {
198
198
  ],
199
199
  };
200
200
  }
201
- function createBackgroundConfig(pluginDir, entry) {
202
- const isProduction = process.env.NODE_ENV === "production";
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) {
203
208
  return {
204
209
  root: pluginDir,
205
210
  resolve: {
206
- // Same default `@/` → `src/` alias as the UI config, so background
207
- // code can share import conventions with the UI without each plugin
208
- // wiring it up in its vite.config.ts.
209
211
  alias: [
210
212
  { find: /^@\//, replacement: path.resolve(pluginDir, "src") + "/" },
211
213
  ],
@@ -220,7 +222,6 @@ function createBackgroundConfig(pluginDir, entry) {
220
222
  },
221
223
  rollupOptions: {
222
224
  external: (id) => {
223
- // Bundle the SDK helpers subpath (createPlugin) into the output
224
225
  if (id === "@skyvexsoftware/stratos-sdk/helpers")
225
226
  return false;
226
227
  if (id === "@skyvexsoftware/stratos-sdk")
@@ -237,4 +238,7 @@ function createBackgroundConfig(pluginDir, entry) {
237
238
  },
238
239
  };
239
240
  }
241
+ function createBackgroundConfig(pluginDir, entry) {
242
+ return backgroundBuildOptions(pluginDir, entry);
243
+ }
240
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: ["ui", "hot-reload"],
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
- root: pluginDir,
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");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skyvexsoftware/stratos-sdk",
3
- "version": "0.7.3",
3
+ "version": "0.7.4",
4
4
  "description": "Plugin SDK for Stratos — types, hooks, and UI components",
5
5
  "author": {
6
6
  "name": "Skyvex Software Pty Ltd",