@gxp-dev/tools 2.0.88 → 2.0.90

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.
@@ -218,6 +218,21 @@ function devCommand(argv) {
218
218
  const paths = resolveGxPaths()
219
219
  const projectPath = findProjectRoot()
220
220
 
221
+ // Surface which toolkit install is being used. resolveGxPaths() prefers
222
+ // <project>/node_modules/@gxp-dev/tools (local) and falls back to the
223
+ // CLI's own install location (global / npm link / workspace).
224
+ const localToolkitDir = path.join(
225
+ projectPath,
226
+ "node_modules",
227
+ "@gxp-dev",
228
+ "tools",
229
+ )
230
+ const installLocation =
231
+ paths.packageRoot === localToolkitDir ? "local" : "package"
232
+ logger.info(
233
+ `📦 Using ${installLocation} toolkit install: ${paths.packageRoot}`,
234
+ )
235
+
221
236
  // Load .env file if it exists for default values
222
237
  const envPath = path.join(projectPath, ".env")
223
238
  const envExamplePath = path.join(projectPath, ".env.example")
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gxp-dev/tools",
3
- "version": "2.0.88",
3
+ "version": "2.0.90",
4
4
  "description": "Dev tools to create platform plugins",
5
5
  "type": "commonjs",
6
6
  "publishConfig": {
@@ -172,9 +172,49 @@ export default defineConfig(async (ctx) => {
172
172
  console.log(`📄 index.html: ${useLocalIndex ? "local" : "runtime"}`)
173
173
  console.log(`📄 main.js: ${useLocalMain ? "local" : "runtime"}`)
174
174
 
175
+ // Build /@fs/ URLs that work regardless of whether the toolkit is inside
176
+ // the project's node_modules or installed globally. Vite's /@fs/ handler
177
+ // serves these via server.fs.allow (which already includes toolkitPath),
178
+ // so absolute paths outside process.cwd() just work.
179
+ const realRuntimeDir = (() => {
180
+ try {
181
+ return fs.realpathSync(runtimeDir)
182
+ } catch {
183
+ return runtimeDir
184
+ }
185
+ })().replace(/\\/g, "/")
186
+ const toFsUrl = (relPath) =>
187
+ `/@fs${realRuntimeDir.startsWith("/") ? "" : "/"}${realRuntimeDir}/${relPath}`
188
+ const runtimeMainFsUrl = toFsUrl("main.js")
189
+ const runtimeLogoFsUrl = toFsUrl("logo.png")
190
+
175
191
  // Create plugin to serve runtime files (index.html and main.js) if no local ones exist
176
192
  const runtimeFilesPlugin = {
177
193
  name: "runtime-files",
194
+ // Resolve the legacy `/@gx-runtime/*` absolute-URL form used by
195
+ // runtime/index.html (and by any project index.html that hasn't
196
+ // migrated to the bare `@gx-runtime/...` specifier). Vite's
197
+ // resolve.alias map only catches bare specifiers, and the
198
+ // configureServer middleware below only catches HTTP requests —
199
+ // Vite's internal pre-transform of script-src URLs takes
200
+ // neither path and ends up logging
201
+ // "Pre-transform error: Failed to load url /@gx-runtime/main.js"
202
+ // every render tick. Returning the real filesystem path here
203
+ // short-circuits the resolution entirely so pre-transform, the
204
+ // dep optimizer, and SSR all agree on where the file lives.
205
+ resolveId(id) {
206
+ if (typeof id !== "string") return null
207
+ if (id.startsWith("/@gx-runtime/")) {
208
+ const relative = id.slice("/@gx-runtime/".length)
209
+ if (!relative) return null
210
+ // Strip any query string (e.g. ?t=12345 from HMR) before
211
+ // resolving against the filesystem.
212
+ const [bare, query] = relative.split("?")
213
+ const resolved = path.resolve(runtimeDir, bare)
214
+ return query ? `${resolved}?${query}` : resolved
215
+ }
216
+ return null
217
+ },
178
218
  configureServer(server) {
179
219
  server.middlewares.use((req, res, next) => {
180
220
  // Serve runtime index.html for root requests and SPA navigation requests
@@ -205,15 +245,21 @@ export default defineConfig(async (ctx) => {
205
245
  ) {
206
246
  const runtimeIndexPath = path.join(runtimeDir, "index.html")
207
247
  if (fs.existsSync(runtimeIndexPath)) {
208
- // Read and transform the runtime index.html
248
+ // Rewrite hard-coded references to runtime assets so they
249
+ // resolve via Vite's /@fs/ handler instead of a guessed
250
+ // /node_modules/... path. This is what makes the same
251
+ // runtime work for local, linked, and global installs.
252
+ let html = fs.readFileSync(runtimeIndexPath, "utf-8")
253
+ html = html
254
+ .split("/node_modules/@gxp-dev/tools/runtime/logo.png")
255
+ .join(runtimeLogoFsUrl)
256
+ .split("/@gx-runtime/main.js")
257
+ .join(useLocalMain ? "/main.js" : runtimeMainFsUrl)
209
258
  server
210
- .transformIndexHtml(
211
- rawUrl,
212
- fs.readFileSync(runtimeIndexPath, "utf-8"),
213
- )
214
- .then((html) => {
259
+ .transformIndexHtml(rawUrl, html)
260
+ .then((transformed) => {
215
261
  res.setHeader("Content-Type", "text/html")
216
- res.end(html)
262
+ res.end(transformed)
217
263
  })
218
264
  .catch((err) => {
219
265
  console.error("Error transforming index.html:", err)
@@ -223,32 +269,24 @@ export default defineConfig(async (ctx) => {
223
269
  }
224
270
  }
225
271
 
226
- // Serve runtime main.js for @gx-runtime/main.js requests (unless local main.js is opted in)
272
+ // Back-compat: anything still hitting the legacy
273
+ // `/@gx-runtime/main.js` URL (e.g. a hand-rolled index.html)
274
+ // is redirected to the /@fs/ URL. The old transformRequest
275
+ // approach passed an absolute filesystem path and only worked
276
+ // when runtimeDir was inside process.cwd() — i.e. for local
277
+ // installs but not global ones.
227
278
  if (
228
279
  !useLocalMain &&
229
- (req.url === "/@gx-runtime/main.js" ||
230
- req.url?.startsWith("/@gx-runtime/main.js?"))
280
+ (urlPath === "/@gx-runtime/main.js" ||
281
+ urlPath.startsWith("/@gx-runtime/main.js"))
231
282
  ) {
232
- const runtimeMainPath = path.join(runtimeDir, "main.js")
233
- if (fs.existsSync(runtimeMainPath)) {
234
- // Use the real path to handle symlinks correctly
235
- const realMainPath = fs.realpathSync(runtimeMainPath)
236
- server
237
- .transformRequest(realMainPath)
238
- .then((result) => {
239
- if (result) {
240
- res.setHeader("Content-Type", "application/javascript")
241
- res.end(result.code)
242
- } else {
243
- next()
244
- }
245
- })
246
- .catch((err) => {
247
- console.error("Error transforming main.js:", err)
248
- next(err)
249
- })
250
- return
251
- }
283
+ const query = rawUrl.includes("?")
284
+ ? rawUrl.slice(rawUrl.indexOf("?"))
285
+ : ""
286
+ res.statusCode = 302
287
+ res.setHeader("Location", runtimeMainFsUrl + query)
288
+ res.end()
289
+ return
252
290
  }
253
291
 
254
292
  next()