|
43 | 43 | */ |
44 | 44 |
|
45 | 45 | import type { IDataEngine } from '@objectstack/spec/contracts'; |
46 | | -import { isMissingTableError, isUniqueViolationError, operatorFacingErrorText } from '@objectstack/types'; |
| 46 | +import { isMissingTableError, isUniqueViolationError } from '@objectstack/types'; |
47 | 47 | import { PREFERENCE_OBJECT } from './preference-resolver.js'; |
48 | 48 |
|
49 | 49 | /** The sentinel the text column held for the admin-global default. Read here and nowhere else. */ |
@@ -93,6 +93,22 @@ export interface PreferenceUserConversionResult { |
93 | 93 | detail?: string; |
94 | 94 | } |
95 | 95 |
|
| 96 | +/** |
| 97 | + * The text an engine refusal reports, for the boot log and the result. |
| 98 | + * |
| 99 | + * Every read and write here goes through the data ENGINE, never the raw-SQL |
| 100 | + * seam, so the error in hand is the engine's own (a validation finding, a |
| 101 | + * `DUPLICATE_RECORD`, a driver error the SQL driver already redacts of its |
| 102 | + * statement and bound values). That is why this is the package's plain |
| 103 | + * `message` reading and not `operatorFacingErrorText`, the helper that digs a |
| 104 | + * dialect's words out of the raw seam's composed fault: there is no such fault |
| 105 | + * on this path, and each of that helper's callers is enumerated and pinned |
| 106 | + * against raw statements this module never issues. |
| 107 | + */ |
| 108 | +function messageOf(err: unknown): string { |
| 109 | + return err instanceof Error ? err.message : String(err); |
| 110 | +} |
| 111 | + |
96 | 112 | function textOrNull(value: unknown): string | null { |
97 | 113 | return value === null || value === undefined ? null : String(value); |
98 | 114 | } |
@@ -136,7 +152,7 @@ export async function convertWildcardPreferenceUsers( |
136 | 152 | // No table yet holds no '*' row — a fresh database, or a boot whose |
137 | 153 | // schema sync is skipped. Anything else is "could not look". |
138 | 154 | if (isMissingTableError(err, object)) return { status: 'absent', converted, missed }; |
139 | | - const detail = operatorFacingErrorText(err); |
| 155 | + const detail = messageOf(err); |
140 | 156 | logger?.error( |
141 | 157 | `[messaging] could not read ${object} to rewrite user_id '${LEGACY_WILDCARD_USER}' to the empty ` + |
142 | 158 | 'reference, so any admin-global notification default still stored that way is NOT applying: ' + |
@@ -174,7 +190,7 @@ export async function convertWildcardPreferenceUsers( |
174 | 190 | topic: textOrNull(row.topic), |
175 | 191 | channel: textOrNull(row.channel), |
176 | 192 | reason: duplicate ? 'duplicate' : 'failed', |
177 | | - detail: operatorFacingErrorText(err), |
| 193 | + detail: messageOf(err), |
178 | 194 | }); |
179 | 195 | } |
180 | 196 | } |
|
0 commit comments