akanjs 3.1.0-rc.22 → 3.1.0-rc.23

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.
@@ -498,5 +498,7 @@ export interface LayoutFallbackRoute {
498
498
  export interface RouteGuide {
499
499
  pathSegment: string;
500
500
  pathRoute?: PathRoute;
501
+ /** CSR: the page a path under this node that no route matches draws, made for the pathname that was asked for. */
502
+ notFoundRouteOf?: (pathname: string) => PathRoute;
501
503
  children: { [key: string]: RouteGuide };
502
504
  }
@@ -100,6 +100,8 @@ export const baseDictionary = serviceDictionary(["en", "ko"])
100
100
  cancel: ["Cancel", "취소"],
101
101
  retry: ["Try again", "다시 시도"],
102
102
  pageLoadFailed: ["This page could not be loaded.", "이 화면을 불러오지 못했습니다."],
103
+ pageNotFound: ["This page does not exist.", "없는 화면입니다."],
104
+ goBack: ["Go back", "돌아가기"],
103
105
  unauthorized: ["Unauthorized", "권한 없음"],
104
106
  agent: ["Agent", "에이전트"],
105
107
  agentIntro: ["Ask about this page or tell the agent what to do.", "이 화면에 대해 묻거나 할 일을 지시해 보세요."],
@@ -144,6 +144,27 @@ export type DocumentQuery<T = any> =
144
144
  [K in DocumentPath<T>]?: DocumentQueryValue;
145
145
  };
146
146
 
147
+ export const isDocumentQueryNode = (value: unknown): value is DocumentQueryNode => {
148
+ if (!value || typeof value !== "object" || Array.isArray(value)) return false;
149
+ const node = value as Record<string, unknown>;
150
+ const fits = (...keys: string[]) => Object.keys(node).every((key) => key === "kind" || keys.includes(key));
151
+ switch (node.kind) {
152
+ case "all":
153
+ case "any":
154
+ return Array.isArray(node.queries) && fits("queries");
155
+ case "not":
156
+ return !!node.query && typeof node.query === "object" && fits("query");
157
+ case "op":
158
+ return typeof node.op === "string" && queryOperatorKeys.has(node.op) && fits("op", "value");
159
+ case "raw":
160
+ return typeof node.sql === "string" && Array.isArray(node.params) && fits("sql", "params");
161
+ case "search":
162
+ return typeof node.text === "string" && fits("text", "columns", "prefix", "weights");
163
+ default:
164
+ return false;
165
+ }
166
+ };
167
+
147
168
  export interface SqlFragment {
148
169
  sql: string;
149
170
  params: unknown[];
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  type DocumentQuery,
3
- type DocumentQueryNode,
4
3
  type DocumentQueryOperator,
4
+ isDocumentQueryNode,
5
5
  queryOperatorKeys,
6
6
  } from "./documentQuery";
7
7
 
@@ -14,7 +14,7 @@ type RemovedAtTest = "isNull" | "isNotNull" | "value";
14
14
  export class LiveRowScope {
15
15
  static conflictOf(query: DocumentQuery | undefined, negated = false): string | null {
16
16
  if (!query || typeof query !== "object") return null;
17
- if (LiveRowScope.#isNode(query)) {
17
+ if (isDocumentQueryNode(query)) {
18
18
  if (query.kind === "all" || query.kind === "any")
19
19
  return query.queries.reduce<string | null>(
20
20
  (found, sub) => found ?? LiveRowScope.conflictOf(sub, negated),
@@ -30,7 +30,7 @@ export class LiveRowScope {
30
30
  }
31
31
 
32
32
  static #fieldConflict(path: string, value: unknown, negated: boolean): string | null {
33
- if (LiveRowScope.#isNode(value) && value.kind !== "op") return LiveRowScope.conflictOf(value, negated);
33
+ if (isDocumentQueryNode(value) && value.kind !== "op") return LiveRowScope.conflictOf(value, negated);
34
34
  if (path !== "removedAt") return null;
35
35
  for (const [test, spelled] of LiveRowScope.#testsOf(value)) {
36
36
  const named = negated ? `not(removedAt ${spelled})` : `removedAt ${spelled}`;
@@ -44,7 +44,7 @@ export class LiveRowScope {
44
44
  static #testsOf(value: unknown): [RemovedAtTest, string][] {
45
45
  if (value === undefined) return [];
46
46
  if (value === null) return [["isNull", "null"]];
47
- if (LiveRowScope.#isNode(value) && value.kind === "op") {
47
+ if (isDocumentQueryNode(value) && value.kind === "op") {
48
48
  const test = LiveRowScope.#testOf(value.op, value.value);
49
49
  return test ? [test] : [];
50
50
  }
@@ -72,8 +72,4 @@ export class LiveRowScope {
72
72
  if ((op === "oneOf" || op === "notOneOf") && !(operand as unknown[] | undefined)?.length) return null;
73
73
  return ["value", op];
74
74
  }
75
-
76
- static #isNode(value: unknown): value is DocumentQueryNode {
77
- return !!value && typeof value === "object" && "kind" in value;
78
- }
79
75
  }
@@ -4,6 +4,7 @@ import {
4
4
  type DocumentQueryNode,
5
5
  type DocumentQueryOperator,
6
6
  encodeDocumentValue,
7
+ isDocumentQueryNode,
7
8
  queryOperatorKeys,
8
9
  sanitizeJson,
9
10
  } from "./documentQuery";
@@ -49,7 +50,7 @@ export class DocumentQueryEvaluator {
49
50
  */
50
51
  static unevaluableReason(query: DocumentQuery | undefined): string | null {
51
52
  if (!query || typeof query !== "object") return null;
52
- if (DocumentQueryEvaluator.#isNode(query)) {
53
+ if (isDocumentQueryNode(query)) {
53
54
  if (query.kind === "raw") return "q.raw() carries SQL that only the database can run";
54
55
  if (query.kind === "search") return "q.search() compiles to a full-text JOIN with no in-memory equivalent";
55
56
  if (query.kind === "all" || query.kind === "any")
@@ -70,7 +71,7 @@ export class DocumentQueryEvaluator {
70
71
  if (!value || typeof value !== "object") return null;
71
72
  if (baseDocumentColumns.has(path)) return null;
72
73
  const keyAbsence = `${path}: exists/missing asks whether the key is in the stored JSON, which a document in hand cannot answer — use q.empty()`;
73
- if (DocumentQueryEvaluator.#isNode(value)) {
74
+ if (isDocumentQueryNode(value)) {
74
75
  if (value.kind === "op") return value.op === "exists" || value.op === "missing" ? keyAbsence : null;
75
76
  return DocumentQueryEvaluator.unevaluableReason(value as DocumentQuery);
76
77
  }
@@ -94,7 +95,7 @@ export class DocumentQueryEvaluator {
94
95
 
95
96
  evaluate(query: DocumentQuery | undefined, row: DocumentRowView): boolean {
96
97
  if (!query || typeof query !== "object") return true;
97
- if (DocumentQueryEvaluator.#isNode(query)) return this.#node(query, row);
98
+ if (isDocumentQueryNode(query)) return this.#node(query, row);
98
99
  const entries = Object.entries(query);
99
100
  if (!entries.length) return true;
100
101
  return entries.every(([path, value]) => this.#field(path, value, row));
@@ -118,7 +119,7 @@ export class DocumentQueryEvaluator {
118
119
  }
119
120
 
120
121
  #field(path: string, value: unknown, row: DocumentRowView): boolean {
121
- if (DocumentQueryEvaluator.#isNode(value)) {
122
+ if (isDocumentQueryNode(value)) {
122
123
  if (value.kind !== "op") return this.evaluate({ [path]: value } as DocumentQuery, row);
123
124
  return this.#operator(path, value.op, value.value, row);
124
125
  }
@@ -290,8 +291,4 @@ export class DocumentQueryEvaluator {
290
291
  static #foldAscii(text: string) {
291
292
  return text.replace(/[A-Z]/g, (char) => char.toLowerCase());
292
293
  }
293
-
294
- static #isNode(value: unknown): value is DocumentQueryNode {
295
- return !!value && typeof value === "object" && "kind" in value;
296
- }
297
294
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "3.1.0-rc.22",
3
+ "version": "3.1.0-rc.23",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -4,6 +4,7 @@ import {
4
4
  DocumentQueryEvaluator,
5
5
  type DocumentRowView,
6
6
  documentQueryHelper,
7
+ isDocumentQueryNode,
7
8
  type QueryFieldMap,
8
9
  } from "akanjs/document";
9
10
 
@@ -141,7 +142,7 @@ export class LiveSyncHub {
141
142
  }
142
143
 
143
144
  static #indexOf(query: DocumentQuery | undefined, fields: QueryFieldMap): Map<string, unknown> | null {
144
- if (!query || typeof query !== "object" || "kind" in query) return null;
145
+ if (!query || typeof query !== "object" || isDocumentQueryNode(query)) return null;
145
146
  const index = new Map<string, unknown>();
146
147
  for (const [path, value] of Object.entries(query)) {
147
148
  if (path.includes(".") || baseDocumentColumns.has(path)) return null;
@@ -1,5 +1,5 @@
1
1
  import { FIELD_META, ID } from "akanjs/base";
2
- import { type DocumentQuery, type DocumentQueryNode, searchColumns } from "akanjs/document";
2
+ import { type DocumentQuery, type DocumentQueryNode, isDocumentQueryNode, searchColumns } from "akanjs/document";
3
3
  import { DEFAULT_SEARCH_WEIGHTS, type SearchIndex } from "../searchIndex";
4
4
  import {
5
5
  BASE_COLUMNS,
@@ -70,7 +70,7 @@ export class QueryCompiler {
70
70
  }
71
71
 
72
72
  private compileNode(query: DocumentQuery, ctx: CompileContext): { sql: string; params: unknown[] } {
73
- if (this.isQueryNode(query)) {
73
+ if (isDocumentQueryNode(query)) {
74
74
  if (query.kind === "search") {
75
75
  if (!ctx.conjunctive)
76
76
  throw new Error(
@@ -145,7 +145,7 @@ export class QueryCompiler {
145
145
  const field = this.fields[path]?.getProps?.() ?? this.fields[path];
146
146
  const leaf = this.#leaf(path);
147
147
  const kind = this.pathKind(path);
148
- if (this.isQueryNode(value)) {
148
+ if (isDocumentQueryNode(value)) {
149
149
  if (value.kind !== "op") return this.compileNode({ [path]: value } as DocumentQuery, ctx);
150
150
  switch (value.op) {
151
151
  case "eq":
@@ -238,8 +238,4 @@ export class QueryCompiler {
238
238
  throw new Error(`Unknown document field path: ${path}`);
239
239
  }
240
240
  }
241
-
242
- private isQueryNode(value: unknown): value is DocumentQueryNode {
243
- return !!value && typeof value === "object" && "kind" in value;
244
- }
245
241
  }
@@ -14,6 +14,7 @@ import {
14
14
  type DocumentUpdateOptions,
15
15
  documentQueryHelper,
16
16
  isDocumentId,
17
+ isDocumentQueryNode,
17
18
  isDocumentUpdateNode,
18
19
  LiveRowScope,
19
20
  NoDocumentError,
@@ -608,7 +609,7 @@ export class SqlDocumentStore {
608
609
  }
609
610
 
610
611
  private extractInsertBase(query: DocumentQuery): Record<string, unknown> {
611
- if (!query || typeof query !== "object" || Array.isArray(query) || "kind" in query) return {};
612
+ if (!query || typeof query !== "object" || Array.isArray(query) || isDocumentQueryNode(query)) return {};
612
613
  return Object.fromEntries(
613
614
  Object.entries(query).flatMap(([key, value]) => {
614
615
  if (["all", "any"].includes(key) || key.startsWith("$")) return [];
@@ -480,6 +480,8 @@ export interface LayoutFallbackRoute {
480
480
  export interface RouteGuide {
481
481
  pathSegment: string;
482
482
  pathRoute?: PathRoute;
483
+ /** CSR: the page a path under this node that no route matches draws, made for the pathname that was asked for. */
484
+ notFoundRouteOf?: (pathname: string) => PathRoute;
483
485
  children: {
484
486
  [key: string]: RouteGuide;
485
487
  };
@@ -1 +1 @@
1
- export declare const baseDictionary: import("./dictInfo.d.ts").ServiceDictInfo<[string, string], "ping" | "pingBody" | "pingParam" | "pingQuery" | "wsPing" | "pubsubPing", "serverUnreachable" | "serverUnavailable" | "gatewayTimeout" | "tooManyRequests" | "unexpectedResponse" | "immutableField" | "invalidArgument" | "requiredArgument" | "invalidField" | "documentNotFound" | "relationNotFound" | "idempotencyInFlight" | "endpointClosed" | "mutationInApp" | "readOnlyDeployment", "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new">;
1
+ export declare const baseDictionary: import("./dictInfo.d.ts").ServiceDictInfo<[string, string], "ping" | "pingBody" | "pingParam" | "pingQuery" | "wsPing" | "pubsubPing", "serverUnreachable" | "serverUnavailable" | "gatewayTimeout" | "tooManyRequests" | "unexpectedResponse" | "immutableField" | "invalidArgument" | "requiredArgument" | "invalidField" | "documentNotFound" | "relationNotFound" | "idempotencyInFlight" | "endpointClosed" | "mutationInApp" | "readOnlyDeployment", "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new">;
@@ -1,13 +1,13 @@
1
1
  import type { AgentEndpoint, AgentTurn, BaseEndpoint } from "akanjs/signal";
2
2
  export declare const dictionary: {
3
- base: import("./locale.d.ts").DictModule<import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new">, "base.error.documentNotFound" | "base.error.gatewayTimeout" | "base.error.tooManyRequests" | "base.error.serverUnavailable" | "base.error.serverUnreachable" | "base.error.idempotencyInFlight" | "base.error.unexpectedResponse" | "base.error.mutationInApp" | "base.error.immutableField" | "base.error.invalidArgument" | "base.error.requiredArgument" | "base.error.invalidField" | "base.error.relationNotFound" | "base.error.endpointClosed" | "base.error.readOnlyDeployment">;
3
+ base: import("./locale.d.ts").DictModule<import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new">, "base.error.documentNotFound" | "base.error.gatewayTimeout" | "base.error.tooManyRequests" | "base.error.serverUnavailable" | "base.error.serverUnreachable" | "base.error.idempotencyInFlight" | "base.error.unexpectedResponse" | "base.error.mutationInApp" | "base.error.immutableField" | "base.error.invalidArgument" | "base.error.requiredArgument" | "base.error.invalidField" | "base.error.relationNotFound" | "base.error.endpointClosed" | "base.error.readOnlyDeployment">;
4
4
  agentTurn: import("./locale.d.ts").DictModule<import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc`, never>;
5
5
  agent: import("./locale.d.ts").DictModule<import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, "agent.error.llmUnavailable" | "agent.error.llmRequestFailed" | "agent.error.contextOverflow" | "agent.error.quotaExceeded">;
6
6
  };
7
- export declare const Err: import("./trans.d.ts").ErrConstructor<"base.error.documentNotFound" | "base.error.gatewayTimeout" | "base.error.tooManyRequests" | "base.error.serverUnavailable" | "base.error.serverUnreachable" | "base.error.idempotencyInFlight" | "base.error.unexpectedResponse" | "base.error.mutationInApp" | "base.error.immutableField" | "base.error.invalidArgument" | "base.error.requiredArgument" | "base.error.invalidField" | "base.error.relationNotFound" | "base.error.endpointClosed" | "base.error.readOnlyDeployment" | "agent.error.llmUnavailable" | "agent.error.llmRequestFailed" | "agent.error.contextOverflow" | "agent.error.quotaExceeded">, translate: (lang: "en" | "ko" | (string & {}) | "zhChs" | "zhCht" | "ja", key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, data?: import("./trans.d.ts").TranslationData) => string, msg: {
8
- error: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
9
- info: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
10
- warning: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
11
- success: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
12
- loading: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
13
- }, getDictionary: (lang: "en" | "ko" | (string & {}) | "zhChs" | "zhCht" | "ja") => object, getAllDictionary: () => import("./trans.d.ts").RootDictionary, __Dict_Key__: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, __Error_Key__: "base.error.documentNotFound" | "base.error.gatewayTimeout" | "base.error.tooManyRequests" | "base.error.serverUnavailable" | "base.error.serverUnreachable" | "base.error.idempotencyInFlight" | "base.error.unexpectedResponse" | "base.error.mutationInApp" | "base.error.immutableField" | "base.error.invalidArgument" | "base.error.requiredArgument" | "base.error.invalidField" | "base.error.relationNotFound" | "base.error.endpointClosed" | "base.error.readOnlyDeployment" | "agent.error.llmUnavailable" | "agent.error.llmRequestFailed" | "agent.error.contextOverflow" | "agent.error.quotaExceeded";
7
+ export declare const Err: import("./trans.d.ts").ErrConstructor<"base.error.documentNotFound" | "base.error.gatewayTimeout" | "base.error.tooManyRequests" | "base.error.serverUnavailable" | "base.error.serverUnreachable" | "base.error.idempotencyInFlight" | "base.error.unexpectedResponse" | "base.error.mutationInApp" | "base.error.immutableField" | "base.error.invalidArgument" | "base.error.requiredArgument" | "base.error.invalidField" | "base.error.relationNotFound" | "base.error.endpointClosed" | "base.error.readOnlyDeployment" | "agent.error.llmUnavailable" | "agent.error.llmRequestFailed" | "agent.error.contextOverflow" | "agent.error.quotaExceeded">, translate: (lang: "en" | "ko" | (string & {}) | "zhChs" | "zhCht" | "ja", key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, data?: import("./trans.d.ts").TranslationData) => string, msg: {
8
+ error: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
9
+ info: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
10
+ warning: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
11
+ success: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
12
+ loading: (key: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, option?: import("./trans.d.ts").TransMessageOption) => void;
13
+ }, getDictionary: (lang: "en" | "ko" | (string & {}) | "zhChs" | "zhCht" | "ja") => object, getAllDictionary: () => import("./trans.d.ts").RootDictionary, __Dict_Key__: import("./locale.d.ts").ServiceTranslatorKey<"base", BaseEndpoint, "edit" | "error" | "ok" | "retry" | "approve" | "view" | "remove" | "skip" | "success" | "unauthorized" | "save" | "refresh" | "password" | "agent" | "stop" | "connecting" | "send" | "cancel" | "somethingWrong" | "connected" | "serverDisconnected" | "refreshing" | "tryReconnecting" | "serverHasProblem" | "checkServerStatus" | "cameraPromptHeader" | "cameraPromptPhoto" | "cameraPromptPicture" | "cameraPromptCancel" | "failed" | "processing" | "processed" | "noData" | "invalidValueError" | "emailInvalidError" | "phoneInvalidError" | "pageLoadFailed" | "pageNotFound" | "goBack" | "agentIntro" | "agentPlaceholder" | "agentClear" | "agentQuestion" | "agentToolCard" | "agentAnswer" | "agentListen" | "agentVoiceFailed" | "agentAttach" | "agentAttachRemove" | "agentAttachReading" | "agentReferenceRemove" | "agentReferenceFailed" | "agentAttachTooLarge" | "agentAttachUnsupported" | "agentAttachDuplicate" | "agentAttachTooMany" | "agentAttachTooMuch" | "agentAnswerNeeded" | "agentQueue" | "agentQueuePlaceholder" | "agentQueued" | "agentQueueEdit" | "agentQueueCancel" | "agentToolDone" | "agentToolFailed" | "agentToolRunning" | "agentToolResult" | "agentTokens" | "agentTokensOf" | "agentCompactsAt" | "agentSummarizing" | "agentContinue" | "agentKeepGoing" | "agentCmdNew" | "agentCmdRetry" | "agentCmdCompact" | "agentCmdCopy" | "agentCmdHelp" | "agentCmdTools" | "agentHelpIntro" | "agentHelpNote" | "agentNothingToRetry" | "agentNothingToCompact" | "agentCompacted" | "agentSummary" | "agentBusy" | "agentCopied" | "agentCopyFailed" | "agentToolsHead" | "agentToolsState" | "decline" | "confirmClose" | "textTooShortError" | "textTooLongError" | "selectTooShortError" | "selectTooLongError" | "numberTooSmallError" | "numberTooBigError" | "passwordNotMatchError" | "selectDateError" | "priceUnit" | "passwordConfirm" | "noOptions" | "noSelection" | "addModel" | "createModel" | "createSuccess" | "updateModel" | "removeModel" | "updateSuccess" | "removeSuccess" | "sureToRemove" | "irreversibleOps" | "typeNameToRemove" | "yesRemove" | "removeMsg" | "confirmMsg" | "perPage" | "cardView" | "tableView" | "exportCsv" | "exportJson" | "actions" | "draftConflict" | "draftApplied" | "draftRestore" | "draftDiscard" | "draftStartOver" | "new"> | import("./locale.d.ts").ScalarTranslatorKey<"agentTurn", AgentTurn, never> | `agentStop.${string}` | `agentStop.${string}.desc` | import("./locale.d.ts").ServiceTranslatorKey<"agent", AgentEndpoint, never>, __Error_Key__: "base.error.documentNotFound" | "base.error.gatewayTimeout" | "base.error.tooManyRequests" | "base.error.serverUnavailable" | "base.error.serverUnreachable" | "base.error.idempotencyInFlight" | "base.error.unexpectedResponse" | "base.error.mutationInApp" | "base.error.immutableField" | "base.error.invalidArgument" | "base.error.requiredArgument" | "base.error.invalidField" | "base.error.relationNotFound" | "base.error.endpointClosed" | "base.error.readOnlyDeployment" | "agent.error.llmUnavailable" | "agent.error.llmRequestFailed" | "agent.error.contextOverflow" | "agent.error.quotaExceeded";
@@ -90,6 +90,7 @@ export declare const isDocumentUpdateNode: (value: unknown) => value is Document
90
90
  export type DocumentQuery<T = any> = DocumentQueryNode | {
91
91
  [K in DocumentPath<T>]?: DocumentQueryValue;
92
92
  };
93
+ export declare const isDocumentQueryNode: (value: unknown) => value is DocumentQueryNode;
93
94
  export interface SqlFragment {
94
95
  sql: string;
95
96
  params: unknown[];
@@ -22,5 +22,4 @@ export declare class QueryCompiler {
22
22
  * indices, array leaves and `Map` keys would refuse working queries.
23
23
  */
24
24
  private assertPath;
25
- private isQueryNode;
26
25
  }
@@ -5,9 +5,15 @@ export type CsrRouteModuleEntry = CsrRouteModuleLoader | {
5
5
  isAsyncDefault?: boolean;
6
6
  };
7
7
  export type CsrRouteContext = Record<string, CsrRouteModuleEntry>;
8
+ interface NotFoundRoute {
9
+ pathSegments: string[];
10
+ routeOf: (pathname: string) => PathRoute;
11
+ }
8
12
  export interface CsrRoutes {
9
13
  pathRoutes: PathRoute[];
10
14
  routeGuide: RouteGuide;
15
+ /** One per layout, from the top: what a path under it that no page matches draws. */
16
+ notFoundRoutes: NotFoundRoute[];
11
17
  }
12
18
  interface CsrRouteTableOptions {
13
19
  device: Pick<Device, "info" | "topSafeArea" | "bottomSafeArea">;
@@ -0,0 +1,5 @@
1
+ interface PageNotFoundProps {
2
+ pathname: string;
3
+ }
4
+ export declare const PageNotFound: ({ pathname }: PageNotFoundProps) => import("react").JSX.Element;
5
+ export {};
@@ -5,8 +5,11 @@ import {
5
5
  insetBreakpoints,
6
6
  type LayoutModule,
7
7
  type PageConfig,
8
+ type PageProps,
9
+ type PageState,
8
10
  type PathRoute,
9
11
  type Route,
12
+ RouteGuards,
10
13
  type RouteGuide,
11
14
  type RouteModule,
12
15
  type RouteModuleSource,
@@ -26,15 +29,24 @@ import {
26
29
  RouteLayering,
27
30
  routeSegmentToTreePath,
28
31
  } from "akanjs/common";
32
+ import { createElement } from "react";
33
+ import { PageNotFound } from "./PageNotFound";
29
34
 
30
35
  type RouteModuleWithConfig = RouteModule & { pageConfig?: PageConfig };
31
36
  type CsrRouteModuleLoader = () => Promise<RouteModuleSource>;
32
37
  export type CsrRouteModuleEntry = CsrRouteModuleLoader | { loader: CsrRouteModuleLoader; isAsyncDefault?: boolean };
33
38
  export type CsrRouteContext = Record<string, CsrRouteModuleEntry>;
34
39
 
40
+ interface NotFoundRoute {
41
+ pathSegments: string[];
42
+ routeOf: (pathname: string) => PathRoute;
43
+ }
44
+
35
45
  export interface CsrRoutes {
36
46
  pathRoutes: PathRoute[];
37
47
  routeGuide: RouteGuide;
48
+ /** One per layout, from the top: what a path under it that no page matches draws. */
49
+ notFoundRoutes: NotFoundRoute[];
38
50
  }
39
51
 
40
52
  interface CsrRouteTableOptions {
@@ -66,7 +78,7 @@ export class CsrRouteTable {
66
78
  readonly #options: CsrRouteTableOptions;
67
79
  readonly #listeners = new Set<() => void>();
68
80
  #keys: string[] = [];
69
- #routes: CsrRoutes = { pathRoutes: [], routeGuide: { pathSegment: "/", children: {} } };
81
+ #routes: CsrRoutes = { pathRoutes: [], routeGuide: { pathSegment: "/", children: {} }, notFoundRoutes: [] };
70
82
  #generation = 0;
71
83
  #cssSafeArea: SafeAreaInsets = { top: 0, bottom: 0 };
72
84
  #breakpoint = 0;
@@ -116,7 +128,8 @@ export class CsrRouteTable {
116
128
  : { ...pathRoute, pageState };
117
129
  });
118
130
  if (pathRoutes.every((pathRoute, idx) => pathRoute === current[idx])) return;
119
- this.#routes = { pathRoutes, routeGuide: CsrRouteTable.#guideOf(pathRoutes) };
131
+ const { notFoundRoutes } = this.#routes;
132
+ this.#routes = { pathRoutes, routeGuide: CsrRouteTable.#guideOf(pathRoutes, notFoundRoutes), notFoundRoutes };
120
133
  for (const listener of this.#listeners) listener();
121
134
  };
122
135
 
@@ -214,6 +227,7 @@ export class CsrRouteTable {
214
227
  } as Route);
215
228
  }
216
229
  assertUniqueRoutePatterns(pagePatterns);
230
+ const notFoundRoutes: NotFoundRoute[] = [];
217
231
  const getPathRoutes = (
218
232
  route: Route,
219
233
  parent: RouteLayer<RouteRender> | null = null,
@@ -228,6 +242,11 @@ export class CsrRouteTable {
228
242
  const ownPageConfig = route.renderPage && route.pageConfig ? route.pageConfig : null;
229
243
  const finalPageConfigChain = [...pageRenderConfigChain, ...(ownPageConfig ? [ownPageConfig] : [])];
230
244
  const pageState = this.#pageStateOf(path, finalPageConfigChain, width);
245
+ if (route.renderLayout) {
246
+ const notFoundPath = `${path === "/" ? "" : path}/*`;
247
+ const notFoundState = { ...this.#pageStateOf(notFoundPath, pageConfigChain, width), cache: false };
248
+ notFoundRoutes.push(CsrRouteTable.#notFoundOf(layer, notFoundPath, notFoundState));
249
+ }
231
250
  return [
232
251
  ...(route.renderPage
233
252
  ? [
@@ -251,7 +270,37 @@ export class CsrRouteTable {
251
270
  const rootRoute = routeMap.get("/");
252
271
  if (!rootRoute) throw new Error("No root route");
253
272
  const pathRoutes = getPathRoutes(rootRoute);
254
- return { pathRoutes, routeGuide: CsrRouteTable.#guideOf(pathRoutes) };
273
+ return { pathRoutes, routeGuide: CsrRouteTable.#guideOf(pathRoutes, notFoundRoutes), notFoundRoutes };
274
+ }
275
+
276
+ static #notFoundOf(layer: RouteLayer<RouteRender>, path: string, pageState: PageState): NotFoundRoute {
277
+ const rootCount = layer.renderRootLayouts.length;
278
+ const layouts = [...layer.renderRootLayouts, ...layer.renderLayouts];
279
+ const owner = layouts.findLastIndex((layout) => !!layout.NotFound);
280
+ const kept = Math.max(owner + 1, rootCount);
281
+ const NotFound = layouts[owner]?.NotFound;
282
+ const guard = RouteGuards.compose(...layouts.slice(kept).map((layout) => layout.guard));
283
+ const pathSegments = [...layer.pathSegments, "/*"];
284
+ const renderLayouts = layer.renderLayouts.slice(0, kept - rootCount);
285
+ return {
286
+ pathSegments: layer.pathSegments,
287
+ routeOf: (pathname) => ({
288
+ path,
289
+ pathSegments,
290
+ renderRootLayouts: layer.renderRootLayouts,
291
+ renderLayouts,
292
+ pageState,
293
+ renderPage: {
294
+ kind: "page",
295
+ isAsync: true,
296
+ guard,
297
+ render: (async ({ params, searchParams }: PageProps) =>
298
+ NotFound
299
+ ? await NotFound({ params, searchParams, pathname })
300
+ : createElement(PageNotFound, { pathname })) as RouteRender["render"],
301
+ },
302
+ }),
303
+ };
255
304
  }
256
305
 
257
306
  #pageStateOf(path: string, configChain: PageConfig[], width: number | undefined) {
@@ -267,7 +316,7 @@ export class CsrRouteTable {
267
316
  });
268
317
  }
269
318
 
270
- static #guideOf(pathRoutes: PathRoute[]) {
319
+ static #guideOf(pathRoutes: PathRoute[], notFoundRoutes: NotFoundRoute[]) {
271
320
  const routeGuide: RouteGuide = { pathSegment: "/", children: {} };
272
321
  pathRoutes.forEach((pathRoute) => {
273
322
  const pathSegments = pathRoute.pathSegments.slice(1);
@@ -283,6 +332,16 @@ export class CsrRouteTable {
283
332
  return next;
284
333
  }, routeGuide);
285
334
  });
335
+
336
+ for (const { pathSegments, routeOf } of notFoundRoutes) {
337
+ const node = pathSegments
338
+ .slice(1)
339
+ .reduce(
340
+ (guide: RouteGuide, pathSegment) => (guide.children[pathSegment] ??= { pathSegment, children: {} }),
341
+ routeGuide,
342
+ );
343
+ node.notFoundRouteOf ??= routeOf;
344
+ }
286
345
  return routeGuide;
287
346
  }
288
347
 
@@ -0,0 +1,24 @@
1
+ "use client";
2
+ import { router, Translator } from "akanjs/client";
3
+ import { parseAkanI18nEnv } from "akanjs/common";
4
+
5
+ interface PageNotFoundProps {
6
+ pathname: string;
7
+ }
8
+ export const PageNotFound = ({ pathname }: PageNotFoundProps) => {
9
+ const lang = Translator.getActiveLocale() ?? parseAkanI18nEnv().defaultLocale;
10
+ return (
11
+ <div role="alert" className="flex min-h-[60vh] flex-col items-center justify-center gap-4 p-6 text-center">
12
+ <p className="font-black text-5xl text-primary">404</p>
13
+ <p className="max-w-sm text-foreground/70 text-sm">{Translator.translateByLocale(lang, "base.pageNotFound")}</p>
14
+ <p className="max-w-sm break-all font-mono text-foreground/50 text-xs">{pathname}</p>
15
+ <button
16
+ type="button"
17
+ onClick={() => router.backOrFallback()}
18
+ className="rounded-field bg-primary px-4 py-2 font-medium text-primary-foreground text-sm"
19
+ >
20
+ {Translator.translateByLocale(lang, "base.goBack")}
21
+ </button>
22
+ </div>
23
+ );
24
+ };
@@ -17,28 +17,31 @@ export const useLocation = ({ rootRouteGuide }: UseLocationOptions) => {
17
17
  .filter((pathSegment) => !!pathSegment)
18
18
  .map((pathSegment) => `/${pathSegment}`);
19
19
  const getPathRoute = (pathname: string): PathRoute => {
20
- const pathSegments = getPathSegments(pathname);
21
- const getTargetRouteGuide = (pathSegments: string[], routeGuide: RouteGuide): RouteGuide => {
22
- const pathSegment = pathSegments.shift();
23
- if (!pathSegment) return routeGuide;
24
- const childrenSegments = Object.keys(routeGuide.children);
20
+ let target: RouteGuide | null = routeGuide.current;
21
+
22
+ let notFoundRouteOf = target.notFoundRouteOf;
23
+ for (const pathSegment of getPathSegments(pathname)) {
24
+ const parent: RouteGuide = target;
25
+ const childrenSegments = Object.keys(parent.children);
25
26
  const matchingPathSegment = childrenSegments.find((segment) => segment === pathSegment);
26
27
  const paramSegment = childrenSegments.find((segment) => segment.startsWith("/:"));
27
- const childRouteGuide = matchingPathSegment
28
- ? routeGuide.children[pathSegment]
28
+ const child = matchingPathSegment
29
+ ? parent.children[pathSegment]
29
30
  : paramSegment
30
- ? routeGuide.children[paramSegment]
31
- : null;
32
- if (!childRouteGuide) throw new Error(`Not found: ${pathname}`);
33
- return getTargetRouteGuide(pathSegments, childRouteGuide);
34
- };
35
- const targetRouteGuide = getTargetRouteGuide(pathSegments, routeGuide.current);
36
- const pathRoute = targetRouteGuide.pathRoute;
37
- if (!pathRoute) {
38
- csrLocation.assign("/404");
39
- throw new Error("404");
31
+ ? parent.children[paramSegment]
32
+ : undefined;
33
+ if (!child) {
34
+ target = null;
35
+ break;
36
+ }
37
+ target = child;
38
+ notFoundRouteOf = child.notFoundRouteOf ?? notFoundRouteOf;
40
39
  }
41
- return pathRoute;
40
+ if (target?.pathRoute) return target.pathRoute;
41
+ if (notFoundRouteOf) return notFoundRouteOf(pathname);
42
+ if (!target) throw new Error(`Not found: ${pathname}`);
43
+ csrLocation.assign("/404");
44
+ throw new Error("404");
42
45
  };
43
46
  const getParams = (pathname: string, pathRoute: PathRoute) => {
44
47
  const pathSegments = getPathSegments(pathname);