@ultimat3/core 19.1.1 → 19.1.3

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 +2 -2
  2. package/src/logger.ts +39 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ultimat3/core",
3
- "version": "19.1.1",
3
+ "version": "19.1.3",
4
4
  "description": "Ultimate's foundation: errors, context, env, config, clock, ids, logging, telemetry, lifecycle",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -37,6 +37,6 @@
37
37
  "test": "bun test"
38
38
  },
39
39
  "dependencies": {
40
- "@ultimat3/schema": "19.1.1"
40
+ "@ultimat3/schema": "19.1.3"
41
41
  }
42
42
  }
package/src/logger.ts CHANGED
@@ -121,8 +121,26 @@ export function setLogStream(stream: 'stdout' | 'stderr'): void {
121
121
  logStream = stream;
122
122
  }
123
123
 
124
+ /**
125
+ * The second half of the same defect, one call deeper than `envLevel`. A module init made safe
126
+ * that still reached `process.stdout` here would only move the `ReferenceError` from load to the
127
+ * first line written — and the framework's own client code writes one: `@ultimat3/realtime`'s
128
+ * `channel.ts` calls `logger.warn('channel.guard_failed', …)` in the browser. That package already
129
+ * says so out loud at `client.ts:51` — "the default reporter: `console.error`, never core's
130
+ * `logger` — that writes `process.stderr`" — a workaround for a hazard that belongs here, in the
131
+ * one file that owns the sink.
132
+ *
133
+ * `console` is the browser's stream pair, kept on the same `toStderr` split so a level does not
134
+ * change lane between runtimes. It is a fallback and never a preference: a container's stdout IS
135
+ * its log stream, and where there is a `process` this writes to the fd as it always did.
136
+ */
124
137
  function defaultWriter(line: string, level: LogLevel): void {
125
138
  const toStderr = logStream === 'stderr' || LEVEL_WEIGHT[level] >= LEVEL_WEIGHT.error;
139
+ if (typeof process === 'undefined') {
140
+ if (toStderr) console.error(line);
141
+ else console.log(line);
142
+ return;
143
+ }
126
144
  const stream = toStderr ? process.stderr : process.stdout;
127
145
  stream.write(`${line}\n`);
128
146
  }
@@ -238,8 +256,28 @@ function timestamp(clock: Clock): string {
238
256
  return INVALID_DATE;
239
257
  }
240
258
 
259
+ /**
260
+ * `LOG_LEVEL`, and the default where there is no environment to read it from.
261
+ *
262
+ * A BROWSER has no `process` binding at all, and this read runs at MODULE INIT — `logger` at the
263
+ * foot of this file is `createLogger()` evaluated when the module is. Measured on ai-maxxing's
264
+ * session console island: `@ultimat3/realtime`'s `channel.ts` calls `logger.warn`, so the shaker
265
+ * keeps `logger`, and the island's chunk died on `ReferenceError: process is not defined` before a
266
+ * line of the app's own code ran — the wrapper rendered `data-x-failed="process is not defined"`
267
+ * and the island never mounted. `info` is what a browser gets, and it is the right answer: there
268
+ * is no environment there to have said otherwise.
269
+ *
270
+ * `typeof`, and never an optional chain. Optional chaining guards a value that is NULLISH, not a
271
+ * binding that is UNDECLARED, so a bare `process?.env` throws the very `ReferenceError` it looks
272
+ * like it is preventing. `globalThis.process?.env` does not throw — that is a property access on
273
+ * an object that exists, and it answers `undefined` — but it is still the wrong form here: it
274
+ * differs from the throwing one by a prefix, so which of the two a reader is looking at is not
275
+ * visible at a glance, and one of them is a browser crash. `typeof` is the single form that is
276
+ * safe on a bare identifier, and it is what `version.ts` already uses for
277
+ * `ULTIMATE_FRAMEWORK_VERSION` — one way to do each thing.
278
+ */
241
279
  function envLevel(): LogLevel {
242
- const raw = process.env['LOG_LEVEL'];
280
+ const raw = typeof process === 'undefined' ? undefined : process.env['LOG_LEVEL'];
243
281
  return raw !== undefined && (LOG_LEVELS as readonly string[]).includes(raw)
244
282
  ? (raw as LogLevel)
245
283
  : 'info';