@vibeorm/schema 4.2.0 → 4.3.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.
@@ -6,6 +6,7 @@
6
6
  * runtime, migrate, generator and tooling share their identity.
7
7
  */
8
8
  import type { Dialect } from "./ir.ts";
9
+ import type { PredicateCapabilityTable, PredicateNumericType } from "./predicate.ts";
9
10
  /** Full-text engines the `search` extension can target. */
10
11
  export type FullTextEngine = "bm25" | "tsvector" | "fts5" | "fulltext";
11
12
  /**
@@ -40,6 +41,20 @@ export type AdvisoryLockMode = "exclusive" | "shared";
40
41
  */
41
42
  export type TimeOfDayType = "time" | "timetz";
42
43
  export type DialectCapabilities = {
44
+ /** Functional BTree keys on qualified engine versions, subject to scalar/storage admission. */
45
+ readonly expressionIndexes: boolean;
46
+ /** Core-owned stored generated columns. */
47
+ readonly generatedColumns: boolean;
48
+ /** Independent generated-expression normalization strategy. */
49
+ readonly generatedColumnNormalization: "rollback" | "temporary" | "sourceText";
50
+ /** Declared row UPDATE/DELETE prohibition. */
51
+ readonly rowRuleAppendOnly: boolean;
52
+ /** Declared explicit fixed-column groups. */
53
+ readonly rowRuleFixed: boolean;
54
+ /** Declared whole-row protection with explicit exceptions. */
55
+ readonly rowRuleRowFixed: boolean;
56
+ /** Declared creation- or field-activated whole-row protection. */
57
+ readonly rowRuleFrozen: boolean;
43
58
  /** Fixed PostgreSQL model/module placement and namespace ownership. */
44
59
  readonly fixedNamespaces: boolean;
45
60
  /** Precise exclusions for objects managed by another DDL owner. */
@@ -53,6 +68,10 @@ export type DialectCapabilities = {
53
68
  readonly checkNormalization: "rollback" | "temporary" | "sourceText";
54
69
  /** Typed JSON text, text length and fail-closed boolean expressions in CHECKs. */
55
70
  readonly schemaCheckExpressions: boolean;
71
+ /** Per-node admission; host availability is checked separately. */
72
+ readonly predicateExpressions: PredicateCapabilityTable;
73
+ /** Same-family arithmetic supported without implicit numeric promotion. */
74
+ readonly predicateArithmeticTypes: readonly PredicateNumericType[];
56
75
  /** Native database row policies; PGlite additionally needs a verified restricted role. */
57
76
  readonly nativeRowLevelSecurity: boolean;
58
77
  /** INSERT/UPDATE/DELETE ... RETURNING. False ⇒ insertId + re-select fallback. */
@@ -113,6 +132,8 @@ export type DialectCapabilities = {
113
132
  * when the schema is validated. Values are strings in JavaScript everywhere.
114
133
  */
115
134
  readonly uuidColumns: "native" | "text" | "unsupported";
135
+ /** String-backed Gregorian calendar days: native DATE, or TEXT with an owned CHECK on SQLite. */
136
+ readonly localDateColumns: boolean;
116
137
  };
117
138
  export declare const POSTGRES_CAPABILITIES: DialectCapabilities;
118
139
  export declare const SQLITE_CAPABILITIES: DialectCapabilities;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Check rules — the common row rules a schema author declares by NAME
3
+ * (`.nonNegative()`, `allOrNone`, a presence table) instead of writing the
4
+ * boolean formula out by hand.
5
+ *
6
+ * DATA only, like `predicate.ts`: each rule expands into ONE `PredicateIR`,
7
+ * which the ordinary renderer (`renderPredicate` in @vibeorm/sql) turns into
8
+ * the CHECK body. Nothing here knows a dialect or a model; the DSL resolves
9
+ * names, validates the rule against the model and then calls
10
+ * {@link checkRulePredicate}.
11
+ *
12
+ * The expansion forms are a stability contract. Migrations compare the
13
+ * rendered text, so changing a form re-creates every user's CHECK. The renderer
14
+ * catalog (`packages/sql/tests/catalog/predicate-cases.ts`) pins each one.
15
+ */
16
+ import type { PredicateComparisonOp, PredicateIR } from "./predicate.ts";
17
+ /** A literal a rule compares against. BigInt and Decimal values travel as exact decimal text. */
18
+ export type CheckRuleLiteral = string | number | boolean;
19
+ /** The column-group rules: which optional columns may be set together. */
20
+ export type CheckRuleGroupKind = "allOrNone" | "exactlyOne" | "atMostOne" | "anySet";
21
+ /**
22
+ * One check rule over LOGICAL field names.
23
+ *
24
+ * - `compare`: `field <op> value` (`nonNegative` is `gte 0`, `positive` is `gt 0`).
25
+ * - `range`: `field >= min AND field <= max`.
26
+ * - `oneOf`: `field IN (values)`.
27
+ * - `lengthAtMost`: `length(field) <= max` (PostgreSQL/PGlite CHECKs only).
28
+ * - `order`: `left <op> right`, two columns.
29
+ * - `allOrNone` / `exactlyOne` / `atMostOne` / `anySet`: how many of a column group are set.
30
+ * - `presence`: whether `field` is set while the enum column `by` holds a member —
31
+ * NOT NULL for the `set` members, NULL for the `unset` members, free otherwise.
32
+ */
33
+ export type CheckRule = {
34
+ readonly kind: "compare";
35
+ readonly field: string;
36
+ readonly op: PredicateComparisonOp;
37
+ readonly value: CheckRuleLiteral;
38
+ } | {
39
+ readonly kind: "range";
40
+ readonly field: string;
41
+ readonly min: CheckRuleLiteral;
42
+ readonly max: CheckRuleLiteral;
43
+ } | {
44
+ readonly kind: "oneOf";
45
+ readonly field: string;
46
+ readonly values: readonly CheckRuleLiteral[];
47
+ } | {
48
+ readonly kind: "lengthAtMost";
49
+ readonly field: string;
50
+ readonly max: number;
51
+ } | {
52
+ readonly kind: "order";
53
+ readonly left: string;
54
+ readonly op: "gt" | "gte" | "lt" | "lte";
55
+ readonly right: string;
56
+ } | {
57
+ readonly kind: CheckRuleGroupKind;
58
+ readonly fields: readonly string[];
59
+ } | {
60
+ readonly kind: "presence";
61
+ readonly by: string;
62
+ readonly field: string;
63
+ readonly set: readonly string[];
64
+ readonly unset: readonly string[];
65
+ };
66
+ /** The most columns a group rule takes: `exactlyOne` and `atMostOne` grow with the square of the count. */
67
+ export declare const CHECK_RULE_GROUP_MAX: 8;
68
+ /**
69
+ * Expand one rule into the predicate its CHECK holds.
70
+ *
71
+ * The forms, exactly as the renderer prints them. AND binds tighter than OR,
72
+ * so the renderer adds no parentheses around AND terms; the renderer catalog
73
+ * pins every form, and that text is frozen once released.
74
+ * - `allOrNone(a, b)`: `a IS NULL AND b IS NULL OR a IS NOT NULL AND b IS NOT NULL`.
75
+ * - `exactlyOne(a, b)`: one AND term per column — that column set, the others
76
+ * empty, in declaration order — joined by OR.
77
+ * - `atMostOne(a, b)`: the `exactlyOne` terms, then the all-empty term.
78
+ * - `anySet(a, b)`: `a IS NOT NULL OR b IS NOT NULL`.
79
+ * - `presence`: `(by NOT IN (set) OR col IS NOT NULL) AND (by NOT IN (unset) OR col IS NULL)`.
80
+ * An empty half is left out, and a lone half prints without parentheses;
81
+ * one member prints as `by <> member`. It never names a free member, so
82
+ * adding an enum member as free changes no CHECK text — PostgreSQL cannot
83
+ * use a new enum member in the transaction that adds it.
84
+ *
85
+ * @throws VibeError `VIBE_SCHEMA_INVALID` for a structurally impossible rule
86
+ * (a group of fewer than two or repeated columns, a presence rule with no
87
+ * members, an empty `oneOf`).
88
+ */
89
+ export declare function checkRulePredicate(params: {
90
+ rule: CheckRule;
91
+ }): PredicateIR;
92
+ //# sourceMappingURL=check-rules.d.ts.map
@@ -0,0 +1,39 @@
1
+ import type { Dialect, SchemaIR } from "./ir.ts";
2
+ /** A database-owned stored value; expression bytes are trusted physical SQL. */
3
+ export type GeneratedColumnIR = {
4
+ readonly expression: string;
5
+ readonly storage: "stored";
6
+ };
7
+ /** Raw SQL authoring declaration; virtual storage is deliberately not exposed. */
8
+ export type GeneratedColumnOptions = {
9
+ readonly sql: string;
10
+ };
11
+ /** One invalid generation declaration or incompatible field use. */
12
+ export type GeneratedColumnValidationIssue = {
13
+ readonly rule: string;
14
+ readonly message: string;
15
+ readonly model?: string;
16
+ readonly field?: string;
17
+ };
18
+ /** Inspect canonical shape without running getters or rewriting SQL. */
19
+ export declare function generatedColumnShapeIssue(params: {
20
+ readonly value: unknown;
21
+ }): string | undefined;
22
+ /** Validate, copy and freeze the canonical declaration. */
23
+ export declare function assertGeneratedColumn(params: {
24
+ readonly value: unknown;
25
+ }): GeneratedColumnIR;
26
+ /** Validate the single-key DSL declaration and lower it to canonical stored generation. */
27
+ export declare function generatedColumnFromSql(params: {
28
+ readonly value: unknown;
29
+ }): GeneratedColumnIR;
30
+ /** Collect all structural conflicts after complete model metadata is available. */
31
+ export declare function validateGeneratedColumns(params: {
32
+ readonly schema: SchemaIR;
33
+ }): readonly GeneratedColumnValidationIssue[];
34
+ /** Refuse invalid or unsupported generation before generating clients or migrations. */
35
+ export declare function assertGeneratedColumns(params: {
36
+ readonly schema: SchemaIR;
37
+ readonly dialect?: Dialect;
38
+ }): void;
39
+ //# sourceMappingURL=generated-columns.d.ts.map
@@ -0,0 +1,73 @@
1
+ import type { Dialect, IndexIR, IndexKeyTermIR, ModelIR, SchemaIR } from "./ir.ts";
2
+ /** An invalid functional-key declaration, reported without evaluating executable data. */
3
+ export type IndexExpressionValidationIssue = {
4
+ readonly rule: string;
5
+ readonly message: string;
6
+ readonly model: string;
7
+ readonly feature?: string;
8
+ };
9
+ /** Presence is decisive: a malformed empty expression list is not a plain unique. */
10
+ export declare function isExpressionIndex(params: {
11
+ readonly index: Pick<IndexIR, "expressions">;
12
+ }): boolean;
13
+ /** Resolve the complete ordered key without mutating the legacy named-field representation. */
14
+ export declare function indexKeyTerms(params: {
15
+ readonly index: Pick<IndexIR, "fields" | "expressions">;
16
+ }): readonly IndexKeyTermIR[];
17
+ /** Exact first-seen logical dependencies; undefined means opaque raw SQL, not no dependencies. */
18
+ export declare function indexKeyFieldNames(params: {
19
+ readonly index: Pick<IndexIR, "fields" | "expressions">;
20
+ }): readonly string[] | undefined;
21
+ /** Ordered scalar structure/carriers, direction, predicate and flags, without rendering SQL. */
22
+ export declare function indexKeyDefinitionKey(params: {
23
+ readonly index: IndexIR;
24
+ readonly model?: Pick<ModelIR, "name" | "fields">;
25
+ }): string;
26
+ /** Conservative utf8mb4 bounds of a modern InnoDB functional key; schema admission and SQL rendering share this one table. */
27
+ export declare const MYSQL_FUNCTIONAL_KEY_LIMITS: {
28
+ readonly bytes: number;
29
+ readonly bytesPerCharacter: number;
30
+ readonly defaultStringLength: number;
31
+ readonly arithmeticBytes: number;
32
+ readonly intBytes: number;
33
+ readonly wideBytes: number;
34
+ readonly decimalBytes: number;
35
+ readonly enumBytes: number;
36
+ readonly booleanBytes: number;
37
+ };
38
+ /** Complete MySQL key width, the first storage refusal, or `raw` when trusted SQL makes the width unknowable. */
39
+ export type MysqlIndexKeyWidth = {
40
+ readonly kind: "bytes";
41
+ readonly bytes: number;
42
+ } | {
43
+ readonly kind: "raw";
44
+ } | {
45
+ readonly kind: "refused";
46
+ readonly field: string;
47
+ readonly feature: string;
48
+ };
49
+ /** The one MySQL expression-key storage rule; `generate` and migration planning both call it. */
50
+ export declare function mysqlIndexKeyWidth(params: {
51
+ readonly terms: readonly IndexKeyTermIR[];
52
+ readonly model: Pick<ModelIR, "fields">;
53
+ }): MysqlIndexKeyWidth;
54
+ /** Collect expression-only shape/type/usage issues, leaving plain schemas unchanged. */
55
+ export declare function validateIndexExpressions(params: {
56
+ readonly schema: SchemaIR;
57
+ readonly dialect: Dialect;
58
+ }): readonly IndexExpressionValidationIssue[];
59
+ /** Refuse untrusted shape, non-scalar operands and unsupported keys before SQL or client generation. */
60
+ export declare function assertIndexExpressions(params: {
61
+ readonly schema: SchemaIR;
62
+ readonly dialect: Dialect;
63
+ }): void;
64
+ /** Shared DSL source for complete keys; scalar data and raw SQL are never executed by the printer. */
65
+ export declare function indexKeyDsl(params: {
66
+ readonly term: IndexKeyTermIR;
67
+ readonly model: Pick<ModelIR, "name" | "fields">;
68
+ }): string;
69
+ /** Canonical VibeORM extended Prisma source; raw SQL retains its exact bytes. */
70
+ export declare function indexKeyPrisma(params: {
71
+ readonly term: IndexKeyTermIR;
72
+ }): string;
73
+ //# sourceMappingURL=index-expressions.d.ts.map
package/dist/index.d.ts CHANGED
@@ -5,18 +5,28 @@
5
5
  export { SQL_NAMESPACES, assertSqlNamespace, qualifiedSqlName, sqlNamespaceIssue } from "./namespaces.ts";
6
6
  export { assertNativeRlsAdmission } from "./native-rls-admission.ts";
7
7
  export { modelSqlNamespace } from "./model-sql-namespace.ts";
8
+ export type { RowRuleIR, RowRuleWhenIR, RowRuleSpec, RowRuleCapability, RowRuleIdentities, RowRuleObject, RowRuleEvent, RowRuleValidationIssue } from "./row-rules.ts";
9
+ export { MYSQL_ROW_RULE_MESSAGE_MAX_BYTES, mysqlRowRuleMessageByteLength, SQLITE_ROW_RULE_ERROR_PREFIX, sqliteRowRuleConstraint, rowRuleTriggerName, assertRowRuleReferentialActions, assertRowRuleCapability, assertRowRuleEquality, defaultRowRuleName, normalizeRowRules, rowRuleCapability, rowRuleGateField, rowRuleGeneratedFields, rowRuleIdentities, rowRuleObjectNames, rowRulePrismaAttribute, rowRuleProtectedFields, rowRuleShapeIssue, schemaRowRuleIdentities, validateRowRules } from "./row-rules.ts";
8
10
  export { assertIndexOperatorClasses } from "./index-operator-classes.ts";
11
+ export { MYSQL_FUNCTIONAL_KEY_LIMITS, assertIndexExpressions, indexKeyDefinitionKey, indexKeyDsl, indexKeyFieldNames, indexKeyPrisma, indexKeyTerms, isExpressionIndex, mysqlIndexKeyWidth, validateIndexExpressions } from "./index-expressions.ts";
12
+ export type { IndexExpressionValidationIssue, MysqlIndexKeyWidth } from "./index-expressions.ts";
13
+ export type { GeneratedColumnIR, GeneratedColumnOptions, GeneratedColumnValidationIssue } from "./generated-columns.ts";
14
+ export { assertGeneratedColumn, assertGeneratedColumns, generatedColumnFromSql, generatedColumnShapeIssue, validateGeneratedColumns } from "./generated-columns.ts";
9
15
  export type { DatabaseModuleOptions, DatabaseModuleManifest, DatabaseModuleArtifact } from "./database-module.ts";
10
16
  export { prepareDatabaseModuleSchema } from "./module-schema.ts";
11
17
  export type { ExclusionIR, ExclusionSpec, ExclusionKey, ExclusionEndpoint } from "./exclusion.ts";
12
18
  export { DIALECTS, ENUM_STORAGES, enumStorageOf, fieldTypeIdentity, isEnumType, providerToDialect } from "./ir.ts";
13
- export type { CascadeAction, DatasourceIR, DefaultValueIR, Dialect, EnumIR, EnumStorage, ExtensionDeclIR, FieldIR, FieldType, JsonSchemaRefIR, IndexFieldIR, CheckIR, IndexIR, IndexKind, ModelIR, Provider, RelationIR, RelationType, ScalarType, SchemaIR, } from "./ir.ts";
14
- export { PREDICATE_COMPARISON_OPS, assertPredicateCapabilities, inspectPredicate, isPredicateFieldRef, predicateFieldNames, predicateKey } from "./predicate.ts";
15
- export type { PredicateComparisonOp, PredicateExpression, PredicateFieldRef, PredicateIR, PredicateOperand, PredicateValue } from "./predicate.ts";
19
+ export type { CascadeAction, DatasourceIR, DefaultValueIR, Dialect, EnumIR, EnumStorage, ExtensionDeclIR, FieldIR, FieldType, JsonSchemaRefIR, ValidatorRefIR, IndexFieldIR, IndexKeyTermIR, CheckIR, IndexIR, IndexKind, ModelIR, Provider, RelationIR, RelationType, ScalarType, SchemaIR, } from "./ir.ts";
20
+ export { PREDICATE_COMPARISON_OPS, assertPredicateCapabilities, inspectPredicate, inspectPredicateExpression, isPredicateFieldRef, predicateCapabilityIssue, predicateFieldNames, predicateKey } from "./predicate.ts";
21
+ export type { PredicateBooleanUsage, PredicateCapabilityInput, PredicateCapabilityIssue, PredicateCapabilityTable, PredicateComparisonOp, PredicateExpression, PredicateFieldRef, PredicateInspection, PredicateIR, PredicateNodeKind, PredicateNumericType, PredicateOperand, PredicateResultType, PredicateUsage, PredicateValue } from "./predicate.ts";
22
+ export { CHECK_RULE_GROUP_MAX, checkRulePredicate } from "./check-rules.ts";
23
+ export type { CheckRule, CheckRuleGroupKind, CheckRuleLiteral } from "./check-rules.ts";
24
+ export { resolveOnDelete, resolveOnUpdate, resolveReferentialActions } from "./referential-actions.ts";
16
25
  export { assertMigrationObjects, isSqlObjectDefinition, isSqlObjectIdentity, sqlObjectKey, sqlObjectNamespace } from "./migration-objects.ts";
17
26
  export type { MigrationObjectIR, QualifiedSqlName, SqlObjectDefinition, SqlObjectDefinitionFormat, SqlObjectFacts, SqlObjectIdentity } from "./migration-objects.ts";
18
27
  export type { AdvisoryLockMode, DialectCapabilities, FullTextEngine, RowLockStrength, RowLockWaitPolicy, TimeOfDayType, } from "./capabilities.ts";
19
28
  export { timeOfDayType } from "./time-of-day.ts";
29
+ export { isLocalDateField, isCanonicalLocalDate, localDateCheckName } from "./local-date.ts";
20
30
  export { READ_ONLY_REFUSAL_REASONS, ReadOnlyClientError, SCOPED_REFUSAL_REASONS, ScopedQueryError, VIBE_ERROR_CODES, VibeError, internalError, invalidStoredData, unsupportedCapability, } from "./errors.ts";
21
31
  export type { ReadOnlyRefusalReason, ScopedRefusalReason, VibeErrorCode } from "./errors.ts";
22
32
  export { decodePrismaString, encodePrismaString, exactDecimalLiteral, exactIntegerLiteral } from "./prisma-literal.ts";
@@ -29,7 +39,7 @@ export { RESERVED_ENUM_NAMES, assertValidSchemaIR, validateSchemaIR } from "./va
29
39
  export type { ValidationIssue } from "./validate.ts";
30
40
  export { implicitJoinTable } from "./m2m.ts";
31
41
  export type { ImplicitJoinTable } from "./m2m.ts";
32
- export { IDENTIFIER_LIMITS, assertIdentifierFits, defaultForeignKeyName, defaultIndexName, defaultPrimaryKeyName, fitDefaultName, identifierLength, implicitJoinTableObjectNames, postgresGeneratedObjectName, } from "./physical-names.ts";
42
+ export { IDENTIFIER_LIMITS, assertIdentifierFits, defaultForeignKeyName, defaultIndexName, defaultExpressionIndexName, defaultPrimaryKeyName, fitDefaultName, identifierLength, implicitJoinTableObjectNames, postgresGeneratedObjectName, } from "./physical-names.ts";
33
43
  export type { IdentifierLimit, ImplicitJoinTableObjectNames } from "./physical-names.ts";
34
44
  export type { NativeRlsIR, RlsContextFieldIR, RlsContextIR, RlsContextRefIR, RlsContextScalar, RlsPolicyIR } from "./ir.ts";
35
45
  export { DIALECT_CAPABILITIES, MYSQL_CAPABILITIES, POSTGRES_CAPABILITIES, SQLITE_CAPABILITIES } from "./capabilities.ts";
@@ -38,4 +48,5 @@ export type { RlsContextReason } from "./errors.ts";
38
48
  export { isImplicitManyToManyRelation, validateRlsContextIR } from "./validate.ts";
39
49
  export { scalarListDefault, serializeJsonDefault } from "./default-values.ts";
40
50
  export { assertJsonSchemaRef, hasJsonSchemaAnnotation, jsonSchemaRefIssue, jsonTypeAnnotationIssue, jsonTypeAnnotationRef, normalizeJsonSchemaRef } from "./json-schema-ref.ts";
51
+ export { assertValidatorRef, hasValidatorAnnotation, normalizeValidatorRef, validatorRefIssue } from "./validator-ref.ts";
41
52
  //# sourceMappingURL=index.d.ts.map