@vibeorm/schema 4.3.0 → 5.1.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/dist/capabilities.d.ts +16 -1
- package/dist/date-truncation.d.ts +37 -0
- package/dist/errors.d.ts +10 -2
- package/dist/index.d.ts +2 -0
- package/dist/index.js +47 -8
- package/dist/index.js.map +8 -7
- package/package.json +1 -1
package/dist/capabilities.d.ts
CHANGED
|
@@ -82,7 +82,7 @@ export type DialectCapabilities = {
|
|
|
82
82
|
readonly nativeEnums: boolean;
|
|
83
83
|
/** Native ILIKE operator. False ⇒ LOWER() LIKE LOWER() strategy. */
|
|
84
84
|
readonly ilike: boolean;
|
|
85
|
-
/** LATERAL JOIN relation strategy ("join") availability. */
|
|
85
|
+
/** LATERAL JOIN relation strategy ("join") availability (mysql: 8.0.14 or later, not MariaDB). */
|
|
86
86
|
readonly lateralJoin: boolean;
|
|
87
87
|
/** Native DISTINCT ON. */
|
|
88
88
|
readonly distinctOn: boolean;
|
|
@@ -90,6 +90,14 @@ export type DialectCapabilities = {
|
|
|
90
90
|
readonly partialIndexes: boolean;
|
|
91
91
|
/** Named-constraint conflict targets (`ON CONFLICT ON CONSTRAINT …`). */
|
|
92
92
|
readonly conflictTargetConstraint: boolean;
|
|
93
|
+
/**
|
|
94
|
+
* A guard on the conflict's update arm: `ON CONFLICT (…) DO UPDATE SET …
|
|
95
|
+
* WHERE <guard>` — the existing row is updated (and returned) only when the
|
|
96
|
+
* guard admits it, in the same atomic statement. Tenant-scoped (`$scoped`)
|
|
97
|
+
* and `$withPolicy` upserts use it; MySQL's `ON DUPLICATE KEY UPDATE` has no
|
|
98
|
+
* WHERE, so there they keep the transactional find-then-write path.
|
|
99
|
+
*/
|
|
100
|
+
readonly conflictUpdateWhere: boolean;
|
|
93
101
|
/** DDL participates in transactions (mysql auto-commits DDL). */
|
|
94
102
|
readonly transactionalDdl: boolean;
|
|
95
103
|
/** createManyAndReturn support (requires multi-row RETURNING). */
|
|
@@ -134,6 +142,13 @@ export type DialectCapabilities = {
|
|
|
134
142
|
readonly uuidColumns: "native" | "text" | "unsupported";
|
|
135
143
|
/** String-backed Gregorian calendar days: native DATE, or TEXT with an owned CHECK on SQLite. */
|
|
136
144
|
readonly localDateColumns: boolean;
|
|
145
|
+
/**
|
|
146
|
+
* Calendar truncation of a timestamp in a named time zone — the `groupBy`
|
|
147
|
+
* key `{ field, truncate, timeZone }` (PostgreSQL `date_trunc` with a zone,
|
|
148
|
+
* PostgreSQL 12 or later). Without it the key is refused when the query is
|
|
149
|
+
* built.
|
|
150
|
+
*/
|
|
151
|
+
readonly dateTruncation: boolean;
|
|
137
152
|
};
|
|
138
153
|
export declare const POSTGRES_CAPABILITIES: DialectCapabilities;
|
|
139
154
|
export declare const SQLITE_CAPABILITIES: DialectCapabilities;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Calendar truncation of a timestamp — the `groupBy` key form
|
|
3
|
+
* `{ field, truncate, timeZone }` (one group per hour, day, ISO week, month
|
|
4
|
+
* or year of a `DateTime` field, in a named time zone).
|
|
5
|
+
*
|
|
6
|
+
* ONE rule decides which fields can take it: the runtime's refusal, the
|
|
7
|
+
* renderer's expression and the generator's `by` type all call
|
|
8
|
+
* {@link dateTruncationStorage}, so they can never disagree.
|
|
9
|
+
*/
|
|
10
|
+
import type { FieldType } from "./ir.ts";
|
|
11
|
+
/** A calendar period a timestamp can be truncated to (PostgreSQL `date_trunc` units; `week` is the ISO week, starting on Monday). */
|
|
12
|
+
export type DateTruncationUnit = "hour" | "day" | "week" | "month" | "year";
|
|
13
|
+
/** Every {@link DateTruncationUnit}, in increasing length. */
|
|
14
|
+
export declare const DATE_TRUNCATION_UNITS: readonly DateTruncationUnit[];
|
|
15
|
+
/**
|
|
16
|
+
* How a truncatable field stores its value on PostgreSQL. `"timestamptz"`: an
|
|
17
|
+
* instant (the canonical `DateTime` mapping, `@db.Timestamptz(n)`).
|
|
18
|
+
* `"timestamp"`: a zone-less column (`@db.Timestamp(n)`), which by VibeORM's
|
|
19
|
+
* contract holds the UTC wall-clock of the instant on every postgres driver.
|
|
20
|
+
*/
|
|
21
|
+
export type DateTruncationStorage = "timestamptz" | "timestamp";
|
|
22
|
+
/**
|
|
23
|
+
* The storage form of a field a timestamp truncation can read, or `undefined`
|
|
24
|
+
* when the field cannot be truncated: not a `DateTime`, a list, an
|
|
25
|
+
* unsupported type, or a native type that is not a timestamp (`@db.Date`,
|
|
26
|
+
* `@db.Time`, `@db.Timetz`). A `DateTime` without a native type takes the
|
|
27
|
+
* canonical mapping, `timestamptz`.
|
|
28
|
+
*/
|
|
29
|
+
export declare function dateTruncationStorage(params: {
|
|
30
|
+
readonly field: {
|
|
31
|
+
readonly type: FieldType;
|
|
32
|
+
readonly nativeType?: string;
|
|
33
|
+
readonly isList: boolean;
|
|
34
|
+
readonly isUnsupported?: boolean;
|
|
35
|
+
};
|
|
36
|
+
}): DateTruncationStorage | undefined;
|
|
37
|
+
//# sourceMappingURL=date-truncation.d.ts.map
|
package/dist/errors.d.ts
CHANGED
|
@@ -126,8 +126,15 @@ export declare function internalError(params: {
|
|
|
126
126
|
message: string;
|
|
127
127
|
meta?: Record<string, unknown>;
|
|
128
128
|
}): VibeError;
|
|
129
|
-
/**
|
|
130
|
-
|
|
129
|
+
/**
|
|
130
|
+
* Stable lifecycle categories; metadata never includes identity values.
|
|
131
|
+
* `"null-claim"`: a key listed in `nativeRls.refuseNull` is bound to `null` and
|
|
132
|
+
* the operation reaches a model whose rule reads it (or runs raw SQL).
|
|
133
|
+
* `"context-switched"`: the handle's transaction is running a `tx.$inContext`
|
|
134
|
+
* switch under another identity; the handle (and every handle derived from it)
|
|
135
|
+
* is refused until the switch has restored its claims.
|
|
136
|
+
*/
|
|
137
|
+
export declare const RLS_CONTEXT_REASONS: readonly ["missing", "invalid", "expired", "conflicting", "null-claim", "context-switched"];
|
|
131
138
|
export type RlsContextReason = (typeof RLS_CONTEXT_REASONS)[number];
|
|
132
139
|
/** Native RLS binding/lifecycle failure, distinct from database permissions. */
|
|
133
140
|
export declare class RlsContextError extends VibeError {
|
|
@@ -135,6 +142,7 @@ export declare class RlsContextError extends VibeError {
|
|
|
135
142
|
constructor(params: {
|
|
136
143
|
reason: RlsContextReason;
|
|
137
144
|
key?: string;
|
|
145
|
+
model?: string;
|
|
138
146
|
});
|
|
139
147
|
}
|
|
140
148
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ export { assertMigrationObjects, isSqlObjectDefinition, isSqlObjectIdentity, sql
|
|
|
26
26
|
export type { MigrationObjectIR, QualifiedSqlName, SqlObjectDefinition, SqlObjectDefinitionFormat, SqlObjectFacts, SqlObjectIdentity } from "./migration-objects.ts";
|
|
27
27
|
export type { AdvisoryLockMode, DialectCapabilities, FullTextEngine, RowLockStrength, RowLockWaitPolicy, TimeOfDayType, } from "./capabilities.ts";
|
|
28
28
|
export { timeOfDayType } from "./time-of-day.ts";
|
|
29
|
+
export { DATE_TRUNCATION_UNITS, dateTruncationStorage } from "./date-truncation.ts";
|
|
30
|
+
export type { DateTruncationStorage, DateTruncationUnit } from "./date-truncation.ts";
|
|
29
31
|
export { isLocalDateField, isCanonicalLocalDate, localDateCheckName } from "./local-date.ts";
|
|
30
32
|
export { READ_ONLY_REFUSAL_REASONS, ReadOnlyClientError, SCOPED_REFUSAL_REASONS, ScopedQueryError, VIBE_ERROR_CODES, VibeError, internalError, invalidStoredData, unsupportedCapability, } from "./errors.ts";
|
|
31
33
|
export type { ReadOnlyRefusalReason, ScopedRefusalReason, VibeErrorCode } from "./errors.ts";
|
package/dist/index.js
CHANGED
|
@@ -70,7 +70,9 @@ var RLS_CONTEXT_REASONS = Object.freeze([
|
|
|
70
70
|
"missing",
|
|
71
71
|
"invalid",
|
|
72
72
|
"expired",
|
|
73
|
-
"conflicting"
|
|
73
|
+
"conflicting",
|
|
74
|
+
"null-claim",
|
|
75
|
+
"context-switched"
|
|
74
76
|
]);
|
|
75
77
|
|
|
76
78
|
class RlsContextError extends VibeError {
|
|
@@ -78,8 +80,8 @@ class RlsContextError extends VibeError {
|
|
|
78
80
|
constructor(params) {
|
|
79
81
|
super({
|
|
80
82
|
code: "VIBE_RLS_CONTEXT",
|
|
81
|
-
message: `Native RLS context is ${params.reason}${params.key === undefined ? "" : ` at key ${JSON.stringify(params.key)}`}`,
|
|
82
|
-
meta: { reason: params.reason, ...params.key === undefined ? {} : { key: params.key } }
|
|
83
|
+
message: params.reason === "null-claim" ? `Native RLS context key ${JSON.stringify(params.key)} is null and refused${params.model === undefined ? " for raw SQL" : ` for model ${JSON.stringify(params.model)}`}` : `Native RLS context is ${params.reason}${params.key === undefined ? "" : ` at key ${JSON.stringify(params.key)}`}`,
|
|
84
|
+
meta: { reason: params.reason, ...params.key === undefined ? {} : { key: params.key }, ...params.model === undefined ? {} : { model: params.model } }
|
|
83
85
|
});
|
|
84
86
|
this.name = "RlsContextError";
|
|
85
87
|
this.reason = params.reason;
|
|
@@ -230,6 +232,7 @@ var RESERVED_CLIENT_NAMES = [
|
|
|
230
232
|
"$executeRaw",
|
|
231
233
|
"$executeRawUnsafe",
|
|
232
234
|
"$on",
|
|
235
|
+
"$observe",
|
|
233
236
|
"$extends",
|
|
234
237
|
"$defineView",
|
|
235
238
|
"$withPolicy",
|
|
@@ -445,6 +448,7 @@ var POSTGRES_CAPABILITIES = Object.freeze({
|
|
|
445
448
|
distinctOn: true,
|
|
446
449
|
partialIndexes: true,
|
|
447
450
|
conflictTargetConstraint: true,
|
|
451
|
+
conflictUpdateWhere: true,
|
|
448
452
|
transactionalDdl: true,
|
|
449
453
|
createManyAndReturn: true,
|
|
450
454
|
jsonColumnType: true,
|
|
@@ -455,7 +459,8 @@ var POSTGRES_CAPABILITIES = Object.freeze({
|
|
|
455
459
|
advisoryLocks: true,
|
|
456
460
|
timeOfDayTypes: Object.freeze(["time", "timetz"]),
|
|
457
461
|
uuidColumns: "native",
|
|
458
|
-
localDateColumns: true
|
|
462
|
+
localDateColumns: true,
|
|
463
|
+
dateTruncation: true
|
|
459
464
|
});
|
|
460
465
|
var SQLITE_CAPABILITIES = Object.freeze({
|
|
461
466
|
rowRuleAppendOnly: true,
|
|
@@ -483,6 +488,7 @@ var SQLITE_CAPABILITIES = Object.freeze({
|
|
|
483
488
|
distinctOn: false,
|
|
484
489
|
partialIndexes: true,
|
|
485
490
|
conflictTargetConstraint: false,
|
|
491
|
+
conflictUpdateWhere: true,
|
|
486
492
|
transactionalDdl: true,
|
|
487
493
|
createManyAndReturn: true,
|
|
488
494
|
jsonColumnType: false,
|
|
@@ -493,7 +499,8 @@ var SQLITE_CAPABILITIES = Object.freeze({
|
|
|
493
499
|
advisoryLocks: false,
|
|
494
500
|
timeOfDayTypes: Object.freeze([]),
|
|
495
501
|
uuidColumns: "text",
|
|
496
|
-
localDateColumns: true
|
|
502
|
+
localDateColumns: true,
|
|
503
|
+
dateTruncation: false
|
|
497
504
|
});
|
|
498
505
|
var MYSQL_CAPABILITIES = Object.freeze({
|
|
499
506
|
rowRuleAppendOnly: true,
|
|
@@ -517,10 +524,11 @@ var MYSQL_CAPABILITIES = Object.freeze({
|
|
|
517
524
|
scalarArrays: false,
|
|
518
525
|
nativeEnums: true,
|
|
519
526
|
ilike: false,
|
|
520
|
-
lateralJoin:
|
|
527
|
+
lateralJoin: true,
|
|
521
528
|
distinctOn: false,
|
|
522
529
|
partialIndexes: false,
|
|
523
530
|
conflictTargetConstraint: false,
|
|
531
|
+
conflictUpdateWhere: false,
|
|
524
532
|
transactionalDdl: false,
|
|
525
533
|
createManyAndReturn: false,
|
|
526
534
|
jsonColumnType: true,
|
|
@@ -531,7 +539,8 @@ var MYSQL_CAPABILITIES = Object.freeze({
|
|
|
531
539
|
advisoryLocks: false,
|
|
532
540
|
timeOfDayTypes: Object.freeze(["time"]),
|
|
533
541
|
uuidColumns: "unsupported",
|
|
534
|
-
localDateColumns: true
|
|
542
|
+
localDateColumns: true,
|
|
543
|
+
dateTruncation: false
|
|
535
544
|
});
|
|
536
545
|
var DIALECT_CAPABILITIES = Object.freeze({
|
|
537
546
|
postgres: POSTGRES_CAPABILITIES,
|
|
@@ -2412,6 +2421,23 @@ function timeOfDayType(params) {
|
|
|
2412
2421
|
return "timetz";
|
|
2413
2422
|
return "time";
|
|
2414
2423
|
}
|
|
2424
|
+
// packages/schema/src/date-truncation.ts
|
|
2425
|
+
var DATE_TRUNCATION_UNITS = Object.freeze(["hour", "day", "week", "month", "year"]);
|
|
2426
|
+
var ZONED_NATIVE_TYPE = /^timestamptz(?:\(\d+\))?$|^timestamp(?:\(\d+\))?withtimezone$/;
|
|
2427
|
+
var ZONE_LESS_NATIVE_TYPE = /^timestamp(?:\(\d+\))?(?:withouttimezone)?$/;
|
|
2428
|
+
function dateTruncationStorage(params) {
|
|
2429
|
+
const { field } = params;
|
|
2430
|
+
if (field.type !== "DateTime" || field.isList || field.isUnsupported === true)
|
|
2431
|
+
return;
|
|
2432
|
+
if (field.nativeType === undefined)
|
|
2433
|
+
return "timestamptz";
|
|
2434
|
+
const native = field.nativeType.toLowerCase().replace(/\s+/g, "");
|
|
2435
|
+
if (ZONED_NATIVE_TYPE.test(native))
|
|
2436
|
+
return "timestamptz";
|
|
2437
|
+
if (ZONE_LESS_NATIVE_TYPE.test(native))
|
|
2438
|
+
return "timestamp";
|
|
2439
|
+
return;
|
|
2440
|
+
}
|
|
2415
2441
|
// packages/schema/src/computed.ts
|
|
2416
2442
|
function buildComputedManifest(params) {
|
|
2417
2443
|
const { computed } = params;
|
|
@@ -2776,6 +2802,8 @@ var RESERVED_ENUM_NAMES = [
|
|
|
2776
2802
|
"KeysetPage",
|
|
2777
2803
|
"KeysetOptions",
|
|
2778
2804
|
"RowLockRequest",
|
|
2805
|
+
"GroupByTruncateUnit",
|
|
2806
|
+
"GroupByKeyName",
|
|
2779
2807
|
"JsonValue",
|
|
2780
2808
|
"InputJsonValue",
|
|
2781
2809
|
"InputJsonArray",
|
|
@@ -2803,8 +2831,12 @@ var RESERVED_ENUM_NAMES = [
|
|
|
2803
2831
|
"ClientContext",
|
|
2804
2832
|
"QueryOperation",
|
|
2805
2833
|
"QueryEvent",
|
|
2834
|
+
"QueryObserver",
|
|
2835
|
+
"QueryObserverFailure",
|
|
2806
2836
|
"Skip",
|
|
2807
2837
|
"TransactionOptions",
|
|
2838
|
+
"CallbackTransactionOptions",
|
|
2839
|
+
"RawStatement",
|
|
2808
2840
|
"AdvisoryLockOptions",
|
|
2809
2841
|
"StatementDiagnosticsOptions",
|
|
2810
2842
|
"SchemaIR",
|
|
@@ -2867,6 +2899,7 @@ var GENERATED_TYPE_NAMES = {
|
|
|
2867
2899
|
"MaxAggregateOrderByInput",
|
|
2868
2900
|
"HavingInput",
|
|
2869
2901
|
"GroupByOrderByInput",
|
|
2902
|
+
"GroupByTruncatedKey",
|
|
2870
2903
|
"FindManyArgs",
|
|
2871
2904
|
"FindPageArgs",
|
|
2872
2905
|
"FindFirstArgs",
|
|
@@ -2998,7 +3031,11 @@ function validateGeneratedNames(params) {
|
|
|
2998
3031
|
owners.set("RlsContext", "native RLS client");
|
|
2999
3032
|
owners.set("BoundVibeClientInstance", "native RLS client");
|
|
3000
3033
|
owners.set("BoundVibeTransactionClientInstance", "native RLS client");
|
|
3034
|
+
owners.set("OperatorVibeClientInstance", "native RLS client");
|
|
3035
|
+
owners.set("OperatorVibeTransactionClientInstance", "native RLS client");
|
|
3001
3036
|
}
|
|
3037
|
+
if (schema.models.some((model) => model.policy !== undefined))
|
|
3038
|
+
owners.set("PolicyClientInstance", "policy client");
|
|
3002
3039
|
if (schema.models.some((model) => model.fields.some((field) => isLocalDateField({ field })))) {
|
|
3003
3040
|
for (const name of ["LocalDate", "LocalDateFilter", "LocalDateNullableFilter"])
|
|
3004
3041
|
owners.set(name, "local-date filters");
|
|
@@ -4362,6 +4399,7 @@ function validRlsForeignKey(params) {
|
|
|
4362
4399
|
}
|
|
4363
4400
|
export {
|
|
4364
4401
|
CHECK_RULE_GROUP_MAX,
|
|
4402
|
+
DATE_TRUNCATION_UNITS,
|
|
4365
4403
|
DIALECTS,
|
|
4366
4404
|
DIALECT_CAPABILITIES,
|
|
4367
4405
|
EMPTY_EXTENSION_REGISTRY,
|
|
@@ -4406,6 +4444,7 @@ export {
|
|
|
4406
4444
|
buildComputedManifest,
|
|
4407
4445
|
buildExtensionRegistry,
|
|
4408
4446
|
checkRulePredicate,
|
|
4447
|
+
dateTruncationStorage,
|
|
4409
4448
|
decodePrismaString,
|
|
4410
4449
|
defaultExpressionIndexName,
|
|
4411
4450
|
defaultForeignKeyName,
|
|
@@ -4496,4 +4535,4 @@ export {
|
|
|
4496
4535
|
validatorRefIssue
|
|
4497
4536
|
};
|
|
4498
4537
|
|
|
4499
|
-
//# debugId=
|
|
4538
|
+
//# debugId=92D7E56C6E6AF7A964756E2164756E21
|