@bakery-framework/core 2.5.0-alpha.0 → 2.5.0-alpha.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bakery-framework/core",
3
- "version": "2.5.0-alpha.0",
3
+ "version": "2.5.0-alpha.1",
4
4
  "description": "Bakery framework core: handlers, router, config, session, caches, logger, compiler.",
5
5
  "keywords": [
6
6
  "bakery",
@@ -65,6 +65,6 @@
65
65
  "!src/tests"
66
66
  ],
67
67
  "engines": {
68
- "bun": ">=1.4.0"
68
+ "bun": ">=1.4.4"
69
69
  }
70
70
  }
@@ -1,12 +1,7 @@
1
1
  import { Strings } from '../cache/string'
2
2
  import { Bakery } from '../core/bakery'
3
3
  import { PluginHooks } from '../core/plugins'
4
- import {
5
- compLog,
6
- errorMsg,
7
- errorWithPosition,
8
- handlerLog,
9
- } from '../logger/serve-log'
4
+ import { compLog, errorWithPosition, handlerLog } from '../logger/serve-log'
10
5
  import type { MapOf } from '../types'
11
6
  import { is, Try, toHash } from '../utils/common'
12
7
  import { FileSystem as fs } from '../utils/fs'
@@ -128,10 +123,14 @@ function preprocessImports(source: string, filePath: fs.AbsolutePath): string {
128
123
  * Compile `source`, naming `path` so a failure can say where it happened.
129
124
  *
130
125
  * The two branches are not symmetric on purpose. Without a path there is no
131
- * file to name and no caller that can render a 500 (the Vue plugin compiles
132
- * fragments of an SFC it has already parsed), so a failure logs and hands the
133
- * source back. With a path the failure is a served request, and the answer is
134
- * `null`: `TSHandler` turns that into the 500 it has always had a branch for.
126
+ * file to resolve imports against and no caller that can render a 500 (the
127
+ * Vue plugin compiles fragments of an SFC it has already parsed), so a failure
128
+ * logs and hands the source back. `origin.file` names the file such a
129
+ * fragment came from, for that log line only: without it the line read
130
+ * "Failed to compile inline source: Transform failed", and a component that
131
+ * would not parse in the browser had to be found by hand. With a path the
132
+ * failure is a served request, and the answer is `null`: `TSHandler` turns
133
+ * that into the 500 it has always had a branch for.
135
134
  *
136
135
  * It used to be neither. The transpiler was wrapped only on the pathless
137
136
  * branch, so a syntax error in a `.ts` asset threw straight past `compile()`,
@@ -140,22 +139,31 @@ function preprocessImports(source: string, filePath: fs.AbsolutePath): string {
140
139
  * `Unhandled Server Error: <message>` with no file and no line while the client
141
140
  * got `An unexpected error occurred.` A total blackout for a one-character typo.
142
141
  */
143
- export function compileText(source: string): Promise<string>
142
+ export function compileText(
143
+ source: string,
144
+ origin?: { file: string },
145
+ ): Promise<string>
144
146
  export function compileText(
145
147
  source: string,
146
148
  path: fs.AbsolutePath,
147
149
  ): Promise<string | null>
148
- export async function compileText(source: string, path?: fs.AbsolutePath) {
149
- if (!path) {
150
- try {
151
- const content = await (await getTranspiler()).transform(source)
152
- return content
153
- } catch (err) {
154
- compLog.COMPILE_SOURCE_FAIL({ error: errorMsg(err) })
155
- return source
156
- }
150
+ export async function compileText(
151
+ source: string,
152
+ where?: fs.AbsolutePath | { file: string },
153
+ ) {
154
+ if (typeof where !== 'string') {
155
+ const [failed, content] = await Try.catch(
156
+ (await getTranspiler()).transform(source),
157
+ )
158
+ if (!failed) return content!
159
+
160
+ const error = errorWithPosition(failed)
161
+ if (where) compLog.COMPILE_FAIL({ file: where.file, error })
162
+ else compLog.COMPILE_SOURCE_FAIL({ error })
163
+ return source
157
164
  }
158
165
 
166
+ const path = where
159
167
  source = preprocessImports(source, path)
160
168
 
161
169
  const [failed, transformed] = await Try.catch(
@@ -163,8 +171,9 @@ export async function compileText(source: string, path?: fs.AbsolutePath) {
163
171
  )
164
172
 
165
173
  if (failed) {
166
- // `errorWithPosition`, not `errorMsg`: the thrown `BuildMessage` has no
167
- // stack, so `errorMsg` degrades to the bare message and the line number ( // the only thing that makes this actionable) is dropped. The file comes
174
+ // `errorWithPosition`, not `errorMsg`: what `transform()` rejects with
175
+ // has no stack, so `errorMsg` degrades to a bare message and drops the
176
+ // line number, the only thing that makes this actionable. The file comes
168
177
  // from `{file}`; the diagnostic's own `position.file` is `input.ts`,
169
178
  // because `transform()` was handed a string.
170
179
  compLog.COMPILE_FAIL({ file: path, error: errorWithPosition(failed) })
package/src/core/jsx.ts CHANGED
@@ -33,7 +33,7 @@ export const Fragment = ({ children }: { children?: any }) =>
33
33
  * like a string everywhere (`.trim()`, concatenation, `String()`), so callers
34
34
  * are unaffected.
35
35
  */
36
- export class SafeHtml extends String {}
36
+ class SafeHtml extends String {}
37
37
 
38
38
  /** Mark a string as trusted HTML, exempting it from escaping. */
39
39
  export function raw(value: unknown): string {
@@ -257,12 +257,20 @@ export function errorDetail(err: any): string {
257
257
  * `position.file` is `input.ts` whenever `transform()` was handed a source
258
258
  * string rather than a path (which is every compile this codebase does), so
259
259
  * printing it beside the real path would contradict it.
260
+ *
261
+ * `transform()` rejects with an `AggregateError` whose own message is only
262
+ * "Transform failed", with no position, and whose `errors` are the
263
+ * diagnostics, so the first of those is the one read. The rest usually follow
264
+ * from it: a `;` inside an object literal is reported as `Expected "}" but
265
+ * found ";"`, then as `Unexpected }` at the brace after it.
260
266
  */
261
267
  export function errorWithPosition(err: any): string {
262
- const position = (err as Diagnostic)?.position
268
+ const first: Diagnostic =
269
+ Array.isArray(err?.errors) && err.errors.length ? err.errors[0] : err
270
+ const position = first?.position
263
271
  if (!position || position.line == null) return errorMsg(err)
264
272
 
265
- const message = (err as Diagnostic).message || errorMsg(err)
273
+ const message = first.message || errorMsg(first)
266
274
  return `${message} (line ${position.line}, column ${position.column ?? 0})`
267
275
  }
268
276
 
package/src/router.ts CHANGED
@@ -289,7 +289,8 @@ export const serveWebSocket: Bun.WebSocketHandler<any> = {
289
289
  try {
290
290
  const h = prepareWSData(ws)
291
291
  if (h) return await h.handler.message(ws, message, h.data)
292
- config.websocket.message(ws, message)
292
+ // Optional since bun-types 1.4.4, like the other three below.
293
+ await config.websocket.message?.(ws, message)
293
294
  } catch (err: any) {
294
295
  serveLog.UNHANDLED_ERR({
295
296
  error: `WebSocket message error: ${errorMsg(err)}`,