@objectstack/types 17.2.0 → 17.4.0
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/CHANGELOG.md +1106 -0
- package/dist/index.d.mts +649 -11
- package/dist/index.d.ts +649 -11
- package/dist/index.js +331 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +313 -3
- package/dist/index.mjs.map +1 -1
- package/dist/node.d.mts +12 -3
- package/dist/node.d.ts +12 -3
- package/dist/node.js +199 -2
- package/dist/node.js.map +1 -1
- package/dist/node.mjs +201 -4
- package/dist/node.mjs.map +1 -1
- package/package.json +5 -4
package/dist/index.js
CHANGED
|
@@ -20,30 +20,40 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
DRIVER_TARGETED_TABLE: () => DRIVER_TARGETED_TABLE,
|
|
23
24
|
GLOBAL_UNIQUE_CONFIRMATION_REQUIRED: () => GLOBAL_UNIQUE_CONFIRMATION_REQUIRED,
|
|
24
25
|
GLOBAL_UNIQUE_ISOLATED_PRESCRIPTION: () => GLOBAL_UNIQUE_ISOLATED_PRESCRIPTION,
|
|
25
26
|
INTERNAL_ERROR_MESSAGE: () => INTERNAL_ERROR_MESSAGE,
|
|
27
|
+
PLATFORM_OWNER_EMAIL_ENV: () => PLATFORM_OWNER_EMAIL_ENV,
|
|
28
|
+
SERVER_FAULT_LOG_PREFIX: () => SERVER_FAULT_LOG_PREFIX,
|
|
26
29
|
VALIDATION_FAILED_STATUS: () => VALIDATION_FAILED_STATUS,
|
|
27
30
|
_resetEnvDeprecationWarnings: () => _resetEnvDeprecationWarnings,
|
|
28
31
|
buildGlobalUniqueStopMessage: () => buildGlobalUniqueStopMessage,
|
|
29
32
|
collectConfiguredLocales: () => collectConfiguredLocales,
|
|
30
33
|
collectGlobalUniques: () => collectGlobalUniques,
|
|
34
|
+
declareTargetedTable: () => declareTargetedTable,
|
|
31
35
|
declaredIndexUniqueIsGlobal: () => declaredIndexUniqueIsGlobal,
|
|
32
36
|
declaredUserMessage: () => declaredUserMessage,
|
|
33
37
|
declaresServerFault: () => declaresServerFault,
|
|
34
38
|
demotedDeclaredCode: () => demotedDeclaredCode,
|
|
39
|
+
describeFaultRequest: () => describeFaultRequest,
|
|
35
40
|
describeGlobalUniqueFinding: () => describeGlobalUniqueFinding,
|
|
36
41
|
emitDegradedBootBanner: () => emitDegradedBootBanner,
|
|
37
42
|
fieldUniqueIsGlobal: () => fieldUniqueIsGlobal,
|
|
38
43
|
fieldsFromZodIssues: () => fieldsFromZodIssues,
|
|
39
44
|
globalUniqueFindingId: () => globalUniqueFindingId,
|
|
45
|
+
isEmailVerifiedUserRow: () => isEmailVerifiedUserRow,
|
|
40
46
|
isMcpServerEnabled: () => isMcpServerEnabled,
|
|
47
|
+
isMissingTableError: () => isMissingTableError,
|
|
41
48
|
isModuleNotFoundError: () => isModuleNotFoundError,
|
|
42
49
|
isPlatformOwnedObject: () => isPlatformOwnedObject,
|
|
43
50
|
isRelationSubObjectPhrase: () => isRelationSubObjectPhrase,
|
|
51
|
+
isSchemaAlreadyExistsError: () => isSchemaAlreadyExistsError,
|
|
52
|
+
isServerFault: () => isServerFault,
|
|
44
53
|
isUnbackedConflictTargetError: () => isUnbackedConflictTargetError,
|
|
45
54
|
isUniqueViolationError: () => isUniqueViolationError,
|
|
46
55
|
keysetWalk: () => keysetWalk,
|
|
56
|
+
logServerFault: () => logServerFault,
|
|
47
57
|
looksLikeInternalErrorLeak: () => looksLikeInternalErrorLeak,
|
|
48
58
|
matchMissingColumnOfRelation: () => matchMissingColumnOfRelation,
|
|
49
59
|
postureGatesGlobalUniques: () => postureGatesGlobalUniques,
|
|
@@ -55,13 +65,21 @@ __export(index_exports, {
|
|
|
55
65
|
resolveMcpStdioAutoStart: () => resolveMcpStdioAutoStart,
|
|
56
66
|
resolveMultiOrgEnabled: () => resolveMultiOrgEnabled,
|
|
57
67
|
resolveOrgLimit: () => resolveOrgLimit,
|
|
68
|
+
resolveOrgMembershipLimit: () => resolveOrgMembershipLimit,
|
|
69
|
+
resolvePlatformOwnerEmail: () => resolvePlatformOwnerEmail,
|
|
58
70
|
resolveSandboxTimeoutMs: () => resolveSandboxTimeoutMs,
|
|
59
71
|
resolveSearchPinyinEnabled: () => resolveSearchPinyinEnabled,
|
|
60
72
|
resolveTenancyPosture: () => resolveTenancyPosture,
|
|
61
73
|
resolveThrownHttpError: () => resolveThrownHttpError,
|
|
62
74
|
sendError: () => sendError,
|
|
63
75
|
sendOk: () => sendOk,
|
|
76
|
+
serverFaultLogMessage: () => serverFaultLogMessage,
|
|
77
|
+
serverFaultLogMeta: () => serverFaultLogMeta,
|
|
78
|
+
serverFaultProvenance: () => serverFaultProvenance,
|
|
64
79
|
stampSearchPinyinEnabled: () => stampSearchPinyinEnabled,
|
|
80
|
+
strandedDecisionDetails: () => strandedDecisionDetails,
|
|
81
|
+
strandedDecisionFailure: () => strandedDecisionFailure,
|
|
82
|
+
targetedTableOf: () => targetedTableOf,
|
|
65
83
|
unconfirmedGlobalUniques: () => unconfirmedGlobalUniques,
|
|
66
84
|
uniqueViolationColumn: () => uniqueViolationColumn,
|
|
67
85
|
validationFailure: () => validationFailure,
|
|
@@ -86,6 +104,12 @@ function emitDegradedBootBanner(message) {
|
|
|
86
104
|
}
|
|
87
105
|
}
|
|
88
106
|
|
|
107
|
+
// src/email-verified.ts
|
|
108
|
+
function isEmailVerifiedUserRow(row) {
|
|
109
|
+
const v = row?.email_verified;
|
|
110
|
+
return v === true || v === 1 || v === "1" || v === "true";
|
|
111
|
+
}
|
|
112
|
+
|
|
89
113
|
// src/env.ts
|
|
90
114
|
var import_security = require("@objectstack/spec/security");
|
|
91
115
|
var _warnedKeys = /* @__PURE__ */ new Set();
|
|
@@ -131,6 +155,13 @@ function resolveTenancyPosture() {
|
|
|
131
155
|
}
|
|
132
156
|
return resolveMultiOrgEnabled() ? "isolated" : "single";
|
|
133
157
|
}
|
|
158
|
+
var PLATFORM_OWNER_EMAIL_ENV = "OS_PLATFORM_OWNER_EMAIL";
|
|
159
|
+
function resolvePlatformOwnerEmail() {
|
|
160
|
+
const raw = globalThis.process?.env?.[PLATFORM_OWNER_EMAIL_ENV];
|
|
161
|
+
if (raw == null) return void 0;
|
|
162
|
+
const trimmed = String(raw).trim();
|
|
163
|
+
return trimmed === "" ? void 0 : trimmed;
|
|
164
|
+
}
|
|
134
165
|
function resolveAllowDegradedTenancy() {
|
|
135
166
|
const raw = readEnvWithDeprecation("OS_ALLOW_DEGRADED_TENANCY", [], { silent: true });
|
|
136
167
|
if (raw == null) return false;
|
|
@@ -170,6 +201,12 @@ function resolveOrgLimit() {
|
|
|
170
201
|
const n = Number.parseInt(String(raw), 10);
|
|
171
202
|
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
172
203
|
}
|
|
204
|
+
function resolveOrgMembershipLimit() {
|
|
205
|
+
const raw = readEnvWithDeprecation("OS_ORG_MEMBERSHIP_LIMIT", [], { silent: true });
|
|
206
|
+
if (raw == null || String(raw).trim() === "") return void 0;
|
|
207
|
+
const n = Number.parseInt(String(raw), 10);
|
|
208
|
+
return Number.isFinite(n) && n > 0 ? n : void 0;
|
|
209
|
+
}
|
|
173
210
|
function resolveSearchPinyinEnabled(opts) {
|
|
174
211
|
const raw = readEnvWithDeprecation("OS_SEARCH_PINYIN_ENABLED", [], { silent: true });
|
|
175
212
|
if (raw != null && String(raw).trim() !== "") {
|
|
@@ -321,11 +358,78 @@ function isModuleNotFoundError(err) {
|
|
|
321
358
|
return msg.includes("Cannot find module") || msg.includes("Cannot find package");
|
|
322
359
|
}
|
|
323
360
|
|
|
361
|
+
// src/server-fault-log.ts
|
|
362
|
+
var SERVER_FAULT_LOG_PREFIX = "[5xx]";
|
|
363
|
+
function isServerFault(status) {
|
|
364
|
+
return typeof status === "number" && status >= 500;
|
|
365
|
+
}
|
|
366
|
+
function toError(thrown) {
|
|
367
|
+
if (thrown === void 0 || thrown === null) return void 0;
|
|
368
|
+
if (thrown instanceof Error) return thrown;
|
|
369
|
+
const wrapped = new Error(typeof thrown === "string" ? thrown : safeStringify(thrown));
|
|
370
|
+
wrapped.stack = void 0;
|
|
371
|
+
return wrapped;
|
|
372
|
+
}
|
|
373
|
+
function safeStringify(value) {
|
|
374
|
+
try {
|
|
375
|
+
return JSON.stringify(value) ?? String(value);
|
|
376
|
+
} catch {
|
|
377
|
+
return String(value);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
function serverFaultLogMessage(input) {
|
|
381
|
+
const err = toError(input.error);
|
|
382
|
+
const text = err?.message || input.message || "Unhandled server fault";
|
|
383
|
+
const where = [input.request?.method, input.request?.path].filter(Boolean).join(" ");
|
|
384
|
+
return `${SERVER_FAULT_LOG_PREFIX} ${input.status}${where ? ` ${where}` : ""} \u2014 ${text}`;
|
|
385
|
+
}
|
|
386
|
+
function serverFaultLogMeta(input) {
|
|
387
|
+
return {
|
|
388
|
+
status: input.status,
|
|
389
|
+
...input.code !== void 0 ? { code: input.code } : {},
|
|
390
|
+
...input.request?.method !== void 0 ? { method: input.request.method } : {},
|
|
391
|
+
...input.request?.path !== void 0 ? { path: input.request.path } : {},
|
|
392
|
+
...input.request?.requestId !== void 0 ? { requestId: input.request.requestId } : {}
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
function logServerFault(input, logger) {
|
|
396
|
+
if (!isServerFault(input.status)) return false;
|
|
397
|
+
const message = serverFaultLogMessage(input);
|
|
398
|
+
const meta = serverFaultLogMeta(input);
|
|
399
|
+
const err = toError(input.error);
|
|
400
|
+
try {
|
|
401
|
+
if (logger) {
|
|
402
|
+
logger.error(message, err, meta);
|
|
403
|
+
return true;
|
|
404
|
+
}
|
|
405
|
+
const sink = globalThis.console;
|
|
406
|
+
sink?.error?.(message, { ...meta, ...err?.stack ? { stack: err.stack } : {} });
|
|
407
|
+
return true;
|
|
408
|
+
} catch {
|
|
409
|
+
return false;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
function describeFaultRequest(req) {
|
|
413
|
+
const r = req;
|
|
414
|
+
if (!r || typeof r !== "object") return {};
|
|
415
|
+
const str = (v) => typeof v === "string" && v ? v : void 0;
|
|
416
|
+
const headerId = r.headers ? str(r.headers["x-request-id"]) ?? str(r.headers["X-Request-Id"]) : void 0;
|
|
417
|
+
const method = str(r.method);
|
|
418
|
+
const path = str(r.path) ?? str(r.url) ?? str(r.originalUrl);
|
|
419
|
+
const requestId = str(r.requestId) ?? headerId;
|
|
420
|
+
return {
|
|
421
|
+
...method !== void 0 ? { method } : {},
|
|
422
|
+
...path !== void 0 ? { path } : {},
|
|
423
|
+
...requestId !== void 0 ? { requestId } : {}
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
|
|
324
427
|
// src/response-envelope.ts
|
|
325
428
|
function sendOk(res, data, status = 200) {
|
|
326
429
|
res.status(status).json({ success: true, data });
|
|
327
430
|
}
|
|
328
431
|
function sendError(res, status, code, message, extra) {
|
|
432
|
+
logServerFault({ status, code, message, ...extra?.requestId ? { request: { requestId: extra.requestId } } : {} });
|
|
329
433
|
res.status(status).json({ success: false, error: { code, message, ...extra } });
|
|
330
434
|
}
|
|
331
435
|
|
|
@@ -390,10 +494,33 @@ function declaredUserMessage(error) {
|
|
|
390
494
|
const declared = error?.userMessage;
|
|
391
495
|
return typeof declared === "string" && declared.trim().length > 0 ? declared : void 0;
|
|
392
496
|
}
|
|
497
|
+
function serverFaultProvenance(thrown) {
|
|
498
|
+
if (thrown.status < 500) return void 0;
|
|
499
|
+
return thrown.declaredStatus === void 0 ? "undeclared" : "declared";
|
|
500
|
+
}
|
|
393
501
|
function demotedDeclaredCode(thrown) {
|
|
502
|
+
if (serverFaultProvenance(thrown) === "undeclared") return void 0;
|
|
394
503
|
return thrown.declaredCode !== void 0 && thrown.declaredCode !== thrown.code ? thrown.declaredCode : void 0;
|
|
395
504
|
}
|
|
396
505
|
|
|
506
|
+
// src/stranded-decision.ts
|
|
507
|
+
var CARRIER = "strandedDecision";
|
|
508
|
+
function strandedDecisionDetails(err) {
|
|
509
|
+
const carried = err?.[CARRIER];
|
|
510
|
+
if (!carried || typeof carried !== "object") return void 0;
|
|
511
|
+
const d = carried;
|
|
512
|
+
if (d.finalized !== true) return void 0;
|
|
513
|
+
if (typeof d.decision !== "string" || d.decision === "") return void 0;
|
|
514
|
+
if (typeof d.runId !== "string" || d.runId === "") return void 0;
|
|
515
|
+
if (typeof d.repairable !== "boolean") return void 0;
|
|
516
|
+
return { finalized: true, decision: d.decision, runId: d.runId, repairable: d.repairable };
|
|
517
|
+
}
|
|
518
|
+
function strandedDecisionFailure(message, details) {
|
|
519
|
+
const err = new Error(message);
|
|
520
|
+
err[CARRIER] = details;
|
|
521
|
+
return err;
|
|
522
|
+
}
|
|
523
|
+
|
|
397
524
|
// src/relation-sub-object.ts
|
|
398
525
|
function matchMissingColumnOfRelation(message) {
|
|
399
526
|
return MISSING_COLUMN_OF_RELATION.exec(message)?.[1];
|
|
@@ -406,7 +533,7 @@ var RELATION_SUB_OBJECT = /["'`][^"'`]+["'`]\s+of relation\s/i;
|
|
|
406
533
|
|
|
407
534
|
// src/unique-violation.ts
|
|
408
535
|
var UNIQUE_VIOLATION = {
|
|
409
|
-
codes: /* @__PURE__ */ new Set(["23505", "ER_DUP_ENTRY", "SQLITE_CONSTRAINT_UNIQUE"]),
|
|
536
|
+
codes: /* @__PURE__ */ new Set(["23505", "ER_DUP_ENTRY", "SQLITE_CONSTRAINT_UNIQUE", "UNIQUE_VIOLATION"]),
|
|
410
537
|
errnos: /* @__PURE__ */ new Set([1062]),
|
|
411
538
|
message: /unique constraint failed|violates unique constraint|unique violation|duplicate key|duplicate entry/i
|
|
412
539
|
};
|
|
@@ -470,16 +597,199 @@ function uniqueViolationColumn(error) {
|
|
|
470
597
|
return findUniqueViolationColumn(error, 0);
|
|
471
598
|
}
|
|
472
599
|
|
|
600
|
+
// src/driver-error-classification.ts
|
|
601
|
+
var RELATION_IN_PHRASE = [
|
|
602
|
+
// SQLite / libsql: `no such table: sys_metadata_history`, and the
|
|
603
|
+
// schema-qualified `no such table: main.orders` it uses when it resolved
|
|
604
|
+
// the name itself (views, triggers) or the caller qualified it.
|
|
605
|
+
/no such table:\s*([^\s'"`;,()]+)/i,
|
|
606
|
+
// PostgreSQL: `relation "sys_metadata_history" does not exist`
|
|
607
|
+
/relation\s+["'`]([^"'`]+)["'`]\s+does not exist/i,
|
|
608
|
+
// MySQL / MariaDB: `Table 'app.sys_metadata_history' doesn't exist`
|
|
609
|
+
/table\s+["'`]([^"'`]+)["'`]\s+doesn'?t exist/i,
|
|
610
|
+
// MySQL / MariaDB: `Unknown table 'app.t'`
|
|
611
|
+
/unknown table\s+["'`]([^"'`]+)["'`]/i
|
|
612
|
+
];
|
|
613
|
+
function normaliseRelationName(name) {
|
|
614
|
+
const afterQualifier = name.slice(name.lastIndexOf(".") + 1);
|
|
615
|
+
const namespaceEnd = afterQualifier.lastIndexOf("__");
|
|
616
|
+
const bare = namespaceEnd === -1 ? afterQualifier : afterQualifier.slice(namespaceEnd + 2);
|
|
617
|
+
return bare.toLowerCase();
|
|
618
|
+
}
|
|
619
|
+
function phraseNamesAnotherRelation(message, readObject) {
|
|
620
|
+
const expected = normaliseRelationName(readObject);
|
|
621
|
+
if (expected === "") return false;
|
|
622
|
+
let named = false;
|
|
623
|
+
for (const pattern of RELATION_IN_PHRASE) {
|
|
624
|
+
const captured = pattern.exec(message)?.[1];
|
|
625
|
+
if (captured === void 0) continue;
|
|
626
|
+
const candidate = normaliseRelationName(captured);
|
|
627
|
+
if (candidate === "") continue;
|
|
628
|
+
if (candidate === expected) return false;
|
|
629
|
+
named = true;
|
|
630
|
+
}
|
|
631
|
+
return named;
|
|
632
|
+
}
|
|
633
|
+
var ALREADY_EXISTS = {
|
|
634
|
+
codes: /* @__PURE__ */ new Set([
|
|
635
|
+
// PostgreSQL SQLSTATE (class 42 — syntax error or access rule violation)
|
|
636
|
+
"42P07",
|
|
637
|
+
// duplicate_table
|
|
638
|
+
"42701",
|
|
639
|
+
// duplicate_column
|
|
640
|
+
"42710",
|
|
641
|
+
// duplicate_object — index / constraint already exists
|
|
642
|
+
// MySQL / MariaDB (mysql2 puts the symbolic name on `code`)
|
|
643
|
+
"ER_TABLE_EXISTS_ERROR",
|
|
644
|
+
// 1050
|
|
645
|
+
"ER_DUP_FIELDNAME",
|
|
646
|
+
// 1060
|
|
647
|
+
"ER_DUP_KEYNAME"
|
|
648
|
+
// 1061
|
|
649
|
+
]),
|
|
650
|
+
errnos: /* @__PURE__ */ new Set([1050, 1060, 1061]),
|
|
651
|
+
/**
|
|
652
|
+
* Message fallback for drivers that carry no machine-readable code —
|
|
653
|
+
* notably SQLite, whose `code` is the undifferentiated `SQLITE_ERROR` for
|
|
654
|
+
* every DDL failure, so the message is the only signal available:
|
|
655
|
+
* - `table sys_metadata already exists`
|
|
656
|
+
* - `duplicate column name: environment_id`
|
|
657
|
+
* - `index idx_x already exists`
|
|
658
|
+
* Postgres phrases its own as `relation "x" already exists` /
|
|
659
|
+
* `column "x" of relation "y" already exists`, which matches the same test.
|
|
660
|
+
*/
|
|
661
|
+
message: /already exists|duplicate column name|duplicate key name/i
|
|
662
|
+
};
|
|
663
|
+
var MISSING_TABLE = {
|
|
664
|
+
codes: /* @__PURE__ */ new Set([
|
|
665
|
+
"42P01",
|
|
666
|
+
// PostgreSQL undefined_table
|
|
667
|
+
"ER_NO_SUCH_TABLE"
|
|
668
|
+
// MySQL / MariaDB 1146
|
|
669
|
+
]),
|
|
670
|
+
errnos: /* @__PURE__ */ new Set([1146]),
|
|
671
|
+
/**
|
|
672
|
+
* - SQLite / libsql: `no such table: sys_metadata_history`
|
|
673
|
+
* - PostgreSQL: `relation "sys_metadata_history" does not exist`
|
|
674
|
+
* - MySQL/MariaDB: `Table 'app.sys_metadata_history' doesn't exist`
|
|
675
|
+
*/
|
|
676
|
+
message: /no such table|relation ["'`][^"'`]+["'`] does not exist|table ["'`][^"'`]+["'`] doesn'?t exist|unknown table/i,
|
|
677
|
+
excludes: {
|
|
678
|
+
/**
|
|
679
|
+
* Exactly the three SQLSTATEs the docblock above already names as
|
|
680
|
+
* must-stay-loud neighbours of `does not exist`. They are listed here
|
|
681
|
+
* rather than merely trusted to miss the message test, because two of
|
|
682
|
+
* them (42703 columns, 42704 constraints/triggers) have a phrasing that
|
|
683
|
+
* *does* hit it, and because a code is a fact where prose is a guess.
|
|
684
|
+
*
|
|
685
|
+
* Postgres-shaped on purpose: measured, neither MySQL
|
|
686
|
+
* (`Unknown column 'label' in 'field list'`) nor SQLite
|
|
687
|
+
* (`no such column: bogus`, `table t has no column named label`)
|
|
688
|
+
* phrases a sub-object failure so that a missing-table phrase falls out
|
|
689
|
+
* of it, so there is nothing there to exclude. Adding their codes would
|
|
690
|
+
* be surface with no defect behind it.
|
|
691
|
+
*/
|
|
692
|
+
codes: /* @__PURE__ */ new Set([
|
|
693
|
+
"42703",
|
|
694
|
+
// undefined_column
|
|
695
|
+
"42704",
|
|
696
|
+
// undefined_object — constraint, trigger, role, type, …
|
|
697
|
+
"3D000"
|
|
698
|
+
// invalid_catalog_name — `database "x" does not exist`
|
|
699
|
+
]),
|
|
700
|
+
/**
|
|
701
|
+
* `«sub-object» "x" of relation "y" …` — Postgres' phrasing for a
|
|
702
|
+
* failure about something *inside* a relation, which therefore says the
|
|
703
|
+
* relation itself is present. The two in-repo siblings that carry this
|
|
704
|
+
* phrase are `mapDataError` (`packages/rest`, #5352) and
|
|
705
|
+
* `service-analytics`'s missing-column subtraction (#6035/PR #6346).
|
|
706
|
+
*
|
|
707
|
+
* [#6615] All three now read one home — `@objectstack/types` — instead
|
|
708
|
+
* of three hand-kept copies, so the phrase can no longer be taught to
|
|
709
|
+
* the repo a fourth time or drift in one package only. [#13279] This
|
|
710
|
+
* file now lives in that same home, so the read is a sibling import. The **width**
|
|
711
|
+
* difference that used to justify the copy is preserved and is the
|
|
712
|
+
* reason the home exports two functions rather than one: those two
|
|
713
|
+
* *extract* the column name to phrase a better error, so a miss costs a
|
|
714
|
+
* vaguer message; this one *excludes*, so a miss restores the
|
|
715
|
+
* corruption. {@link isRelationSubObjectPhrase} is therefore the wider
|
|
716
|
+
* question — it drops their `column`/`[a-z0-9_]+`/`does not exist`
|
|
717
|
+
* anchors: any sub-object, any quoted identifier, any verdict.
|
|
718
|
+
* Over-matching here only ever converts a benign verdict into a loud
|
|
719
|
+
* one, which is the direction this whole module already errs in.
|
|
720
|
+
*/
|
|
721
|
+
matchesMessage: isRelationSubObjectPhrase,
|
|
722
|
+
/**
|
|
723
|
+
* [#13324] "…and the relation it names is not the one you read."
|
|
724
|
+
*
|
|
725
|
+
* The sibling of the phrase above, reached one step further out. That
|
|
726
|
+
* one recognises a failure about something INSIDE a relation, which
|
|
727
|
+
* therefore says the relation is present; this one recognises a failure
|
|
728
|
+
* about a DIFFERENT relation, which says nothing at all about the one
|
|
729
|
+
* the caller read. Both end the question with `false` for the same
|
|
730
|
+
* reason: the licence this predicate grants — "there are no rows, so
|
|
731
|
+
* there is nothing to be inconsistent with" — is about the table that
|
|
732
|
+
* was READ, and neither phrase is evidence about it.
|
|
733
|
+
*/
|
|
734
|
+
namesAnotherRelation: phraseNamesAnotherRelation
|
|
735
|
+
}
|
|
736
|
+
};
|
|
737
|
+
var MAX_CAUSE_DEPTH2 = 4;
|
|
738
|
+
var DRIVER_TARGETED_TABLE = /* @__PURE__ */ Symbol.for("objectstack.driver.targetedTable");
|
|
739
|
+
function declareTargetedTable(error, table) {
|
|
740
|
+
if (typeof table !== "string" || table === "") return error;
|
|
741
|
+
if (targetedTableOf(error) !== null) return error;
|
|
742
|
+
Object.defineProperty(error, DRIVER_TARGETED_TABLE, { value: table, enumerable: false });
|
|
743
|
+
return error;
|
|
744
|
+
}
|
|
745
|
+
function targetedTableOf(error) {
|
|
746
|
+
if (error === null || typeof error !== "object" && typeof error !== "function") return null;
|
|
747
|
+
const table = error[DRIVER_TARGETED_TABLE];
|
|
748
|
+
return typeof table === "string" && table !== "" ? table : null;
|
|
749
|
+
}
|
|
750
|
+
function excludedByReadObject(message, signature, relation) {
|
|
751
|
+
if (typeof relation !== "string" || relation === "") return false;
|
|
752
|
+
return signature.excludes?.namesAnotherRelation?.(message, relation) === true;
|
|
753
|
+
}
|
|
754
|
+
function matchesDriverError(error, signature, depth, readObject) {
|
|
755
|
+
if (error === null || error === void 0 || depth > MAX_CAUSE_DEPTH2) return false;
|
|
756
|
+
if (typeof error === "string") {
|
|
757
|
+
if (signature.excludes?.matchesMessage(error)) return false;
|
|
758
|
+
if (excludedByReadObject(error, signature, readObject)) return false;
|
|
759
|
+
return signature.message.test(error);
|
|
760
|
+
}
|
|
761
|
+
if (typeof error !== "object") return false;
|
|
762
|
+
const err = error;
|
|
763
|
+
const relation = targetedTableOf(err) ?? readObject;
|
|
764
|
+
const excludes = signature.excludes;
|
|
765
|
+
if (excludes) {
|
|
766
|
+
if (typeof err.code === "string" && excludes.codes.has(err.code)) return false;
|
|
767
|
+
if (typeof err.message === "string" && excludes.matchesMessage(err.message)) return false;
|
|
768
|
+
if (typeof err.message === "string" && excludedByReadObject(err.message, signature, relation))
|
|
769
|
+
return false;
|
|
770
|
+
}
|
|
771
|
+
if (typeof err.code === "string" && signature.codes.has(err.code)) return true;
|
|
772
|
+
if (typeof err.errno === "number" && signature.errnos.has(err.errno)) return true;
|
|
773
|
+
if (typeof err.message === "string" && signature.message.test(err.message)) return true;
|
|
774
|
+
return matchesDriverError(err.cause, signature, depth + 1, relation);
|
|
775
|
+
}
|
|
776
|
+
function isSchemaAlreadyExistsError(error, depth = 0) {
|
|
777
|
+
return matchesDriverError(error, ALREADY_EXISTS, depth);
|
|
778
|
+
}
|
|
779
|
+
function isMissingTableError(error, readObject, depth = 0) {
|
|
780
|
+
return matchesDriverError(error, MISSING_TABLE, depth, readObject);
|
|
781
|
+
}
|
|
782
|
+
|
|
473
783
|
// src/unbacked-conflict-target.ts
|
|
474
784
|
var UNBACKED_CONFLICT_TARGET = {
|
|
475
785
|
message: /ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint|there is no unique or exclusion constraint matching the ON CONFLICT specification/i
|
|
476
786
|
};
|
|
477
|
-
var
|
|
787
|
+
var MAX_CAUSE_DEPTH3 = 4;
|
|
478
788
|
function isUnbackedConflictTargetError(error) {
|
|
479
789
|
return matchesUnbackedConflictTarget(error, 0);
|
|
480
790
|
}
|
|
481
791
|
function matchesUnbackedConflictTarget(error, depth) {
|
|
482
|
-
if (error === null || error === void 0 || depth >
|
|
792
|
+
if (error === null || error === void 0 || depth > MAX_CAUSE_DEPTH3) return false;
|
|
483
793
|
if (typeof error === "string") return UNBACKED_CONFLICT_TARGET.message.test(error);
|
|
484
794
|
if (typeof error !== "object") return false;
|
|
485
795
|
const err = error;
|
|
@@ -586,30 +896,40 @@ function postureGatesGlobalUniques(posture) {
|
|
|
586
896
|
}
|
|
587
897
|
// Annotate the CommonJS export names for ESM import in node:
|
|
588
898
|
0 && (module.exports = {
|
|
899
|
+
DRIVER_TARGETED_TABLE,
|
|
589
900
|
GLOBAL_UNIQUE_CONFIRMATION_REQUIRED,
|
|
590
901
|
GLOBAL_UNIQUE_ISOLATED_PRESCRIPTION,
|
|
591
902
|
INTERNAL_ERROR_MESSAGE,
|
|
903
|
+
PLATFORM_OWNER_EMAIL_ENV,
|
|
904
|
+
SERVER_FAULT_LOG_PREFIX,
|
|
592
905
|
VALIDATION_FAILED_STATUS,
|
|
593
906
|
_resetEnvDeprecationWarnings,
|
|
594
907
|
buildGlobalUniqueStopMessage,
|
|
595
908
|
collectConfiguredLocales,
|
|
596
909
|
collectGlobalUniques,
|
|
910
|
+
declareTargetedTable,
|
|
597
911
|
declaredIndexUniqueIsGlobal,
|
|
598
912
|
declaredUserMessage,
|
|
599
913
|
declaresServerFault,
|
|
600
914
|
demotedDeclaredCode,
|
|
915
|
+
describeFaultRequest,
|
|
601
916
|
describeGlobalUniqueFinding,
|
|
602
917
|
emitDegradedBootBanner,
|
|
603
918
|
fieldUniqueIsGlobal,
|
|
604
919
|
fieldsFromZodIssues,
|
|
605
920
|
globalUniqueFindingId,
|
|
921
|
+
isEmailVerifiedUserRow,
|
|
606
922
|
isMcpServerEnabled,
|
|
923
|
+
isMissingTableError,
|
|
607
924
|
isModuleNotFoundError,
|
|
608
925
|
isPlatformOwnedObject,
|
|
609
926
|
isRelationSubObjectPhrase,
|
|
927
|
+
isSchemaAlreadyExistsError,
|
|
928
|
+
isServerFault,
|
|
610
929
|
isUnbackedConflictTargetError,
|
|
611
930
|
isUniqueViolationError,
|
|
612
931
|
keysetWalk,
|
|
932
|
+
logServerFault,
|
|
613
933
|
looksLikeInternalErrorLeak,
|
|
614
934
|
matchMissingColumnOfRelation,
|
|
615
935
|
postureGatesGlobalUniques,
|
|
@@ -621,13 +941,21 @@ function postureGatesGlobalUniques(posture) {
|
|
|
621
941
|
resolveMcpStdioAutoStart,
|
|
622
942
|
resolveMultiOrgEnabled,
|
|
623
943
|
resolveOrgLimit,
|
|
944
|
+
resolveOrgMembershipLimit,
|
|
945
|
+
resolvePlatformOwnerEmail,
|
|
624
946
|
resolveSandboxTimeoutMs,
|
|
625
947
|
resolveSearchPinyinEnabled,
|
|
626
948
|
resolveTenancyPosture,
|
|
627
949
|
resolveThrownHttpError,
|
|
628
950
|
sendError,
|
|
629
951
|
sendOk,
|
|
952
|
+
serverFaultLogMessage,
|
|
953
|
+
serverFaultLogMeta,
|
|
954
|
+
serverFaultProvenance,
|
|
630
955
|
stampSearchPinyinEnabled,
|
|
956
|
+
strandedDecisionDetails,
|
|
957
|
+
strandedDecisionFailure,
|
|
958
|
+
targetedTableOf,
|
|
631
959
|
unconfirmedGlobalUniques,
|
|
632
960
|
uniqueViolationColumn,
|
|
633
961
|
validationFailure,
|