akanjs 2.3.9-rc.4 → 2.3.9-rc.5

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/README.ko.md CHANGED
@@ -220,7 +220,7 @@ akan update
220
220
 
221
221
  주요 영역:
222
222
 
223
- - **Workspace**: workspace 생성, Mongo 설정 생성, lint, sync.
223
+ - **Workspace**: workspace 생성, lint, sync.
224
224
  - **Application**: app start, build, typecheck, package, release.
225
225
  - **Library**: shared library 생성, 설치, sync, push, pull.
226
226
  - **Module and scalar**: domain module, model, view, unit, template, store 생성.
package/README.md CHANGED
@@ -218,7 +218,7 @@ akan update
218
218
 
219
219
  Common areas:
220
220
 
221
- - **Workspace**: create workspaces, generate Mongo configuration, lint and sync projects.
221
+ - **Workspace**: create workspaces, lint and sync projects.
222
222
  - **Application**: start, build, typecheck, package, and release apps.
223
223
  - **Library**: create, install, sync, push, and pull shared libraries.
224
224
  - **Module and scalar**: generate domain modules, models, views, units, templates, and stores.
package/common/Logger.ts CHANGED
@@ -2,24 +2,12 @@ import dayjs from "dayjs";
2
2
 
3
3
  const logLevels = ["trace", "verbose", "debug", "log", "info", "warn", "error"] as const;
4
4
  export type LogLevel = (typeof logLevels)[number];
5
- export type LoggerMeta = Record<string, unknown>;
6
-
7
- export interface LoggerSerializedError {
8
- name?: string;
9
- message: string;
10
- stack?: string;
11
- cause?: LoggerSerializedError | string;
12
- digest?: string;
13
- code?: string | number;
14
- status?: number;
15
- }
16
5
 
17
6
  export interface LoggerSinkEntry {
18
7
  stream: "stdout" | "stderr";
19
8
  level?: LogLevel;
20
9
  message: string;
21
10
  plainMessage: string;
22
- meta?: LoggerMeta;
23
11
  }
24
12
 
25
13
  export type LoggerSink = (entry: LoggerSinkEntry) => void | Promise<void>;
@@ -45,11 +33,6 @@ const colorizeMap: { [key in LogLevel]: (text: string) => string } = {
45
33
 
46
34
  const ansiPattern = new RegExp(`${String.fromCharCode(27)}\\[[0-?]*[ -/]*[@-~]`, "g");
47
35
 
48
- function readErrorProp(error: unknown, key: string): unknown {
49
- if (typeof error !== "object" || error === null || !(key in error)) return undefined;
50
- return (error as Record<string, unknown>)[key];
51
- }
52
-
53
36
  /** Log-level aware logger used by Akan runtime, CLI, and application services. */
54
37
  export class Logger {
55
38
  static level: LogLevel = (process.env?.AKAN_PUBLIC_LOG_LEVEL as LogLevel | undefined) ?? "log";
@@ -103,9 +86,6 @@ export class Logger {
103
86
  error(msg: string, context = "", name = this.name ?? "App") {
104
87
  if (Logger.#shouldLog("error")) Logger.#printMessages(name, msg, context, "error");
105
88
  }
106
- errorObject(msg: string, error: unknown, meta: LoggerMeta = {}, context = "", name = this.name ?? "App") {
107
- if (Logger.#shouldLog("error")) Logger.#printError(name, msg, error, meta, context);
108
- }
109
89
  raw(msg: string, method?: "console" | "process") {
110
90
  Logger.rawLog(msg, method);
111
91
  }
@@ -134,60 +114,6 @@ export class Logger {
134
114
  static error(msg: string, context = "", name = "App") {
135
115
  if (Logger.#shouldLog("error")) Logger.#printMessages(name, msg, context, "error");
136
116
  }
137
- static errorObject(msg: string, error: unknown, meta: LoggerMeta = {}, context = "", name = "App") {
138
- if (Logger.#shouldLog("error")) Logger.#printError(name, msg, error, meta, context);
139
- }
140
- static createErrorId(input: { requestId?: string; scope?: string; sequence?: string | number } = {}) {
141
- const parts = ["akanerr", input.requestId, input.scope, input.sequence, Date.now().toString(36)]
142
- .filter((part): part is string | number => part !== undefined && part !== "")
143
- .map((part) => String(part).replace(/[^a-zA-Z0-9_-]/g, "-"));
144
- return parts.join("-");
145
- }
146
- static serializeError(error: unknown): LoggerSerializedError {
147
- if (error instanceof Error) {
148
- const digest = readErrorProp(error, "digest");
149
- const code = readErrorProp(error, "code");
150
- const status = readErrorProp(error, "status") ?? readErrorProp(error, "statusCode");
151
- return {
152
- name: error.name,
153
- message: error.message,
154
- ...(error.stack ? { stack: error.stack } : {}),
155
- ...(error.cause !== undefined ? { cause: Logger.serializeError(error.cause) } : {}),
156
- ...(typeof digest === "string" ? { digest } : {}),
157
- ...(typeof code === "string" || typeof code === "number" ? { code } : {}),
158
- ...(typeof status === "number" ? { status } : {}),
159
- };
160
- }
161
- if (typeof error === "object" && error !== null) {
162
- const message = readErrorProp(error, "message");
163
- const name = readErrorProp(error, "name");
164
- const stack = readErrorProp(error, "stack");
165
- const cause = readErrorProp(error, "cause");
166
- const digest = readErrorProp(error, "digest");
167
- const code = readErrorProp(error, "code");
168
- const status = readErrorProp(error, "status") ?? readErrorProp(error, "statusCode");
169
- return {
170
- ...(typeof name === "string" ? { name } : {}),
171
- message: typeof message === "string" ? message : String(error),
172
- ...(typeof stack === "string" ? { stack } : {}),
173
- ...(cause !== undefined ? { cause: Logger.serializeError(cause) } : {}),
174
- ...(typeof digest === "string" ? { digest } : {}),
175
- ...(typeof code === "string" || typeof code === "number" ? { code } : {}),
176
- ...(typeof status === "number" ? { status } : {}),
177
- };
178
- }
179
- return { message: String(error) };
180
- }
181
- static formatError(error: unknown) {
182
- const serialized = Logger.serializeError(error);
183
- const details = serialized.stack ?? serialized.message;
184
- if (!serialized.cause) return details;
185
- const cause =
186
- typeof serialized.cause === "string"
187
- ? serialized.cause
188
- : (serialized.cause.stack ?? serialized.cause.message);
189
- return `${details}\nCaused by: ${cause}`;
190
- }
191
117
  static #colorize(msg: string, logLevel: LogLevel) {
192
118
  return colorizeMap[logLevel](msg);
193
119
  }
@@ -211,18 +137,12 @@ export class Logger {
211
137
  }
212
138
  }
213
139
  }
214
- static #printError(name: string | undefined, msg: string, error: unknown, meta: LoggerMeta, context: string) {
215
- const serializedError = Logger.serializeError(error);
216
- const message = `${msg}: ${Logger.formatError(error)}`;
217
- Logger.#printMessages(name, message, context, "error", "stderr", { ...meta, error: serializedError });
218
- }
219
140
  static #printMessages(
220
141
  name: string | undefined,
221
142
  content: string,
222
143
  context: string,
223
144
  logLevel: LogLevel,
224
145
  writeStreamType: "stdout" | "stderr" = logLevel === "error" ? "stderr" : "stdout",
225
- meta?: LoggerMeta,
226
146
  ) {
227
147
  const now = dayjs();
228
148
  const replicaIdx = (process as unknown as NodeJS.Process | undefined)?.env?.AKAN_REPLICA_IDX;
@@ -238,7 +158,7 @@ export class Logger {
238
158
  const timeDiffMsg = clc.yellow(`+${now.diff(Logger.#startAt, "ms")}ms`);
239
159
  const message = `${processMsg} ${timestampMsg} ${logLevelMsg} ${contextMsg} ${contentMsg} ${timeDiffMsg}\n`;
240
160
  if (Logger.#shouldEmitSink(logLevel))
241
- Logger.#emit({ stream: writeStreamType, level: logLevel, message, plainMessage: Logger.#stripAnsi(message), meta });
161
+ Logger.#emit({ stream: writeStreamType, level: logLevel, message, plainMessage: Logger.#stripAnsi(message) });
242
162
  if (!Logger.#shouldWriteConsole(logLevel)) return;
243
163
  if (typeof window === "undefined")
244
164
  (process[writeStreamType] as unknown as NodeJS.WriteStream | undefined)?.write(message);
package/common/index.ts CHANGED
@@ -17,14 +17,7 @@ export { isPhoneNumber } from "./isPhoneNumber";
17
17
  export { isQueryEqual } from "./isQueryEqual";
18
18
  export { isValidDate } from "./isValidDate";
19
19
  export { decodeJwtPayload } from "./jwtDecode";
20
- export {
21
- Logger,
22
- type LoggerMeta,
23
- type LoggerSerializedError,
24
- type LoggerSink,
25
- type LoggerSinkEntry,
26
- type LogLevel,
27
- } from "./Logger";
20
+ export { Logger, type LoggerSink, type LoggerSinkEntry, type LogLevel } from "./Logger";
28
21
  export {
29
22
  type AkanI18nConfig,
30
23
  type AkanI18nConfigInput,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "2.3.9-rc.4",
3
+ "version": "2.3.9-rc.5",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -110,7 +110,7 @@ type InMsg = InitMsg | RenderMsg | CancelMsg | ReloadMsg | UpdateCssAssetsMsg |
110
110
  type RenderControl =
111
111
  | { type: "redirect"; location: string; method: "replace" | "push"; status: RedirectStatus }
112
112
  | { type: "not-found" }
113
- | { type: "error"; error: unknown; errorId: string; digest: string };
113
+ | { type: "error"; error: unknown };
114
114
  interface FlightRenderResult {
115
115
  chunks: Uint8Array[];
116
116
  bytes: number;
@@ -206,7 +206,6 @@ export class RscRenderer {
206
206
  #resultCacheHits = 0;
207
207
  #resultCacheMisses = 0;
208
208
  #resultCacheBypass = 0;
209
- #renderErrorSequence = 0;
210
209
  readonly #send: (message: unknown) => void;
211
210
 
212
211
  constructor() {
@@ -224,74 +223,6 @@ export class RscRenderer {
224
223
  this.#send({ type: "hello" });
225
224
  }
226
225
 
227
- #nextRenderErrorId(requestId: string | undefined, scope: string): string {
228
- this.#renderErrorSequence += 1;
229
- return Logger.createErrorId({ requestId, scope, sequence: this.#renderErrorSequence });
230
- }
231
-
232
- #createRenderErrorPayload(
233
- error: unknown,
234
- input: {
235
- requestId?: string;
236
- scope: string;
237
- errorId?: string;
238
- url?: URL | string;
239
- pathname?: string;
240
- routeId?: string;
241
- trace?: RscTraceMetadata;
242
- },
243
- ) {
244
- const errorId = input.errorId ?? this.#nextRenderErrorId(input.requestId, input.scope);
245
- const serialized = Logger.serializeError(error);
246
- const pathname = input.pathname ?? input.trace?.pathname;
247
- const routeId = input.routeId ?? input.trace?.routeId;
248
- const url = typeof input.url === "string" ? input.url : input.url?.href;
249
- const meta = {
250
- errorId,
251
- requestId: input.requestId,
252
- scope: input.scope,
253
- url,
254
- pathname,
255
- routeId,
256
- digest: errorId,
257
- originalDigest: serialized.digest,
258
- };
259
- return {
260
- message: serialized.message,
261
- name: serialized.name,
262
- stack: serialized.stack,
263
- errorId,
264
- digest: errorId,
265
- requestId: input.requestId,
266
- scope: input.scope,
267
- pathname,
268
- routeId,
269
- meta,
270
- };
271
- }
272
-
273
- #logRenderError(
274
- message: string,
275
- error: unknown,
276
- input: {
277
- requestId?: string;
278
- scope: string;
279
- errorId?: string;
280
- url?: URL | string;
281
- pathname?: string;
282
- routeId?: string;
283
- trace?: RscTraceMetadata;
284
- },
285
- ) {
286
- const payload = this.#createRenderErrorPayload(error, input);
287
- this.#logger.errorObject(
288
- `${message} requestId=${input.requestId ?? "(none)"} scope=${input.scope} errorId=${payload.errorId}`,
289
- error,
290
- payload.meta,
291
- );
292
- return payload;
293
- }
294
-
295
226
  #handleMessage(msg: InMsg): void {
296
227
  switch (msg.type) {
297
228
  case "init":
@@ -356,11 +287,11 @@ export class RscRenderer {
356
287
  this.#logger.verbose(`init complete in ${Date.now() - startedAt}ms`);
357
288
  this.#send({ type: "ready" });
358
289
  } catch (error) {
359
- const payload = this.#logRenderError("init failed", error, { requestId: "__init__", scope: "rsc-init" });
290
+ this.#logger.error(`init failed: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`);
360
291
  this.#send({
361
292
  type: "error",
362
- ...payload,
363
293
  requestId: "__init__",
294
+ message: error instanceof Error ? error.message : String(error),
364
295
  });
365
296
  }
366
297
  }
@@ -395,15 +326,14 @@ export class RscRenderer {
395
326
  this.#logger.verbose(`reload complete buildId=${msg.buildId} in ${Date.now() - startedAt}ms`);
396
327
  this.#send({ type: "reloaded", buildId: msg.buildId });
397
328
  } catch (error) {
398
- const payload = this.#logRenderError(`reload failed buildId=${msg.buildId}`, error, {
399
- requestId: "__reload__",
400
- scope: "rsc-reload",
401
- });
329
+ this.#logger.error(
330
+ `reload failed buildId=${msg.buildId}: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`,
331
+ );
402
332
  this.#send({
403
333
  type: "error",
404
- ...payload,
405
334
  requestId: "__reload__",
406
335
  buildId: msg.buildId,
336
+ message: error instanceof Error ? error.message : String(error),
407
337
  });
408
338
  }
409
339
  }
@@ -808,13 +738,9 @@ export class RscRenderer {
808
738
  this.#send({ type: "not-found", requestId });
809
739
  return;
810
740
  }
811
- const payload = this.#logRenderError("[RSC] worker render failed", error, {
812
- requestId,
813
- scope: "rsc-render",
814
- url,
815
- pathname: activeRoute.url?.pathname,
816
- routeId: activeRoute.match?.pathRoute.path,
817
- });
741
+ this.#logger.error(
742
+ `render[${requestId}] failed url=${url}: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`,
743
+ );
818
744
  const fallbackUrl = activeRoute.url;
819
745
  const fallbackMatch = activeRoute.match;
820
746
  if (
@@ -836,8 +762,8 @@ export class RscRenderer {
836
762
  }
837
763
  this.#send({
838
764
  type: "error",
839
- ...payload,
840
765
  requestId,
766
+ message: error instanceof Error ? error.message : String(error),
841
767
  });
842
768
  } finally {
843
769
  this.#activeRenderReaders.delete(requestId);
@@ -908,7 +834,6 @@ export class RscRenderer {
908
834
  const controlRef: { current: RenderControl | null } = { current: null };
909
835
  const stream = await renderToReadableStream(element, clientManifest, {
910
836
  onError: (error) => {
911
- if (controlRef.current?.type === "error") return controlRef.current.digest;
912
837
  if (isAkanRedirectError(error)) {
913
838
  controlRef.current = {
914
839
  type: "redirect",
@@ -926,13 +851,8 @@ export class RscRenderer {
926
851
  controlRef.current = { type: "not-found" };
927
852
  return error.digest;
928
853
  }
929
- const payload = this.#logRenderError("[RSC] worker render stream error", error, {
930
- requestId: options.requestId,
931
- scope: "rsc-stream",
932
- trace: options.trace,
933
- });
934
- controlRef.current = { type: "error", error, errorId: payload.errorId, digest: payload.digest };
935
- return payload.digest;
854
+ controlRef.current = { type: "error", error };
855
+ return error instanceof Error ? error.message : String(error);
936
856
  },
937
857
  });
938
858
  const reader = stream.getReader();
@@ -1071,14 +991,11 @@ export class RscRenderer {
1071
991
  this.#stats.totalFlightChunks += result.chunksCount;
1072
992
  return true;
1073
993
  } catch (fallbackError) {
1074
- this.#logRenderError(`render[${requestId}] custom ${kind} fallback failed`, fallbackError, {
1075
- requestId,
1076
- scope: `fallback:${kind}`,
1077
- url,
1078
- pathname,
1079
- routeId: route.path,
1080
- trace,
1081
- });
994
+ this.#logger.error(
995
+ `render[${requestId}] custom ${kind} fallback failed: ${
996
+ fallbackError instanceof Error ? (fallbackError.stack ?? fallbackError.message) : String(fallbackError)
997
+ }`,
998
+ );
1082
999
  return false;
1083
1000
  }
1084
1001
  }
@@ -1108,13 +1025,11 @@ export class RscRenderer {
1108
1025
  this.#stats.totalFlightChunks += result.chunksCount;
1109
1026
  return true;
1110
1027
  } catch (error) {
1111
- this.#logRenderError(`render[${requestId}] system not-found fallback failed`, error, {
1112
- requestId,
1113
- scope: "fallback:system-not-found",
1114
- url,
1115
- pathname: url.pathname,
1116
- trace,
1117
- });
1028
+ this.#logger.error(
1029
+ `render[${requestId}] system not-found fallback failed: ${
1030
+ error instanceof Error ? (error.stack ?? error.message) : String(error)
1031
+ }`,
1032
+ );
1118
1033
  return false;
1119
1034
  }
1120
1035
  }
@@ -1132,13 +1047,9 @@ export class RscRenderer {
1132
1047
  return;
1133
1048
  }
1134
1049
  if (control.type === "error") {
1135
- const payload = this.#createRenderErrorPayload(control.error, {
1136
- requestId,
1137
- scope: "rsc-render-control",
1138
- errorId: control.errorId,
1139
- });
1140
- this.#logger.verbose(`render[${requestId}] error errorId=${payload.errorId}`);
1141
- this.#send({ type: "error", ...payload, requestId });
1050
+ const message = control.error instanceof Error ? control.error.message : String(control.error);
1051
+ this.#logger.verbose(`render[${requestId}] error`);
1052
+ this.#send({ type: "error", requestId, message });
1142
1053
  return;
1143
1054
  }
1144
1055
  this.#logger.verbose(`render[${requestId}] not-found`);
@@ -1,7 +1,7 @@
1
1
  import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import { fileURLToPath } from "node:url";
4
- import { type AkanI18nConfig, DEFAULT_AKAN_I18N, Logger, type LoggerMeta } from "akanjs/common";
4
+ import { type AkanI18nConfig, DEFAULT_AKAN_I18N, Logger } from "akanjs/common";
5
5
  import type { AkanTheme } from "akanjs/fetch";
6
6
  import type { AkanMetricsReport } from "akanjs/service";
7
7
  import type { ClientManifest } from "./artifact";
@@ -14,7 +14,7 @@ const DEFAULT_RSC_HOST_MAX_PENDING_CHUNKS = 256;
14
14
  export interface RscPending {
15
15
  onChunk: (data: Uint8Array) => void;
16
16
  onEnd: () => void;
17
- onError: (error: string | RscWorkerErrorPayload) => void;
17
+ onError: (message: string) => void;
18
18
  onMeta?: (meta: { theme?: AkanTheme; status?: number; trace?: RscTraceMetadata }) => void;
19
19
  onCacheState?: (state: RouteCacheRenderState) => void;
20
20
  onRedirect?: (location: string, method: RscRedirectMethod, status: RscRedirectStatus) => void;
@@ -25,19 +25,6 @@ export interface RscPending {
25
25
  export type RscRedirectMethod = "replace" | "push";
26
26
  export type RscRedirectStatus = 303 | 307 | 308;
27
27
 
28
- export interface RscWorkerErrorPayload {
29
- message: string;
30
- name?: string;
31
- stack?: string;
32
- errorId?: string;
33
- digest?: string;
34
- requestId?: string;
35
- scope?: string;
36
- pathname?: string;
37
- routeId?: string;
38
- meta?: LoggerMeta;
39
- }
40
-
41
28
  export interface RscWorkerInvalidateCacheMessage {
42
29
  type: "invalidate-cache";
43
30
  reason?: string;
@@ -48,7 +35,6 @@ export interface RscWorkerInvalidateCacheMessage {
48
35
  export type RscRenderResult =
49
36
  | {
50
37
  type: "stream";
51
- requestId?: string;
52
38
  stream: ReadableStream<Uint8Array>;
53
39
  theme?: AkanTheme;
54
40
  status?: number;
@@ -80,23 +66,6 @@ function createRscRenderAbortError(reason?: unknown): Error {
80
66
  return error;
81
67
  }
82
68
 
83
- export function createRscWorkerError(input: string | RscWorkerErrorPayload): Error {
84
- if (typeof input === "string") return new Error(input);
85
- const error = new Error(input.message);
86
- if (input.name) error.name = input.name;
87
- if (input.stack) error.stack = input.stack;
88
- Object.assign(error, {
89
- errorId: input.errorId,
90
- digest: input.digest ?? input.errorId,
91
- requestId: input.requestId,
92
- scope: input.scope,
93
- pathname: input.pathname,
94
- routeId: input.routeId,
95
- meta: input.meta,
96
- });
97
- return error;
98
- }
99
-
100
69
  export function createIdempotentRscRenderCancel(onCancel: (reason?: unknown) => void): (reason?: unknown) => void {
101
70
  let cancelled = false;
102
71
  return (reason?: unknown) => {
@@ -120,7 +89,6 @@ export function createRscWorkerInvalidateCacheMessage(
120
89
  }
121
90
 
122
91
  export function createRscHostRenderStream(input: {
123
- requestId?: string;
124
92
  setPending: (pending: RscPending) => void;
125
93
  deletePending: () => void;
126
94
  sendRenderOrQueue: () => void;
@@ -185,17 +153,7 @@ export function createRscHostRenderStream(input: {
185
153
  const settleStream = () => {
186
154
  if (settled) return;
187
155
  settled = true;
188
- resolve({
189
- type: "stream",
190
- requestId: input.requestId,
191
- stream,
192
- theme,
193
- status,
194
- trace,
195
- lateControl,
196
- cacheState,
197
- cancel: cancelRender,
198
- });
156
+ resolve({ type: "stream", stream, theme, status, trace, lateControl, cacheState, cancel: cancelRender });
199
157
  };
200
158
  input.setPending({
201
159
  onMeta: (meta) => {
@@ -224,17 +182,16 @@ export function createRscHostRenderStream(input: {
224
182
  settleStream();
225
183
  controller.close();
226
184
  },
227
- onError: (payload) => {
228
- const error = createRscWorkerError(payload);
185
+ onError: (msg) => {
229
186
  settleLateControl(null);
230
187
  settleCacheState({ cacheable: false, reason: "error" });
231
188
  cleanupAbortListener();
232
189
  if (!settled) {
233
190
  settled = true;
234
- reject(error);
191
+ reject(new Error(msg));
235
192
  return;
236
193
  }
237
- controller.error(error);
194
+ controller.error(new Error(msg));
238
195
  },
239
196
  onRedirect: (location, method, status) => {
240
197
  settleLateControl(null);
@@ -305,7 +262,7 @@ type RscInMsg =
305
262
  }
306
263
  | { type: "not-found"; requestId: string }
307
264
  | { type: "metrics"; metrics: AkanMetricsReport }
308
- | ({ type: "error"; requestId: string; buildId?: number } & RscWorkerErrorPayload);
265
+ | { type: "error"; requestId: string; message: string; buildId?: number };
309
266
 
310
267
  export interface RscWorkerReloadInput {
311
268
  clientManifest: ClientManifest;
@@ -422,7 +379,7 @@ export class RscWorker {
422
379
  this.#pending.set(requestId, {
423
380
  onChunk: (data) => controller.enqueue(data),
424
381
  onEnd: () => controller.close(),
425
- onError: (payload) => controller.error(createRscWorkerError(payload)),
382
+ onError: (msg) => controller.error(new Error(msg)),
426
383
  });
427
384
  const send = () => {
428
385
 
@@ -455,7 +412,6 @@ export class RscWorker {
455
412
  ): Promise<RscRenderResult> {
456
413
  const requestId = crypto.randomUUID();
457
414
  return createRscHostRenderStream({
458
- requestId,
459
415
  setPending: (pending) => {
460
416
  this.#pending.set(requestId, pending);
461
417
  },
@@ -700,8 +656,8 @@ export class RscWorker {
700
656
  case "error":
701
657
  if (message.requestId === "__init__") {
702
658
 
703
- if (!this.#readyResolved) this.#rejectReady(createRscWorkerError(message));
704
- else this.#logger.errorObject("[rsc] worker init error on restart", createRscWorkerError(message), message.meta);
659
+ if (!this.#readyResolved) this.#rejectReady(new Error(String(message.message)));
660
+ else this.#logger.error(`[rsc] worker init error on restart: ${message.message}`);
705
661
  return;
706
662
  }
707
663
  if (message.requestId === "__reload__") {
@@ -709,12 +665,12 @@ export class RscWorker {
709
665
  this.#pendingReload &&
710
666
  (message.buildId === undefined || this.#pendingReload.targetBuildId === message.buildId)
711
667
  ) {
712
- this.#pendingReload.reject(createRscWorkerError(message));
668
+ this.#pendingReload.reject(new Error(String(message.message)));
713
669
  this.#pendingReload = null;
714
670
  }
715
671
  return;
716
672
  }
717
- this.#resolvePending(message.requestId, (p) => p.onError(message));
673
+ this.#resolvePending(message.requestId, (p) => p.onError(String(message.message)));
718
674
  return;
719
675
  }
720
676
  }
@@ -595,28 +595,11 @@ export class SsrFromRscRenderer {
595
595
  : SsrFromRscRenderer.#clientBootstrap;
596
596
 
597
597
  const renderHtml = async () => {
598
- let root: ReactNode;
599
- try {
600
- root = await thenable;
601
- } catch (error) {
602
- input.onError?.({ scope: "flight-decode", error });
603
- throw error;
604
- }
605
- let stream: ReadableStream<Uint8Array> & { allReady: Promise<void> };
606
- try {
607
- stream = await renderToReadableStream(root, {
608
- bootstrapScriptContent: bootstrap,
609
- });
610
- } catch (error) {
611
- input.onError?.({ scope: "html-render", error });
612
- throw error;
613
- }
614
- try {
615
- await stream.allReady;
616
- } catch (error) {
617
- input.onError?.({ scope: "html-all-ready", error });
618
- throw error;
619
- }
598
+ const root = await thenable;
599
+ const stream = await renderToReadableStream(root, {
600
+ bootstrapScriptContent: bootstrap,
601
+ });
602
+ await stream.allReady;
620
603
  return stream;
621
604
  };
622
605
  const requestContext = input.requestStore ?? input.request;
@@ -73,5 +73,4 @@ export interface SsrFromRscInput {
73
73
  injectThemeInitScript?: boolean;
74
74
  lateControl?: Promise<SsrLateRedirect | null>;
75
75
  onCancel?: (reason?: unknown) => void;
76
- onError?: (event: { scope: "flight-decode" | "html-render" | "html-all-ready"; error: unknown }) => void;
77
76
  }
@@ -6,7 +6,6 @@ import {
6
6
  DEFAULT_AKAN_I18N,
7
7
  getBasePathFromPathname,
8
8
  Logger,
9
- type LoggerMeta,
10
9
  parseAkanI18nEnv,
11
10
  } from "akanjs/common";
12
11
  import { type AkanRequestStore, createRequestStore, parseCookieHeader } from "akanjs/fetch";
@@ -58,15 +57,6 @@ const RESERVED_BASE_PATHS = new Set(["admin"]);
58
57
  const CLIENT_CLOSED_REQUEST_STATUS = 499;
59
58
  export const DEFAULT_HTML_RESULT_CACHE_MAX_BODY_BYTES = 2 * 1024 * 1024;
60
59
 
61
- interface SsrErrorLogMeta extends LoggerMeta {
62
- errorId: string;
63
- requestId?: string;
64
- scope: string;
65
- pathname?: string;
66
- routeId?: string;
67
- url?: string;
68
- }
69
-
70
60
  export function createRscRedirectResponse(
71
61
  location: string,
72
62
  method: RscRedirectMethod,
@@ -459,16 +449,10 @@ export class WebRouter {
459
449
  return createRscRedirectResponse(result.location, result.method, result.status);
460
450
  if (result.type === "not-found") return WebRouter.#rscNotFoundResponse();
461
451
  if (result.status && result.status >= 500)
462
- return this.#renderRscErrorResponse(
463
- "__rsc",
464
- new Error("RSC render returned an error status"),
465
- req,
466
- result.trace,
467
- result.requestId,
468
- );
452
+ return this.#renderRscErrorResponse("__rsc", "Internal Server Error");
469
453
  return createRscNavigationStreamResponse(result);
470
454
  } catch (err) {
471
- return this.#renderRscErrorResponse("__rsc", err, req);
455
+ return this.#renderRscErrorResponse("__rsc", err);
472
456
  }
473
457
  },
474
458
  "/__rsc/manifest": () =>
@@ -546,8 +530,6 @@ export class WebRouter {
546
530
  );
547
531
  }
548
532
 
549
- let activeRscRequestId: string | undefined;
550
- let activeRscTrace: RscTraceMetadata | undefined;
551
533
  try {
552
534
  this.#requestStats.fullSsr += 1;
553
535
  const manifest = await this.#ensureRoute(url);
@@ -566,10 +548,6 @@ export class WebRouter {
566
548
  clientManifest: manifest.clientManifest,
567
549
  signal: req.signal,
568
550
  });
569
- if (rscResult.type === "stream") {
570
- activeRscRequestId = rscResult.requestId ?? rscResult.trace?.navId;
571
- activeRscTrace = rscResult.trace;
572
- }
573
551
  if (rscResult.type === "redirect")
574
552
  return Response.redirect(new URL(rscResult.location, url.origin), rscResult.status);
575
553
  if (rscResult.type === "not-found") return this.#renderSystemNotFoundFallbackResponse(req, url);
@@ -596,22 +574,6 @@ export class WebRouter {
596
574
  onCancel: (reason: unknown) => {
597
575
  rscResult.cancel(reason);
598
576
  },
599
- onError: ({ scope, error }) => {
600
- const meta = WebRouter.#createSsrErrorLogMeta(error, {
601
- scope,
602
- requestId: rscResult.requestId ?? rscResult.trace?.navId,
603
- pathname: url.pathname,
604
- routeId: rscResult.trace?.routeId,
605
- url: url.href,
606
- });
607
- this.#logger.errorObject(
608
- `[SSR] ${scope} failed requestId=${meta.requestId ?? "(none)"} pathname=${
609
- meta.pathname ?? "(unknown)"
610
- } route=${meta.routeId ?? "(unknown)"} errorId=${meta.errorId}`,
611
- error,
612
- meta,
613
- );
614
- },
615
577
  });
616
578
  const responseStatus = rscResult.status ?? 200;
617
579
  const responseHeaders = WebRouter.#htmlResponseHeaders(responseStatus);
@@ -680,11 +642,7 @@ export class WebRouter {
680
642
  headers,
681
643
  });
682
644
  } catch (err) {
683
- return this.#renderErrorResponse(req, "html", err, {
684
- requestId: activeRscRequestId,
685
- routeId: activeRscTrace?.routeId,
686
- pathname: activeRscTrace?.pathname ?? url.pathname,
687
- });
645
+ return this.#renderErrorResponse(req, url.pathname, err);
688
646
  }
689
647
  },
690
648
  };
@@ -839,110 +797,34 @@ export class WebRouter {
839
797
  });
840
798
  }
841
799
 
842
- #renderErrorResponse(
843
- req: Request,
844
- scope: string,
845
- err: unknown,
846
- input: { requestId?: string; pathname?: string; routeId?: string } = {},
847
- ): Promise<Response> {
800
+ #renderErrorResponse(req: Request, scope: string, err: unknown): Promise<Response> {
848
801
  if (WebRouter.#isExpectedRequestAbort(err)) return Promise.resolve(WebRouter.#clientClosedResponse());
849
802
  const message = err instanceof Error ? err.message : String(err);
850
- const url = new URL(req.url);
851
- const meta = WebRouter.#createSsrErrorLogMeta(err, {
852
- scope,
853
- requestId: input.requestId,
854
- pathname: input.pathname ?? url.pathname,
855
- routeId: input.routeId,
856
- url: url.href,
857
- });
858
- this.#logger.errorObject(
859
- `[SSR] render failed requestId=${meta.requestId ?? "(none)"} scope=${meta.scope} pathname=${
860
- meta.pathname ?? "(unknown)"
861
- } route=${meta.routeId ?? "(unknown)"} errorId=${meta.errorId}`,
862
- err,
863
- meta,
864
- );
803
+ this.#logger.error(`[SSR] render failed scope=${scope}: ${message}`);
865
804
  this.#hub?.broadcast({ type: "error", message });
866
805
  return createSystemPageResponse({
867
806
  kind: "error",
868
807
  method: req.method,
869
- pathname: url.pathname,
870
- lang: WebRouter.#getLocale(url.pathname, this.#artifact.i18n),
871
- homeHref: this.#getSystemPageHomeHref(req, url.pathname),
872
- stylesheetHref: this.#getStylesheetHref(req, url.pathname),
808
+ pathname: scope,
809
+ lang: WebRouter.#getLocale(new URL(req.url).pathname, this.#artifact.i18n),
810
+ homeHref: this.#getSystemPageHomeHref(req, new URL(req.url).pathname),
811
+ stylesheetHref: this.#getStylesheetHref(req, new URL(req.url).pathname),
873
812
  showDetails: !this.#prodMode,
874
813
  error: err,
875
- }).then((response) => {
876
- response.headers.set("X-Akan-Error-Id", meta.errorId);
877
- if (meta.requestId) response.headers.set("X-Akan-Rsc-Nav-Id", meta.requestId);
878
- return response;
879
814
  });
880
815
  }
881
816
 
882
- #renderRscErrorResponse(
883
- scope: string,
884
- err: unknown,
885
- req?: Request,
886
- trace?: RscTraceMetadata,
887
- requestId?: string,
888
- ): Response {
817
+ #renderRscErrorResponse(scope: string, err: unknown): Response {
889
818
  if (WebRouter.#isExpectedRequestAbort(err)) return WebRouter.#clientClosedResponse();
890
819
  const message = err instanceof Error ? err.message : String(err);
891
- const url = req ? new URL(req.url) : undefined;
892
- const meta = WebRouter.#createSsrErrorLogMeta(err, {
893
- scope,
894
- pathname: trace?.pathname ?? url?.pathname,
895
- routeId: trace?.routeId,
896
- requestId: trace?.navId ?? requestId,
897
- url: url?.href,
898
- });
899
- this.#logger.errorObject(
900
- `[SSR] render failed requestId=${meta.requestId ?? "(none)"} scope=${meta.scope} pathname=${
901
- meta.pathname ?? "(unknown)"
902
- } route=${meta.routeId ?? "(unknown)"} errorId=${meta.errorId}`,
903
- err,
904
- meta,
905
- );
820
+ this.#logger.error(`[SSR] render failed scope=${scope}: ${message}`);
906
821
  this.#hub?.broadcast({ type: "error", message });
907
822
  return new Response("Internal Server Error", {
908
823
  status: 500,
909
- headers: {
910
- "Content-Type": "text/plain; charset=utf-8",
911
- "Cache-Control": "no-store",
912
- "X-Akan-Error-Id": meta.errorId,
913
- ...(meta.requestId ? { "X-Akan-Rsc-Nav-Id": meta.requestId } : {}),
914
- },
824
+ headers: { "Content-Type": "text/plain; charset=utf-8", "Cache-Control": "no-store" },
915
825
  });
916
826
  }
917
827
 
918
- static #createSsrErrorLogMeta(
919
- error: unknown,
920
- input: { scope: string; requestId?: string; pathname?: string; routeId?: string; url?: string },
921
- ): SsrErrorLogMeta {
922
- const requestId = WebRouter.#stringErrorProp(error, "requestId") ?? input.requestId;
923
- const scope = WebRouter.#stringErrorProp(error, "scope") ?? input.scope;
924
- const pathname = WebRouter.#stringErrorProp(error, "pathname") ?? input.pathname;
925
- const routeId = WebRouter.#stringErrorProp(error, "routeId") ?? input.routeId;
926
- const errorId =
927
- WebRouter.#stringErrorProp(error, "errorId") ??
928
- WebRouter.#stringErrorProp(error, "digest") ??
929
- Logger.createErrorId({ requestId, scope });
930
- return {
931
- errorId,
932
- requestId,
933
- scope,
934
- pathname,
935
- routeId,
936
- url: input.url,
937
- };
938
- }
939
-
940
- static #stringErrorProp(error: unknown, key: string): string | undefined {
941
- if (typeof error !== "object" || error === null || !(key in error)) return undefined;
942
- const value = (error as Record<string, unknown>)[key];
943
- return typeof value === "string" && value ? value : undefined;
944
- }
945
-
946
828
  static #clientClosedResponse(): Response {
947
829
  return new Response(null, {
948
830
  status: CLIENT_CLOSED_REQUEST_STATUS,
@@ -1,21 +1,10 @@
1
1
  declare const logLevels: readonly ["trace", "verbose", "debug", "log", "info", "warn", "error"];
2
2
  export type LogLevel = (typeof logLevels)[number];
3
- export type LoggerMeta = Record<string, unknown>;
4
- export interface LoggerSerializedError {
5
- name?: string;
6
- message: string;
7
- stack?: string;
8
- cause?: LoggerSerializedError | string;
9
- digest?: string;
10
- code?: string | number;
11
- status?: number;
12
- }
13
3
  export interface LoggerSinkEntry {
14
4
  stream: "stdout" | "stderr";
15
5
  level?: LogLevel;
16
6
  message: string;
17
7
  plainMessage: string;
18
- meta?: LoggerMeta;
19
8
  }
20
9
  export type LoggerSink = (entry: LoggerSinkEntry) => void | Promise<void>;
21
10
  /** Log-level aware logger used by Akan runtime, CLI, and application services. */
@@ -37,7 +26,6 @@ export declare class Logger {
37
26
  info(msg: string, context?: string, name?: string): void;
38
27
  warn(msg: string, context?: string, name?: string): void;
39
28
  error(msg: string, context?: string, name?: string): void;
40
- errorObject(msg: string, error: unknown, meta?: LoggerMeta, context?: string, name?: string): void;
41
29
  raw(msg: string, method?: "console" | "process"): void;
42
30
  rawLog(msg: string, method?: "console" | "process"): void;
43
31
  static trace(msg: string, context?: string, name?: string): void;
@@ -47,14 +35,6 @@ export declare class Logger {
47
35
  static info(msg: string, context?: string, name?: string): void;
48
36
  static warn(msg: string, context?: string, name?: string): void;
49
37
  static error(msg: string, context?: string, name?: string): void;
50
- static errorObject(msg: string, error: unknown, meta?: LoggerMeta, context?: string, name?: string): void;
51
- static createErrorId(input?: {
52
- requestId?: string;
53
- scope?: string;
54
- sequence?: string | number;
55
- }): string;
56
- static serializeError(error: unknown): LoggerSerializedError;
57
- static formatError(error: unknown): string;
58
38
  static rawLog(msg?: string, method?: "console" | "process", outputStream?: "log" | "error"): void;
59
39
  static raw(msg?: string, method?: "console" | "process", outputStream?: "log" | "error"): void;
60
40
  }
@@ -13,7 +13,7 @@ export { isPhoneNumber } from "./isPhoneNumber.d.ts";
13
13
  export { isQueryEqual } from "./isQueryEqual.d.ts";
14
14
  export { isValidDate } from "./isValidDate.d.ts";
15
15
  export { decodeJwtPayload } from "./jwtDecode.d.ts";
16
- export { Logger, type LoggerMeta, type LoggerSerializedError, type LoggerSink, type LoggerSinkEntry, type LogLevel, } from "./Logger.d.ts";
16
+ export { Logger, type LoggerSink, type LoggerSinkEntry, type LogLevel } from "./Logger.d.ts";
17
17
  export { type AkanI18nConfig, type AkanI18nConfigInput, DEFAULT_AKAN_I18N, parseAkanI18nEnv, resolveAkanI18nConfig, } from "./localeConfig.d.ts";
18
18
  export { lowerlize } from "./lowerlize.d.ts";
19
19
  export { mergeVersion } from "./mergeVersion.d.ts";
@@ -1,4 +1,4 @@
1
- import { type AkanI18nConfig, type LoggerMeta } from "akanjs/common";
1
+ import { type AkanI18nConfig } from "akanjs/common";
2
2
  import type { AkanTheme } from "akanjs/fetch";
3
3
  import type { AkanMetricsReport } from "akanjs/service";
4
4
  import type { ClientManifest } from "./artifact.d.ts";
@@ -8,7 +8,7 @@ import type { BaseBuildArtifact, CssAsset } from "./types.d.ts";
8
8
  export interface RscPending {
9
9
  onChunk: (data: Uint8Array) => void;
10
10
  onEnd: () => void;
11
- onError: (error: string | RscWorkerErrorPayload) => void;
11
+ onError: (message: string) => void;
12
12
  onMeta?: (meta: {
13
13
  theme?: AkanTheme;
14
14
  status?: number;
@@ -21,18 +21,6 @@ export interface RscPending {
21
21
  }
22
22
  export type RscRedirectMethod = "replace" | "push";
23
23
  export type RscRedirectStatus = 303 | 307 | 308;
24
- export interface RscWorkerErrorPayload {
25
- message: string;
26
- name?: string;
27
- stack?: string;
28
- errorId?: string;
29
- digest?: string;
30
- requestId?: string;
31
- scope?: string;
32
- pathname?: string;
33
- routeId?: string;
34
- meta?: LoggerMeta;
35
- }
36
24
  export interface RscWorkerInvalidateCacheMessage {
37
25
  type: "invalidate-cache";
38
26
  reason?: string;
@@ -41,7 +29,6 @@ export interface RscWorkerInvalidateCacheMessage {
41
29
  }
42
30
  export type RscRenderResult = {
43
31
  type: "stream";
44
- requestId?: string;
45
32
  stream: ReadableStream<Uint8Array>;
46
33
  theme?: AkanTheme;
47
34
  status?: number;
@@ -60,11 +47,9 @@ export type RscRenderResult = {
60
47
  export declare function getRscHostMaxPendingChunks(value?: string | undefined): number;
61
48
  export declare function nextRscHostPendingChunkCount(currentPendingChunks: number, desiredSize: number | null): number;
62
49
  export declare function isRscHostPendingChunkOverflow(pendingChunks: number, maxPendingChunks: number): boolean;
63
- export declare function createRscWorkerError(input: string | RscWorkerErrorPayload): Error;
64
50
  export declare function createIdempotentRscRenderCancel(onCancel: (reason?: unknown) => void): (reason?: unknown) => void;
65
51
  export declare function createRscWorkerInvalidateCacheMessage(invalidation?: string | RouteCacheInvalidation): RscWorkerInvalidateCacheMessage;
66
52
  export declare function createRscHostRenderStream(input: {
67
- requestId?: string;
68
53
  setPending: (pending: RscPending) => void;
69
54
  deletePending: () => void;
70
55
  sendRenderOrQueue: () => void;
@@ -70,8 +70,4 @@ export interface SsrFromRscInput {
70
70
  injectThemeInitScript?: boolean;
71
71
  lateControl?: Promise<SsrLateRedirect | null>;
72
72
  onCancel?: (reason?: unknown) => void;
73
- onError?: (event: {
74
- scope: "flight-decode" | "html-render" | "html-all-ready";
75
- error: unknown;
76
- }) => void;
77
73
  }