@bakery-framework/plugin-dashboard 2.0.0-alpha.15 → 2.0.0-alpha.17

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.
Files changed (2) hide show
  1. package/package.json +4 -4
  2. package/src/setup.ts +33 -17
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bakery-framework/plugin-dashboard",
3
- "version": "2.0.0-alpha.15",
3
+ "version": "2.0.0-alpha.17",
4
4
  "description": "Bakery dashboard plugin.",
5
5
  "keywords": [
6
6
  "bakery",
@@ -33,11 +33,11 @@
33
33
  "!src/tests"
34
34
  ],
35
35
  "dependencies": {
36
- "@bakery-framework/core": "^2.0.0-alpha.15",
37
- "@bakery-framework/plugin-analytics": "^2.0.0-alpha.15"
36
+ "@bakery-framework/core": "^2.0.0-alpha.17",
37
+ "@bakery-framework/plugin-analytics": "^2.0.0-alpha.17"
38
38
  },
39
39
  "devDependencies": {
40
- "@bakery-framework/orm": "^2.0.0-alpha.15"
40
+ "@bakery-framework/orm": "^2.0.0-alpha.17"
41
41
  },
42
42
  "engines": {
43
43
  "bun": ">=1.4.0"
package/src/setup.ts CHANGED
@@ -147,7 +147,7 @@ async function handleDashboardView() {
147
147
  }
148
148
 
149
149
  /**
150
- * A bare `import` left in the bundle, or `null`.
150
+ * Why the bundle cannot run in a `<script>`, or `null`.
151
151
  *
152
152
  * `bundleModule` marks every *installed* package external, so a bare specifier
153
153
  * survives into the output and resolves through the page's import map. That is
@@ -156,19 +156,35 @@ async function handleDashboardView() {
156
156
  * apply to one, and a top-level `import` is a syntax error — so the *entire*
157
157
  * bundle fails to execute and the console does nothing at all.
158
158
  *
159
- * It is worth a check rather than a convention because of how it failed.
160
- * `Bun.build` reported success, the file was served with a 200 and the right
161
- * length, typecheck passed, and 2,376 tests passed because nothing
162
- * *requested the page*. That is the same gap CLAUDE.md already records for
163
- * `apps/starter`: a process that boots is not a page that works.
159
+ * **This asks the engine instead of matching a pattern, and the first version
160
+ * of it matched a pattern and was wrong.** It anchored on `^import`. In
161
+ * development the bundle is not minified and the import starts a line, so it
162
+ * looked right. Production minifies, the import lands mid-line, and the check
163
+ * that existed to catch exactly this missed it measured by reintroducing the
164
+ * bug and watching a production server answer 200 with the import present.
164
165
  *
165
- * Matched on a line starting with `import`, which is what an ESM bundle emits
166
- * for an external. A dynamic `import(...)` inside a function body is fine and
167
- * does not start a line.
166
+ * Against seven shapes, the anchored regex was wrong on three: a minified bare
167
+ * import, a side-effect-only `import"./x.css"`, and a top-level `await`. A
168
+ * widened regex got the first two and still missed the third. `new Function`
169
+ * is wrong on none of them, because it is not approximating the question — a
170
+ * function body rejects a top-level `import` and a top-level `await` for the
171
+ * same reasons a classic script does. It also costs less than the widened
172
+ * regex: 13.0 us against 26.4 on a 24 KB bundle, and 12.0 for the broken one.
173
+ *
174
+ * It parses without executing, and only on the build path — the cached branch
175
+ * returns the file and never reaches here.
176
+ *
177
+ * One known difference, and it is in the safe direction: a function body
178
+ * permits a top-level `return`, which a script does not. `Bun.build` does not
179
+ * emit one, and a false pass is a missed report rather than a broken page.
168
180
  */
169
- export function bareImportIn(bundle: string): string | null {
170
- const match = bundle.match(/^import\s[^\n]*?from\s*['"]([^'"]+)['"]/m)
171
- return match ? match[1]! : null
181
+ export function whyUnrunnable(bundle: string): string | null {
182
+ try {
183
+ new Function(bundle)
184
+ return null
185
+ } catch (error) {
186
+ return (error as Error).message
187
+ }
172
188
  }
173
189
 
174
190
  /**
@@ -212,15 +228,15 @@ export async function handleJsAsset() {
212
228
  )
213
229
  }
214
230
 
215
- // See `bareImportIn`. A build that "succeeded" and cannot run is worse than
231
+ // See `whyUnrunnable`. A build that "succeeded" and cannot run is worse than
216
232
  // one that failed, because it is silent.
217
- const bare = bareImportIn(bundleResult.content as string)
218
- if (bare) {
233
+ const unrunnable = whyUnrunnable(bundleResult.content as string)
234
+ if (unrunnable) {
219
235
  pluginLog.DASHBOARD_BUNDLE_ERR({
220
- error: `dashboard.js kept a bare import of "${bare}". It is served as a classic script, so an import map cannot resolve it and the whole bundle fails to parse. The console client must not import across a package boundary.`,
236
+ error: `dashboard.js cannot run as a classic script: ${unrunnable}. The usual cause is an import across a package boundary, which the bundler leaves as a bare specifier for the import map and an import map does not apply to a classic script.`,
221
237
  })
222
238
  return response.error(
223
- `dashboard.js kept a bare import of "${bare}"`,
239
+ `dashboard.js cannot run as a classic script: ${unrunnable}`,
224
240
  500,
225
241
  )
226
242
  }