@objectstack/types 17.0.0-rc.5 → 17.0.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 +2293 -0
- package/dist/index.d.mts +429 -6
- package/dist/index.d.ts +429 -6
- package/dist/index.js +187 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +176 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -136,10 +136,25 @@ function _resetEnvDeprecationWarnings() {
|
|
|
136
136
|
|
|
137
137
|
// src/error-leak.ts
|
|
138
138
|
var INTERNAL_ERROR_MESSAGE = "Internal server error";
|
|
139
|
+
var DIALECT_LEAK_PHRASINGS = [
|
|
140
|
+
// Postgres 42P01 / 42703 (and, as a superstring, the `… of relation "…"`
|
|
141
|
+
// sub-object family: 42704 and friends). The quotes are required because
|
|
142
|
+
// Postgres always emits them here.
|
|
143
|
+
/\b(?:relation|column)\s+["'`][^"'`]+["'`]\s+does not exist/i,
|
|
144
|
+
// Postgres 42501. Restricted to physical object kinds: `schema`, `view`,
|
|
145
|
+
// `function` and `column` are all ObjectStack AUTHORING vocabulary, so a
|
|
146
|
+
// product message could legitimately use them and a miss is the cheap
|
|
147
|
+
// direction (the outcome is already a 5xx).
|
|
148
|
+
/\bpermission denied for (?:table|relation|sequence|database)\b/i,
|
|
149
|
+
// SQLite/libsql, message-only form. The `sqlite_` limb below catches these
|
|
150
|
+
// only when the driver prefixed its code; `better-sqlite3` and libsql both
|
|
151
|
+
// raise them bare, which is the shape measured across this repo.
|
|
152
|
+
/\bno such (?:table|column):/i
|
|
153
|
+
];
|
|
139
154
|
function looksLikeInternalErrorLeak(message) {
|
|
140
155
|
if (!message) return false;
|
|
141
156
|
const lower = String(message).toLowerCase();
|
|
142
|
-
return lower.includes("sqlite_") || lower.includes("sqlstate") || lower.startsWith("insert into ") || lower.startsWith("update ") || lower.startsWith("select ") || lower.startsWith("delete from ") || lower.includes("constraint failed") || lower.includes("unique constraint") || lower.includes("foreign key");
|
|
157
|
+
return lower.includes("sqlite_") || lower.includes("sqlstate") || lower.startsWith("insert into ") || lower.startsWith("update ") || lower.startsWith("select ") || lower.startsWith("delete from ") || lower.includes("constraint failed") || lower.includes("unique constraint") || lower.includes("foreign key") || DIALECT_LEAK_PHRASINGS.some((pattern) => pattern.test(lower));
|
|
143
158
|
}
|
|
144
159
|
function declaresServerFault(err) {
|
|
145
160
|
if (typeof err !== "object" || err === null) return false;
|
|
@@ -224,6 +239,155 @@ function sendError(res, status, code, message, extra) {
|
|
|
224
239
|
res.status(status).json({ success: false, error: { code, message, ...extra } });
|
|
225
240
|
}
|
|
226
241
|
|
|
242
|
+
// src/thrown-http-error.ts
|
|
243
|
+
import { ErrorCode, standardErrorCodeForHttpStatus } from "@objectstack/spec/api";
|
|
244
|
+
|
|
245
|
+
// src/validation-failure.ts
|
|
246
|
+
import { zodIssuesToFields } from "@objectstack/spec/api";
|
|
247
|
+
var VALIDATION_FAILED_STATUS = 400;
|
|
248
|
+
function validationFailureDetails(err) {
|
|
249
|
+
if (!err) return void 0;
|
|
250
|
+
if (err.code !== "VALIDATION_FAILED" && err.name !== "ValidationError") return void 0;
|
|
251
|
+
return {
|
|
252
|
+
code: "VALIDATION_FAILED",
|
|
253
|
+
fields: Array.isArray(err.fields) ? err.fields : []
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function validationFailure(message, fields) {
|
|
257
|
+
const err = new Error(message);
|
|
258
|
+
err.name = "ValidationError";
|
|
259
|
+
err.code = "VALIDATION_FAILED";
|
|
260
|
+
err.fields = fields;
|
|
261
|
+
return err;
|
|
262
|
+
}
|
|
263
|
+
function fieldsFromZodIssues(issues, ...input) {
|
|
264
|
+
return zodIssuesToFields(issues, ...input).map(
|
|
265
|
+
(entry) => entry.field === "" ? { ...entry, field: "(body)" } : entry
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// src/thrown-http-error.ts
|
|
270
|
+
function resolveThrownHttpError(error, fallbackStatus = 500) {
|
|
271
|
+
const e = error;
|
|
272
|
+
const validation = validationFailureDetails(e);
|
|
273
|
+
const declaredStatus = typeof e?.status === "number" ? e.status : typeof e?.statusCode === "number" ? e.statusCode : validation ? VALIDATION_FAILED_STATUS : void 0;
|
|
274
|
+
const status = declaredStatus ?? fallbackStatus;
|
|
275
|
+
const spelled = typeof e?.code === "string" && e.code !== "" ? e.code : void 0;
|
|
276
|
+
const registered = spelled !== void 0 && ErrorCode.safeParse(spelled).success ? spelled : void 0;
|
|
277
|
+
const code = validation ? validation.code : registered ?? standardErrorCodeForHttpStatus(status);
|
|
278
|
+
const declaredCode = validation ? validation.code : spelled;
|
|
279
|
+
const issues = Array.isArray(e?.issues) ? e.issues : void 0;
|
|
280
|
+
const details = {
|
|
281
|
+
// A truthy NON-string `code` (a driver errno, say) is context and stays
|
|
282
|
+
// context — promoting it would put a number in the field callers branch on,
|
|
283
|
+
// which is the drift #3842 removed.
|
|
284
|
+
...!validation && e?.code && typeof e.code !== "string" ? { code: e.code } : {},
|
|
285
|
+
...issues ? { issues } : {},
|
|
286
|
+
...validation ? { fields: validation.fields } : {}
|
|
287
|
+
};
|
|
288
|
+
return {
|
|
289
|
+
status,
|
|
290
|
+
...declaredStatus !== void 0 ? { declaredStatus } : {},
|
|
291
|
+
code,
|
|
292
|
+
...declaredCode !== void 0 ? { declaredCode } : {},
|
|
293
|
+
message: typeof e?.message === "string" ? e.message : String(error),
|
|
294
|
+
...Object.keys(details).length > 0 ? { details } : {}
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// src/relation-sub-object.ts
|
|
299
|
+
function matchMissingColumnOfRelation(message) {
|
|
300
|
+
return MISSING_COLUMN_OF_RELATION.exec(message)?.[1];
|
|
301
|
+
}
|
|
302
|
+
function isRelationSubObjectPhrase(message) {
|
|
303
|
+
return RELATION_SUB_OBJECT.test(message);
|
|
304
|
+
}
|
|
305
|
+
var MISSING_COLUMN_OF_RELATION = /column\s+["'`]([a-z0-9_]+)["'`]\s+of relation\s+\S+\s+does not exist/i;
|
|
306
|
+
var RELATION_SUB_OBJECT = /["'`][^"'`]+["'`]\s+of relation\s/i;
|
|
307
|
+
|
|
308
|
+
// src/unique-violation.ts
|
|
309
|
+
var UNIQUE_VIOLATION = {
|
|
310
|
+
codes: /* @__PURE__ */ new Set(["23505", "ER_DUP_ENTRY", "SQLITE_CONSTRAINT_UNIQUE"]),
|
|
311
|
+
errnos: /* @__PURE__ */ new Set([1062]),
|
|
312
|
+
message: /unique constraint|unique violation|duplicate key|duplicate entry/i
|
|
313
|
+
};
|
|
314
|
+
var MAX_CAUSE_DEPTH = 4;
|
|
315
|
+
function isUniqueViolationError(error) {
|
|
316
|
+
return matchesUniqueViolation(error, 0);
|
|
317
|
+
}
|
|
318
|
+
function matchesUniqueViolation(error, depth) {
|
|
319
|
+
if (error === null || error === void 0 || depth > MAX_CAUSE_DEPTH) return false;
|
|
320
|
+
if (typeof error === "string") return UNIQUE_VIOLATION.message.test(error);
|
|
321
|
+
if (typeof error !== "object") return false;
|
|
322
|
+
const err = error;
|
|
323
|
+
if (typeof err.code === "string" && UNIQUE_VIOLATION.codes.has(err.code)) return true;
|
|
324
|
+
if (typeof err.code === "number" && UNIQUE_VIOLATION.errnos.has(err.code)) return true;
|
|
325
|
+
if (typeof err.errno === "number" && UNIQUE_VIOLATION.errnos.has(err.errno)) return true;
|
|
326
|
+
if (typeof err.message === "string" && UNIQUE_VIOLATION.message.test(err.message)) return true;
|
|
327
|
+
return matchesUniqueViolation(err.cause, depth + 1);
|
|
328
|
+
}
|
|
329
|
+
var SQLITE_TARGETS = /unique constraint failed:\s*([^\n]*)/i;
|
|
330
|
+
var POSTGRES_DETAIL_TARGETS = /\bkey \(([^)]+)\)=\(/i;
|
|
331
|
+
var SQLITE_INDEX_FORM = /^index\b/i;
|
|
332
|
+
var PLAIN_IDENTIFIER = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
333
|
+
function bareIdentifier(raw) {
|
|
334
|
+
const stripped = raw.trim().replace(/[`"'[\]]/g, "");
|
|
335
|
+
const dot = stripped.lastIndexOf(".");
|
|
336
|
+
return dot >= 0 ? stripped.slice(dot + 1) : stripped;
|
|
337
|
+
}
|
|
338
|
+
function soleColumn(targets) {
|
|
339
|
+
const names = targets.split(",").map(bareIdentifier);
|
|
340
|
+
if (names.length !== 1) return void 0;
|
|
341
|
+
const [name] = names;
|
|
342
|
+
return PLAIN_IDENTIFIER.test(name) ? name : void 0;
|
|
343
|
+
}
|
|
344
|
+
function columnFromText(text) {
|
|
345
|
+
const sqlite = SQLITE_TARGETS.exec(text);
|
|
346
|
+
if (sqlite) {
|
|
347
|
+
const targets = sqlite[1].trim();
|
|
348
|
+
return SQLITE_INDEX_FORM.test(targets) ? void 0 : soleColumn(targets);
|
|
349
|
+
}
|
|
350
|
+
const postgres = POSTGRES_DETAIL_TARGETS.exec(text);
|
|
351
|
+
if (postgres) return soleColumn(postgres[1]);
|
|
352
|
+
return void 0;
|
|
353
|
+
}
|
|
354
|
+
function findUniqueViolationColumn(error, depth) {
|
|
355
|
+
if (error === null || error === void 0 || depth > MAX_CAUSE_DEPTH) return void 0;
|
|
356
|
+
if (typeof error === "string") return columnFromText(error);
|
|
357
|
+
if (typeof error !== "object") return void 0;
|
|
358
|
+
const err = error;
|
|
359
|
+
if (typeof err.message === "string") {
|
|
360
|
+
const fromMessage = columnFromText(err.message);
|
|
361
|
+
if (fromMessage !== void 0) return fromMessage;
|
|
362
|
+
}
|
|
363
|
+
if (typeof err.detail === "string") {
|
|
364
|
+
const fromDetail = columnFromText(err.detail);
|
|
365
|
+
if (fromDetail !== void 0) return fromDetail;
|
|
366
|
+
}
|
|
367
|
+
return findUniqueViolationColumn(err.cause, depth + 1);
|
|
368
|
+
}
|
|
369
|
+
function uniqueViolationColumn(error) {
|
|
370
|
+
if (!isUniqueViolationError(error)) return void 0;
|
|
371
|
+
return findUniqueViolationColumn(error, 0);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// src/unbacked-conflict-target.ts
|
|
375
|
+
var UNBACKED_CONFLICT_TARGET = {
|
|
376
|
+
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
|
|
377
|
+
};
|
|
378
|
+
var MAX_CAUSE_DEPTH2 = 4;
|
|
379
|
+
function isUnbackedConflictTargetError(error) {
|
|
380
|
+
return matchesUnbackedConflictTarget(error, 0);
|
|
381
|
+
}
|
|
382
|
+
function matchesUnbackedConflictTarget(error, depth) {
|
|
383
|
+
if (error === null || error === void 0 || depth > MAX_CAUSE_DEPTH2) return false;
|
|
384
|
+
if (typeof error === "string") return UNBACKED_CONFLICT_TARGET.message.test(error);
|
|
385
|
+
if (typeof error !== "object") return false;
|
|
386
|
+
const err = error;
|
|
387
|
+
if (typeof err.message === "string" && UNBACKED_CONFLICT_TARGET.message.test(err.message)) return true;
|
|
388
|
+
return matchesUnbackedConflictTarget(err.cause, depth + 1);
|
|
389
|
+
}
|
|
390
|
+
|
|
227
391
|
// src/unique-scope-install-gate.ts
|
|
228
392
|
import { normalizeTenancyPosture as normalizeTenancyPosture2 } from "@objectstack/spec/security";
|
|
229
393
|
var SYS_OBJECT_PREFIXES = ["sys_", "base_"];
|
|
@@ -325,6 +489,7 @@ export {
|
|
|
325
489
|
GLOBAL_UNIQUE_CONFIRMATION_REQUIRED,
|
|
326
490
|
GLOBAL_UNIQUE_ISOLATED_PRESCRIPTION,
|
|
327
491
|
INTERNAL_ERROR_MESSAGE,
|
|
492
|
+
VALIDATION_FAILED_STATUS,
|
|
328
493
|
_resetEnvDeprecationWarnings,
|
|
329
494
|
buildGlobalUniqueStopMessage,
|
|
330
495
|
collectConfiguredLocales,
|
|
@@ -334,12 +499,17 @@ export {
|
|
|
334
499
|
describeGlobalUniqueFinding,
|
|
335
500
|
emitDegradedBootBanner,
|
|
336
501
|
fieldUniqueIsGlobal,
|
|
502
|
+
fieldsFromZodIssues,
|
|
337
503
|
globalUniqueFindingId,
|
|
338
504
|
isMcpServerEnabled,
|
|
339
505
|
isModuleNotFoundError,
|
|
340
506
|
isPlatformOwnedObject,
|
|
507
|
+
isRelationSubObjectPhrase,
|
|
508
|
+
isUnbackedConflictTargetError,
|
|
509
|
+
isUniqueViolationError,
|
|
341
510
|
keysetWalk,
|
|
342
511
|
looksLikeInternalErrorLeak,
|
|
512
|
+
matchMissingColumnOfRelation,
|
|
343
513
|
postureGatesGlobalUniques,
|
|
344
514
|
readEnvWithDeprecation,
|
|
345
515
|
recordGlobalUniqueAttestation,
|
|
@@ -352,9 +522,13 @@ export {
|
|
|
352
522
|
resolveSandboxTimeoutMs,
|
|
353
523
|
resolveSearchPinyinEnabled,
|
|
354
524
|
resolveTenancyPosture,
|
|
525
|
+
resolveThrownHttpError,
|
|
355
526
|
sendError,
|
|
356
527
|
sendOk,
|
|
357
528
|
stampSearchPinyinEnabled,
|
|
358
|
-
unconfirmedGlobalUniques
|
|
529
|
+
unconfirmedGlobalUniques,
|
|
530
|
+
uniqueViolationColumn,
|
|
531
|
+
validationFailure,
|
|
532
|
+
validationFailureDetails
|
|
359
533
|
};
|
|
360
534
|
//# sourceMappingURL=index.mjs.map
|