@vibeorm/schema 5.0.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 +15 -0
- package/dist/date-truncation.d.ts +37 -0
- package/dist/errors.d.ts +4 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +38 -5
- package/dist/index.js.map +7 -6
- package/package.json +1 -1
package/dist/capabilities.d.ts
CHANGED
|
@@ -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
|
@@ -130,8 +130,11 @@ export declare function internalError(params: {
|
|
|
130
130
|
* Stable lifecycle categories; metadata never includes identity values.
|
|
131
131
|
* `"null-claim"`: a key listed in `nativeRls.refuseNull` is bound to `null` and
|
|
132
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.
|
|
133
136
|
*/
|
|
134
|
-
export declare const RLS_CONTEXT_REASONS: readonly ["missing", "invalid", "expired", "conflicting", "null-claim"];
|
|
137
|
+
export declare const RLS_CONTEXT_REASONS: readonly ["missing", "invalid", "expired", "conflicting", "null-claim", "context-switched"];
|
|
135
138
|
export type RlsContextReason = (typeof RLS_CONTEXT_REASONS)[number];
|
|
136
139
|
/** Native RLS binding/lifecycle failure, distinct from database permissions. */
|
|
137
140
|
export declare class RlsContextError extends VibeError {
|
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
|
@@ -71,7 +71,8 @@ var RLS_CONTEXT_REASONS = Object.freeze([
|
|
|
71
71
|
"invalid",
|
|
72
72
|
"expired",
|
|
73
73
|
"conflicting",
|
|
74
|
-
"null-claim"
|
|
74
|
+
"null-claim",
|
|
75
|
+
"context-switched"
|
|
75
76
|
]);
|
|
76
77
|
|
|
77
78
|
class RlsContextError extends VibeError {
|
|
@@ -447,6 +448,7 @@ var POSTGRES_CAPABILITIES = Object.freeze({
|
|
|
447
448
|
distinctOn: true,
|
|
448
449
|
partialIndexes: true,
|
|
449
450
|
conflictTargetConstraint: true,
|
|
451
|
+
conflictUpdateWhere: true,
|
|
450
452
|
transactionalDdl: true,
|
|
451
453
|
createManyAndReturn: true,
|
|
452
454
|
jsonColumnType: true,
|
|
@@ -457,7 +459,8 @@ var POSTGRES_CAPABILITIES = Object.freeze({
|
|
|
457
459
|
advisoryLocks: true,
|
|
458
460
|
timeOfDayTypes: Object.freeze(["time", "timetz"]),
|
|
459
461
|
uuidColumns: "native",
|
|
460
|
-
localDateColumns: true
|
|
462
|
+
localDateColumns: true,
|
|
463
|
+
dateTruncation: true
|
|
461
464
|
});
|
|
462
465
|
var SQLITE_CAPABILITIES = Object.freeze({
|
|
463
466
|
rowRuleAppendOnly: true,
|
|
@@ -485,6 +488,7 @@ var SQLITE_CAPABILITIES = Object.freeze({
|
|
|
485
488
|
distinctOn: false,
|
|
486
489
|
partialIndexes: true,
|
|
487
490
|
conflictTargetConstraint: false,
|
|
491
|
+
conflictUpdateWhere: true,
|
|
488
492
|
transactionalDdl: true,
|
|
489
493
|
createManyAndReturn: true,
|
|
490
494
|
jsonColumnType: false,
|
|
@@ -495,7 +499,8 @@ var SQLITE_CAPABILITIES = Object.freeze({
|
|
|
495
499
|
advisoryLocks: false,
|
|
496
500
|
timeOfDayTypes: Object.freeze([]),
|
|
497
501
|
uuidColumns: "text",
|
|
498
|
-
localDateColumns: true
|
|
502
|
+
localDateColumns: true,
|
|
503
|
+
dateTruncation: false
|
|
499
504
|
});
|
|
500
505
|
var MYSQL_CAPABILITIES = Object.freeze({
|
|
501
506
|
rowRuleAppendOnly: true,
|
|
@@ -523,6 +528,7 @@ var MYSQL_CAPABILITIES = Object.freeze({
|
|
|
523
528
|
distinctOn: false,
|
|
524
529
|
partialIndexes: false,
|
|
525
530
|
conflictTargetConstraint: false,
|
|
531
|
+
conflictUpdateWhere: false,
|
|
526
532
|
transactionalDdl: false,
|
|
527
533
|
createManyAndReturn: false,
|
|
528
534
|
jsonColumnType: true,
|
|
@@ -533,7 +539,8 @@ var MYSQL_CAPABILITIES = Object.freeze({
|
|
|
533
539
|
advisoryLocks: false,
|
|
534
540
|
timeOfDayTypes: Object.freeze(["time"]),
|
|
535
541
|
uuidColumns: "unsupported",
|
|
536
|
-
localDateColumns: true
|
|
542
|
+
localDateColumns: true,
|
|
543
|
+
dateTruncation: false
|
|
537
544
|
});
|
|
538
545
|
var DIALECT_CAPABILITIES = Object.freeze({
|
|
539
546
|
postgres: POSTGRES_CAPABILITIES,
|
|
@@ -2414,6 +2421,23 @@ function timeOfDayType(params) {
|
|
|
2414
2421
|
return "timetz";
|
|
2415
2422
|
return "time";
|
|
2416
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
|
+
}
|
|
2417
2441
|
// packages/schema/src/computed.ts
|
|
2418
2442
|
function buildComputedManifest(params) {
|
|
2419
2443
|
const { computed } = params;
|
|
@@ -2778,6 +2802,8 @@ var RESERVED_ENUM_NAMES = [
|
|
|
2778
2802
|
"KeysetPage",
|
|
2779
2803
|
"KeysetOptions",
|
|
2780
2804
|
"RowLockRequest",
|
|
2805
|
+
"GroupByTruncateUnit",
|
|
2806
|
+
"GroupByKeyName",
|
|
2781
2807
|
"JsonValue",
|
|
2782
2808
|
"InputJsonValue",
|
|
2783
2809
|
"InputJsonArray",
|
|
@@ -2810,6 +2836,7 @@ var RESERVED_ENUM_NAMES = [
|
|
|
2810
2836
|
"Skip",
|
|
2811
2837
|
"TransactionOptions",
|
|
2812
2838
|
"CallbackTransactionOptions",
|
|
2839
|
+
"RawStatement",
|
|
2813
2840
|
"AdvisoryLockOptions",
|
|
2814
2841
|
"StatementDiagnosticsOptions",
|
|
2815
2842
|
"SchemaIR",
|
|
@@ -2872,6 +2899,7 @@ var GENERATED_TYPE_NAMES = {
|
|
|
2872
2899
|
"MaxAggregateOrderByInput",
|
|
2873
2900
|
"HavingInput",
|
|
2874
2901
|
"GroupByOrderByInput",
|
|
2902
|
+
"GroupByTruncatedKey",
|
|
2875
2903
|
"FindManyArgs",
|
|
2876
2904
|
"FindPageArgs",
|
|
2877
2905
|
"FindFirstArgs",
|
|
@@ -3004,7 +3032,10 @@ function validateGeneratedNames(params) {
|
|
|
3004
3032
|
owners.set("BoundVibeClientInstance", "native RLS client");
|
|
3005
3033
|
owners.set("BoundVibeTransactionClientInstance", "native RLS client");
|
|
3006
3034
|
owners.set("OperatorVibeClientInstance", "native RLS client");
|
|
3035
|
+
owners.set("OperatorVibeTransactionClientInstance", "native RLS client");
|
|
3007
3036
|
}
|
|
3037
|
+
if (schema.models.some((model) => model.policy !== undefined))
|
|
3038
|
+
owners.set("PolicyClientInstance", "policy client");
|
|
3008
3039
|
if (schema.models.some((model) => model.fields.some((field) => isLocalDateField({ field })))) {
|
|
3009
3040
|
for (const name of ["LocalDate", "LocalDateFilter", "LocalDateNullableFilter"])
|
|
3010
3041
|
owners.set(name, "local-date filters");
|
|
@@ -4368,6 +4399,7 @@ function validRlsForeignKey(params) {
|
|
|
4368
4399
|
}
|
|
4369
4400
|
export {
|
|
4370
4401
|
CHECK_RULE_GROUP_MAX,
|
|
4402
|
+
DATE_TRUNCATION_UNITS,
|
|
4371
4403
|
DIALECTS,
|
|
4372
4404
|
DIALECT_CAPABILITIES,
|
|
4373
4405
|
EMPTY_EXTENSION_REGISTRY,
|
|
@@ -4412,6 +4444,7 @@ export {
|
|
|
4412
4444
|
buildComputedManifest,
|
|
4413
4445
|
buildExtensionRegistry,
|
|
4414
4446
|
checkRulePredicate,
|
|
4447
|
+
dateTruncationStorage,
|
|
4415
4448
|
decodePrismaString,
|
|
4416
4449
|
defaultExpressionIndexName,
|
|
4417
4450
|
defaultForeignKeyName,
|
|
@@ -4502,4 +4535,4 @@ export {
|
|
|
4502
4535
|
validatorRefIssue
|
|
4503
4536
|
};
|
|
4504
4537
|
|
|
4505
|
-
//# debugId=
|
|
4538
|
+
//# debugId=92D7E56C6E6AF7A964756E2164756E21
|