@atscript/db 0.1.154 → 0.1.155

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.
Files changed (33) hide show
  1. package/dist/agg.d.cts +1 -1
  2. package/dist/agg.d.mts +1 -1
  3. package/dist/{buckets-jy8BfswO.d.cts → buckets-DcWm3SLt.d.cts} +120 -10
  4. package/dist/{buckets-CBKL_ZWE.d.mts → buckets-goCoky8v.d.mts} +120 -10
  5. package/dist/{column-diff-DAIAq6XR.mjs → column-diff-C68V_eYM.mjs} +346 -65
  6. package/dist/{column-diff-qnzx1o3c.cjs → column-diff-DMkGYAGM.cjs} +357 -64
  7. package/dist/{fk-diff-BIJ8l_hF.d.mts → fk-diff-BYLNWoF9.d.mts} +2 -1
  8. package/dist/{fk-diff-D1mrLMjU.d.cts → fk-diff-DblOPBLS.d.cts} +2 -1
  9. package/dist/index.cjs +2 -2
  10. package/dist/index.d.cts +10 -5
  11. package/dist/index.d.mts +10 -5
  12. package/dist/index.mjs +2 -2
  13. package/dist/plugin.cjs +3 -3
  14. package/dist/plugin.mjs +3 -3
  15. package/dist/rel.d.cts +2 -2
  16. package/dist/rel.d.mts +2 -2
  17. package/dist/{relation-helpers-BUsxNNGU.d.mts → relation-helpers-B9MVBrtx.d.mts} +1 -1
  18. package/dist/{relation-helpers-D_8bydc2.d.cts → relation-helpers-D9kMFfum.d.cts} +1 -1
  19. package/dist/shared.cjs +2 -1
  20. package/dist/shared.d.cts +10 -3
  21. package/dist/shared.d.mts +10 -3
  22. package/dist/shared.mjs +2 -2
  23. package/dist/sync.cjs +288 -30
  24. package/dist/sync.d.cts +34 -5
  25. package/dist/sync.d.mts +34 -5
  26. package/dist/sync.mjs +288 -30
  27. package/dist/{validation-utils-DqZAH6aT.mjs → validation-utils-DxHIqa36.mjs} +23 -5
  28. package/dist/{validation-utils-debIYpq0.cjs → validation-utils-_PA7iSLm.cjs} +28 -4
  29. package/dist/{validator-BACewoRj.mjs → validator-BC3nwFi4.mjs} +178 -10
  30. package/dist/{validator-BxWwh3wf.cjs → validator-DHwSyBej.cjs} +201 -9
  31. package/dist/validator.cjs +1 -1
  32. package/dist/validator.mjs +1 -1
  33. package/package.json +6 -6
package/dist/agg.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- import { r as TResolvedBucket } from "./buckets-jy8BfswO.cjs";
1
+ import { r as TResolvedBucket } from "./buckets-DcWm3SLt.cjs";
2
2
  import { _ as TDbAggregateFn, a as AggregateResult, c as CalendarBucketLabel, d as WeekStart, f as isAggregateExpr, h as resolveAlias, i as AggregateQuery, l as ComputedExpr, m as resolveAggregateSearch, n as AggregateExpr, o as BucketExpr, p as isBucketExpr, r as AggregateFn, s as BucketUnit, t as AggregateControls, u as ResolvedBucket, v as assertAggregateFn } from "./agg-42CSpGDR.cjs";
3
3
  export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, type BucketExpr, type BucketUnit, type CalendarBucketLabel, type ComputedExpr, type ResolvedBucket, type TDbAggregateFn, type TResolvedBucket, type WeekStart, assertAggregateFn, isAggregateExpr, isBucketExpr, resolveAggregateSearch, resolveAlias };
package/dist/agg.d.mts CHANGED
@@ -1,3 +1,3 @@
1
- import { r as TResolvedBucket } from "./buckets-CBKL_ZWE.mjs";
1
+ import { r as TResolvedBucket } from "./buckets-goCoky8v.mjs";
2
2
  import { _ as TDbAggregateFn, a as AggregateResult, c as CalendarBucketLabel, d as WeekStart, f as isAggregateExpr, h as resolveAlias, i as AggregateQuery, l as ComputedExpr, m as resolveAggregateSearch, n as AggregateExpr, o as BucketExpr, p as isBucketExpr, r as AggregateFn, s as BucketUnit, t as AggregateControls, u as ResolvedBucket, v as assertAggregateFn } from "./agg-Wo-smrYV.mjs";
3
3
  export { type AggregateControls, type AggregateExpr, type AggregateFn, type AggregateQuery, type AggregateResult, type BucketExpr, type BucketUnit, type CalendarBucketLabel, type ComputedExpr, type ResolvedBucket, type TDbAggregateFn, type TResolvedBucket, type WeekStart, assertAggregateFn, isAggregateExpr, isBucketExpr, resolveAggregateSearch, resolveAlias };
@@ -594,7 +594,9 @@ type DbResponse<Data, Nav, Q> = [keyof Nav] extends [never] ? Data : string exte
594
594
  * otherwise trips up every adapter author.
595
595
  *
596
596
  * For union types (e.g., from flattened `{...} | {...}` objects):
597
- * - If all members resolve to the same type → returns that type (strong type)
597
+ * - `null` / `undefined` members are left out (since 0.1.155): `T | null`
598
+ * resolves to the design type of `T`
599
+ * - If all other members resolve to the same type → returns that type (strong type)
598
600
  * - If members disagree → returns `'union'` (out of scope for type management)
599
601
  */
600
602
  declare function resolveDesignType(fieldType: TAtscriptAnnotatedType): string;
@@ -1545,8 +1547,21 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
1545
1547
  * full row). Function defaults (`now` / `uuid` / `increment` / custom) the
1546
1548
  * adapter handles natively are NOT filled — the field stays absent so the
1547
1549
  * engine's own default applies. The version column is never touched.
1550
+ * A nested field (`audit.createdAt`) is filled inside its object, only when
1551
+ * that object is present (an absent or `null` embedded object stays so), and
1552
+ * in every object of an array on the way; a field inside a JSON value or an
1553
+ * array has no column default, so the SDK fills its function default too.
1548
1554
  */
1549
1555
  protected _applyDefaults(data: Record<string, unknown>): Record<string, unknown>;
1556
+ /** {@link _nestedDefaultFillable} per nested default path. */
1557
+ private _fillableDefaults?;
1558
+ /**
1559
+ * Whether every parent of the nested default `field` is one object type —
1560
+ * an object, `T | null` of one, or an array of one. Below a tuple or a
1561
+ * union of several types the default cannot be placed (the item it belongs
1562
+ * to is unknown), so it is not filled.
1563
+ */
1564
+ private _nestedDefaultFillable;
1550
1565
  /**
1551
1566
  * Parsed `@db.default 'literal'` values that are primitives — reused for
1552
1567
  * every row (an object / array default is parsed per row: each row gets
@@ -2878,6 +2893,24 @@ declare abstract class BaseDbAdapter {
2878
2893
  * Optional — only relational adapters implement this.
2879
2894
  */
2880
2895
  dropTable?(): Promise<void>;
2896
+ /**
2897
+ * Schema sync (since 0.1.155): copies the values of `source` — a text
2898
+ * column holding a whole value as JSON (the layout atscript-db ≤ 0.1.154
2899
+ * gave a `T | null` object or a union field) — into the columns that
2900
+ * replace it, in rows where `source` is not NULL and every target is NULL.
2901
+ * A malformed JSON value or one that does not convert to a target's type
2902
+ * throws (the table's sync entry errors before anything is dropped).
2903
+ * Optional — relational adapters implement it.
2904
+ */
2905
+ copyFromJsonColumn?(source: string, targets: readonly TJsonCopyTarget[]): Promise<void>;
2906
+ /**
2907
+ * Schema sync (since 0.1.155): rewrites the values of the text column
2908
+ * `column` that are not JSON as JSON strings (`abc` → `"abc"`), before the
2909
+ * column becomes a JSON column — the layout ≤ 0.1.154 stored a mixed
2910
+ * union's string member as plain text. Idempotent.
2911
+ * Optional — relational adapters implement it.
2912
+ */
2913
+ jsonifyTextColumn?(column: string): Promise<void>;
2881
2914
  /**
2882
2915
  * Drops one or more columns from the table.
2883
2916
  * Used by schema sync to remove stale columns no longer in the schema.
@@ -2921,7 +2954,7 @@ declare abstract class BaseDbAdapter {
2921
2954
  dropTablesByName(tableNames: string[]): Promise<void>;
2922
2955
  /**
2923
2956
  * Whether the table has at least one row. Schema sync uses it in the
2924
- * pre-flight phase to refuse a primary-key change on a populated table.
2957
+ * pre-flight phase to check a primary-key change on a populated table.
2925
2958
  * Override with an EXISTS/LIMIT 1 probe — this default is `count() > 0`,
2926
2959
  * a full scan on some engines, and it can only answer for the adapter's
2927
2960
  * OWN table: for another `tableName` (or on an administrative adapter
@@ -2955,12 +2988,26 @@ declare abstract class BaseDbAdapter {
2955
2988
  getObjectKind?(name: string): Promise<TDbObjectKind | undefined>;
2956
2989
  /**
2957
2990
  * Rewrites the table's primary key from `change.from` to `change.to`.
2958
- * Called only on an EMPTY table (schema sync refuses populated ones) after
2959
- * new columns were added and before stale columns are dropped, so both
2960
- * column sets exist. Adapters without it fall back to {@link recreateTable}.
2991
+ * Called on an empty table, or (since 0.1.155) on a populated one whose
2992
+ * rows already satisfy the new key ({@link countKeyViolations} answered
2993
+ * `0`), after new columns were added and before stale columns are dropped,
2994
+ * so both column sets exist. Adapters without it fall back to
2995
+ * {@link recreateTable}.
2961
2996
  * @since 0.1.128
2962
2997
  */
2963
2998
  rebuildPrimaryKey?(change: TPrimaryKeyChange): Promise<void>;
2999
+ /**
3000
+ * How many rows of the live table `columns` cannot hold as a primary key:
3001
+ * rows with a NULL (or missing value) in one of them, plus every row that
3002
+ * shares its values with another. Schema sync rebuilds the key of a
3003
+ * populated table only when this answers `0`, and refuses the run with the
3004
+ * count otherwise. Optional — without it a populated key change is refused.
3005
+ *
3006
+ * @param tableName - Check this table instead of the adapter's own (the OLD
3007
+ * name of a table that is about to be renamed).
3008
+ * @since 0.1.155
3009
+ */
3010
+ countKeyViolations?(columns: readonly string[], tableName?: string): Promise<number>;
2964
3011
  /**
2965
3012
  * Renames a table/collection from `oldName` to the adapter's current table name.
2966
3013
  * Used by schema sync when `@db.table.renamed` is present.
@@ -3006,6 +3053,16 @@ declare abstract class BaseDbAdapter {
3006
3053
  formatValue?(field: TDbFieldMeta): TValueFormatterPair | ((value: unknown) => unknown) | undefined;
3007
3054
  }
3008
3055
  //#endregion
3056
+ //#region src/shared/union-shape.d.ts
3057
+ /**
3058
+ * Whether a value at a path is always there (`"required"`), may be NULL /
3059
+ * missing (`"nullable"` — the path or an ancestor object is optional or a
3060
+ * `| null` union), or is declared by only some members of a union of objects
3061
+ * on the way (`"partial"` — `card` of `payment: Card | Bank` when only
3062
+ * `Card` declares it). Ordered: each is weaker than the previous one.
3063
+ */
3064
+ type TPathPresence = "required" | "nullable" | "partial";
3065
+ //#endregion
3009
3066
  //#region src/table/table-metadata.d.ts
3010
3067
  /** Returns true if the annotated type IS the `db.geoPoint` primitive (tag-based). */
3011
3068
  declare function isGeoPointType(fieldType: TAtscriptAnnotatedType): boolean;
@@ -3142,8 +3199,42 @@ declare class TableMetadata {
3142
3199
  private _alwaysAddressable?;
3143
3200
  private _collateMap;
3144
3201
  private _columnFromMap;
3202
+ /** The annotated type `build()` ran on — the root of {@link presence}. */
3203
+ private _rootType?;
3204
+ private readonly _presence;
3145
3205
  constructor(nestedObjects: boolean);
3146
3206
  get isBuilt(): boolean;
3207
+ /**
3208
+ * Whether the value of the LOGICAL field `path` is always there, may be
3209
+ * NULL / missing, or is declared by only some members of a union of
3210
+ * objects on the way ({@link TPathPresence}); `undefined` inside an array.
3211
+ * @since 0.1.155
3212
+ */
3213
+ presence(path: string): TPathPresence | undefined;
3214
+ /**
3215
+ * Whether the LOGICAL field `path` can hold NULL (or be missing): it or a
3216
+ * parent object is optional or a `| null` union, or only some members of
3217
+ * a union of objects declare it. Inside an array: the field or a parent
3218
+ * is optional.
3219
+ * @since 0.1.155
3220
+ */
3221
+ isNullable(path: string): boolean;
3222
+ private _objectLeaves?;
3223
+ /**
3224
+ * The stored fields under the object field `path` that a null test on the
3225
+ * object reads (`rewriteObjectNullTests`, since 0.1.155): its leaf columns
3226
+ * on relational storage, its scalar / array / JSON fields on document
3227
+ * storage (not inside an array or a JSON value). `undefined` when `path`
3228
+ * is no stored object (a leaf, a `@db.json` / encrypted / ignored field,
3229
+ * a navigation relation, inside a JSON value, unknown).
3230
+ */
3231
+ objectLeaves(path: string): readonly string[] | undefined;
3232
+ /**
3233
+ * Whether the column of `path` is nullable: {@link isNullable}, except
3234
+ * inside an array (document storage only), where the field's own
3235
+ * optionality counts.
3236
+ */
3237
+ private _columnNullable;
3147
3238
  /**
3148
3239
  * {@link documentPath} over this table's `columnMap`. A `@db.column.derived`
3149
3240
  * field has no stored path of its own: it maps to its source leaf.
@@ -3184,10 +3275,13 @@ declare class TableMetadata {
3184
3275
  * into the synthetic flat entry of the prop's path, so a member's
3185
3276
  * annotations would reach the column (DDL type, size, default). Since
3186
3277
  * atscript 0.1.103 a built-in primitive member carries its built-in
3187
- * annotations (`number.timestamp.created | null` → `@db.default.now`,
3188
- * `string.char` → `@expect.maxLength 1`). Rebuild such an entry from the
3189
- * prop's own annotations plus the non-`db.*` annotations of named members
3190
- * (aliases, interfaces), so the column is described as before 0.1.103.
3278
+ * annotations (`string.char` → `@expect.maxLength 1`). Rebuild such an
3279
+ * entry from the prop's own annotations plus the non-`db.*` annotations of
3280
+ * named members (aliases, interfaces), so the column is described as before
3281
+ * 0.1.103. Exception: the one non-`null` member of `T | null` is the
3282
+ * column's type, so its `db.*` annotations apply too — `createdAt:
3283
+ * number.timestamp.created | null` gets `@db.default.now` like
3284
+ * `createdAt: number.timestamp.created`.
3191
3285
  */
3192
3286
  private _dropMemberMetadata;
3193
3287
  /**
@@ -3973,6 +4067,22 @@ interface TExistingColumn {
3973
4067
  * @since 0.1.141
3974
4068
  */
3975
4069
  type TDerivedChangeReason = "kind" | "expression" | "type";
4070
+ /**
4071
+ * One column {@link BaseDbAdapter.copyFromJsonColumn} fills from the JSON
4072
+ * text of a column the previous layout stored a whole value in (since 0.1.155).
4073
+ */
4074
+ interface TJsonCopyTarget {
4075
+ /** Physical column to fill. */
4076
+ column: string;
4077
+ /** Path of the value inside the source JSON (logical property names). */
4078
+ path: readonly string[];
4079
+ /**
4080
+ * How the value is read: `text` — a scalar as text, cast to the column
4081
+ * type; `boolean` — a JSON boolean; `json` — the sub-value as JSON.
4082
+ */
4083
+ kind: "text" | "boolean" | "json";
4084
+ field: TDbFieldMeta;
4085
+ }
3976
4086
  /** Result of comparing desired schema against existing database columns. */
3977
4087
  interface TColumnDiff {
3978
4088
  added: TDbFieldMeta[];
@@ -4573,4 +4683,4 @@ declare function isJsonValueField(fd: TDbFieldMeta): boolean;
4573
4683
  */
4574
4684
  declare function jsonValueAncestor(path: string, jsonValueParents: ReadonlySet<string>): string | undefined;
4575
4685
  //#endregion
4576
- export { TDbInsertResult as $, DbSpace as $t, TColumnDiff as A, TRelationFilterJunction as An, TReferencingForeignKey as At, TDbDefaultFn as B, TDbEncryptionOptions as Bn, TWriteOptions as Bt, NavPropsOf$1 as C, AtscriptDbReadable as Cn, TIdDescriptor as Ct, PrimaryKeyOf$1 as D, REL_FILTER_MAX_NODES as Dn, TMetaResponse as Dt, OwnPropsOf$1 as E, REL_FILTER_MAX_DEPTH as En, TInsertOptions as Et, TDbActionLevel as F, forEachResolvedRelation as Fn, TTableOptionDiff as Ft, TDbIndex as G, TGenericLogger as Gn, WithRelation$1 as Gt, TDbDeleteResult as H, FieldMappingStrategy as Hn, TypedWithRelation as Ht, TDbActionProcessor as I, hasRelationOp as In, TTableResolver as It, TDbInsertIgnoreOptions as J, TRowOrderKey as Jn, isGeoPointType as Jt, TDbIndexField as K, TExprAggregate as Kn, TableMetadata as Kt, TDbActionTargetSummary as L, isResolvedRelationFilter as Ln, TTouchManyOptions as Lt, TCrudPermissions as M, TRelationStaticFilter as Mn, TRowResolveOptions as Mt, TDbActionInfo as N, andFilters as Nn, TSearchIndexInfo as Nt, TCascadeResolver as O, ResolvedRelationFilter as On, TMetadataOverrides as Ot, TDbActionIntent as P, containsRelationFilter as Pn, TSyncColumnResult as Pt, TDbInsertManyResult as Q, TViewCapability as Qt, TDbAvailableActions as R, relationStaticFilter as Rn, TValueFormatterPair as Rt, FlatOf$1 as S, TCascadePin as Sn, TFkLookupTarget as St, NullsPlacement$1 as T, resolveDesignType as Tn, TIdentification as Tt, TDbFieldMeta as U, TReadControls as Un, Uniquery$1 as Ut, TDbDefaultValue as V, DocumentFieldMapper as Vn, TWriteTableResolver as Vt, TDbForeignKey as W, NoopLogger as Wn, UniqueryControls$1 as Wt, TDbInsertIgnoreSlot as X, ALL_VIEW_CAPABILITIES as Xt, TDbInsertIgnoreResult as Y, UniquSelect as Yn, ALL_BUCKET_UNITS as Yt, TDbInsertManyIgnoreResult as Z, BaseDbAdapter as Zt, DbPatch as _, isFieldRef as _n, TExistingColumn as _t, isJsonValueField as a, isViewType as an, TDbStorageType as at, FieldOpsFor as b, IntegrityStrategy as bn, TFieldMeta as bt, resolveCalendarBuckets as c, AtscriptExprNode$1 as cn, TDbWriteAction as ct, AggregateFn$1 as d, AtscriptQueryFieldRef$1 as dn, TDbWriteGuard as dt, TAdapterFactory as en, TDbObjectKind as et, AggregateQuery$1 as f, AtscriptQueryNode$1 as fn, TDbWriteGuardContext as ft, DbControls as g, evaluateExpr as gn, TEnsureTableOptions as gt, AtscriptDbWritable as h, TViewPlan as hn, TDerivedColumn as ht, isBucketableField as i, isAtscriptDbView as in, TDbRemoveGuardContext as it, TCrudOp as j, TRelationFilterTable as jn, TRelationInfo as jt, TCascadeTarget as k, TRelGuardState as kn, TPrimaryKeyChange as kt, AggregateControls as l, AtscriptOrderItem as ln, TDbWriteCheck as lt, AtscriptDbTableLike as m, TViewJoin as mn, TDerivedChangeReason as mt, TComputedSelect as n, AtscriptDbView as nn, TDbRelation as nt, jsonValueAncestor as o, TViewReadPlan as on, TDbUpdateOptions as ot, AggregateResult as p, AtscriptRef as pn, TDeleteOptions as pt, TDbIndexType as q, TFirstLast as qn, isGeoIndexableType as qt, TResolvedBucket as r, TViewColumnMapping as rn, TDbRemoveGuard as rt, normalizeComputedSelect as s, aliasTargetOf as sn, TDbUpdateResult as st, TBucketFieldSource as t, TDbSpaceOptions as tn, TDbReferentialAction as tt, AggregateExpr$1 as u, AtscriptQueryComparison as un, TDbWriteCheckContext as ut, DbQuery as v, translateQueryTree as vn, TExistingForeignKey as vt, NullableOptional as w, DbResponse as wn, TIdResolveOptions as wt, FilterExpr$1 as x, NativeIntegrity as xn, TFkLookupResolver as xt, DbRow as y, AtscriptDbTable as yn, TExistingTableOption as yt, TDbCollation as z, DbEncryption as zn, TViewJsonType as zt };
4686
+ export { TDbInsertResult as $, BaseDbAdapter as $t, TColumnDiff as A, ResolvedRelationFilter as An, TPrimaryKeyChange as At, TDbDefaultFn as B, relationStaticFilter as Bn, TViewJsonType as Bt, NavPropsOf$1 as C, NativeIntegrity as Cn, TIdDescriptor as Ct, PrimaryKeyOf$1 as D, resolveDesignType as Dn, TJsonCopyTarget as Dt, OwnPropsOf$1 as E, DbResponse as En, TInsertOptions as Et, TDbActionLevel as F, andFilters as Fn, TSyncColumnResult as Ft, TDbIndex as G, TReadControls as Gn, UniqueryControls$1 as Gt, TDbDeleteResult as H, TDbEncryptionOptions as Hn, TWriteTableResolver as Ht, TDbActionProcessor as I, containsRelationFilter as In, TTableOptionDiff as It, TDbInsertIgnoreOptions as J, TExprAggregate as Jn, isGeoIndexableType as Jt, TDbIndexField as K, NoopLogger as Kn, WithRelation$1 as Kt, TDbActionTargetSummary as L, forEachResolvedRelation as Ln, TTableResolver as Lt, TCrudPermissions as M, TRelationFilterJunction as Mn, TRelationInfo as Mt, TDbActionInfo as N, TRelationFilterTable as Nn, TRowResolveOptions as Nt, TCascadeResolver as O, REL_FILTER_MAX_DEPTH as On, TMetaResponse as Ot, TDbActionIntent as P, TRelationStaticFilter as Pn, TSearchIndexInfo as Pt, TDbInsertManyResult as Q, ALL_VIEW_CAPABILITIES as Qt, TDbAvailableActions as R, hasRelationOp as Rn, TTouchManyOptions as Rt, FlatOf$1 as S, IntegrityStrategy as Sn, TFkLookupTarget as St, NullsPlacement$1 as T, AtscriptDbReadable as Tn, TIdentification as Tt, TDbFieldMeta as U, DocumentFieldMapper as Un, TypedWithRelation as Ut, TDbDefaultValue as V, DbEncryption as Vn, TWriteOptions as Vt, TDbForeignKey as W, FieldMappingStrategy as Wn, Uniquery$1 as Wt, TDbInsertIgnoreSlot as X, TRowOrderKey as Xn, TPathPresence as Xt, TDbInsertIgnoreResult as Y, TFirstLast as Yn, isGeoPointType as Yt, TDbInsertManyIgnoreResult as Z, UniquSelect as Zn, ALL_BUCKET_UNITS as Zt, DbPatch as _, TViewPlan as _n, TExistingColumn as _t, isJsonValueField as a, TViewColumnMapping as an, TDbStorageType as at, FieldOpsFor as b, translateQueryTree as bn, TFieldMeta as bt, resolveCalendarBuckets as c, TViewReadPlan as cn, TDbWriteAction as ct, AggregateFn$1 as d, AtscriptOrderItem as dn, TDbWriteGuard as dt, TViewCapability as en, TDbObjectKind as et, AggregateQuery$1 as f, AtscriptQueryComparison as fn, TDbWriteGuardContext as ft, DbControls as g, TViewJoin as gn, TEnsureTableOptions as gt, AtscriptDbWritable as h, AtscriptRef as hn, TDerivedColumn as ht, isBucketableField as i, AtscriptDbView as in, TDbRemoveGuardContext as it, TCrudOp as j, TRelGuardState as jn, TReferencingForeignKey as jt, TCascadeTarget as k, REL_FILTER_MAX_NODES as kn, TMetadataOverrides as kt, AggregateControls as l, aliasTargetOf as ln, TDbWriteCheck as lt, AtscriptDbTableLike as m, AtscriptQueryNode$1 as mn, TDerivedChangeReason as mt, TComputedSelect as n, TAdapterFactory as nn, TDbRelation as nt, jsonValueAncestor as o, isAtscriptDbView as on, TDbUpdateOptions as ot, AggregateResult as p, AtscriptQueryFieldRef$1 as pn, TDeleteOptions as pt, TDbIndexType as q, TGenericLogger as qn, TableMetadata as qt, TResolvedBucket as r, TDbSpaceOptions as rn, TDbRemoveGuard as rt, normalizeComputedSelect as s, isViewType as sn, TDbUpdateResult as st, TBucketFieldSource as t, DbSpace as tn, TDbReferentialAction as tt, AggregateExpr$1 as u, AtscriptExprNode$1 as un, TDbWriteCheckContext as ut, DbQuery as v, evaluateExpr as vn, TExistingForeignKey as vt, NullableOptional as w, TCascadePin as wn, TIdResolveOptions as wt, FilterExpr$1 as x, AtscriptDbTable as xn, TFkLookupResolver as xt, DbRow as y, isFieldRef as yn, TExistingTableOption as yt, TDbCollation as z, isResolvedRelationFilter as zn, TValueFormatterPair as zt };
@@ -594,7 +594,9 @@ type DbResponse<Data, Nav, Q> = [keyof Nav] extends [never] ? Data : string exte
594
594
  * otherwise trips up every adapter author.
595
595
  *
596
596
  * For union types (e.g., from flattened `{...} | {...}` objects):
597
- * - If all members resolve to the same type → returns that type (strong type)
597
+ * - `null` / `undefined` members are left out (since 0.1.155): `T | null`
598
+ * resolves to the design type of `T`
599
+ * - If all other members resolve to the same type → returns that type (strong type)
598
600
  * - If members disagree → returns `'union'` (out of scope for type management)
599
601
  */
600
602
  declare function resolveDesignType(fieldType: TAtscriptAnnotatedType): string;
@@ -1545,8 +1547,21 @@ declare class AtscriptDbTable<T extends TAtscriptAnnotatedType = TAtscriptAnnota
1545
1547
  * full row). Function defaults (`now` / `uuid` / `increment` / custom) the
1546
1548
  * adapter handles natively are NOT filled — the field stays absent so the
1547
1549
  * engine's own default applies. The version column is never touched.
1550
+ * A nested field (`audit.createdAt`) is filled inside its object, only when
1551
+ * that object is present (an absent or `null` embedded object stays so), and
1552
+ * in every object of an array on the way; a field inside a JSON value or an
1553
+ * array has no column default, so the SDK fills its function default too.
1548
1554
  */
1549
1555
  protected _applyDefaults(data: Record<string, unknown>): Record<string, unknown>;
1556
+ /** {@link _nestedDefaultFillable} per nested default path. */
1557
+ private _fillableDefaults?;
1558
+ /**
1559
+ * Whether every parent of the nested default `field` is one object type —
1560
+ * an object, `T | null` of one, or an array of one. Below a tuple or a
1561
+ * union of several types the default cannot be placed (the item it belongs
1562
+ * to is unknown), so it is not filled.
1563
+ */
1564
+ private _nestedDefaultFillable;
1550
1565
  /**
1551
1566
  * Parsed `@db.default 'literal'` values that are primitives — reused for
1552
1567
  * every row (an object / array default is parsed per row: each row gets
@@ -2878,6 +2893,24 @@ declare abstract class BaseDbAdapter {
2878
2893
  * Optional — only relational adapters implement this.
2879
2894
  */
2880
2895
  dropTable?(): Promise<void>;
2896
+ /**
2897
+ * Schema sync (since 0.1.155): copies the values of `source` — a text
2898
+ * column holding a whole value as JSON (the layout atscript-db ≤ 0.1.154
2899
+ * gave a `T | null` object or a union field) — into the columns that
2900
+ * replace it, in rows where `source` is not NULL and every target is NULL.
2901
+ * A malformed JSON value or one that does not convert to a target's type
2902
+ * throws (the table's sync entry errors before anything is dropped).
2903
+ * Optional — relational adapters implement it.
2904
+ */
2905
+ copyFromJsonColumn?(source: string, targets: readonly TJsonCopyTarget[]): Promise<void>;
2906
+ /**
2907
+ * Schema sync (since 0.1.155): rewrites the values of the text column
2908
+ * `column` that are not JSON as JSON strings (`abc` → `"abc"`), before the
2909
+ * column becomes a JSON column — the layout ≤ 0.1.154 stored a mixed
2910
+ * union's string member as plain text. Idempotent.
2911
+ * Optional — relational adapters implement it.
2912
+ */
2913
+ jsonifyTextColumn?(column: string): Promise<void>;
2881
2914
  /**
2882
2915
  * Drops one or more columns from the table.
2883
2916
  * Used by schema sync to remove stale columns no longer in the schema.
@@ -2921,7 +2954,7 @@ declare abstract class BaseDbAdapter {
2921
2954
  dropTablesByName(tableNames: string[]): Promise<void>;
2922
2955
  /**
2923
2956
  * Whether the table has at least one row. Schema sync uses it in the
2924
- * pre-flight phase to refuse a primary-key change on a populated table.
2957
+ * pre-flight phase to check a primary-key change on a populated table.
2925
2958
  * Override with an EXISTS/LIMIT 1 probe — this default is `count() > 0`,
2926
2959
  * a full scan on some engines, and it can only answer for the adapter's
2927
2960
  * OWN table: for another `tableName` (or on an administrative adapter
@@ -2955,12 +2988,26 @@ declare abstract class BaseDbAdapter {
2955
2988
  getObjectKind?(name: string): Promise<TDbObjectKind | undefined>;
2956
2989
  /**
2957
2990
  * Rewrites the table's primary key from `change.from` to `change.to`.
2958
- * Called only on an EMPTY table (schema sync refuses populated ones) after
2959
- * new columns were added and before stale columns are dropped, so both
2960
- * column sets exist. Adapters without it fall back to {@link recreateTable}.
2991
+ * Called on an empty table, or (since 0.1.155) on a populated one whose
2992
+ * rows already satisfy the new key ({@link countKeyViolations} answered
2993
+ * `0`), after new columns were added and before stale columns are dropped,
2994
+ * so both column sets exist. Adapters without it fall back to
2995
+ * {@link recreateTable}.
2961
2996
  * @since 0.1.128
2962
2997
  */
2963
2998
  rebuildPrimaryKey?(change: TPrimaryKeyChange): Promise<void>;
2999
+ /**
3000
+ * How many rows of the live table `columns` cannot hold as a primary key:
3001
+ * rows with a NULL (or missing value) in one of them, plus every row that
3002
+ * shares its values with another. Schema sync rebuilds the key of a
3003
+ * populated table only when this answers `0`, and refuses the run with the
3004
+ * count otherwise. Optional — without it a populated key change is refused.
3005
+ *
3006
+ * @param tableName - Check this table instead of the adapter's own (the OLD
3007
+ * name of a table that is about to be renamed).
3008
+ * @since 0.1.155
3009
+ */
3010
+ countKeyViolations?(columns: readonly string[], tableName?: string): Promise<number>;
2964
3011
  /**
2965
3012
  * Renames a table/collection from `oldName` to the adapter's current table name.
2966
3013
  * Used by schema sync when `@db.table.renamed` is present.
@@ -3006,6 +3053,16 @@ declare abstract class BaseDbAdapter {
3006
3053
  formatValue?(field: TDbFieldMeta): TValueFormatterPair | ((value: unknown) => unknown) | undefined;
3007
3054
  }
3008
3055
  //#endregion
3056
+ //#region src/shared/union-shape.d.ts
3057
+ /**
3058
+ * Whether a value at a path is always there (`"required"`), may be NULL /
3059
+ * missing (`"nullable"` — the path or an ancestor object is optional or a
3060
+ * `| null` union), or is declared by only some members of a union of objects
3061
+ * on the way (`"partial"` — `card` of `payment: Card | Bank` when only
3062
+ * `Card` declares it). Ordered: each is weaker than the previous one.
3063
+ */
3064
+ type TPathPresence = "required" | "nullable" | "partial";
3065
+ //#endregion
3009
3066
  //#region src/table/table-metadata.d.ts
3010
3067
  /** Returns true if the annotated type IS the `db.geoPoint` primitive (tag-based). */
3011
3068
  declare function isGeoPointType(fieldType: TAtscriptAnnotatedType): boolean;
@@ -3142,8 +3199,42 @@ declare class TableMetadata {
3142
3199
  private _alwaysAddressable?;
3143
3200
  private _collateMap;
3144
3201
  private _columnFromMap;
3202
+ /** The annotated type `build()` ran on — the root of {@link presence}. */
3203
+ private _rootType?;
3204
+ private readonly _presence;
3145
3205
  constructor(nestedObjects: boolean);
3146
3206
  get isBuilt(): boolean;
3207
+ /**
3208
+ * Whether the value of the LOGICAL field `path` is always there, may be
3209
+ * NULL / missing, or is declared by only some members of a union of
3210
+ * objects on the way ({@link TPathPresence}); `undefined` inside an array.
3211
+ * @since 0.1.155
3212
+ */
3213
+ presence(path: string): TPathPresence | undefined;
3214
+ /**
3215
+ * Whether the LOGICAL field `path` can hold NULL (or be missing): it or a
3216
+ * parent object is optional or a `| null` union, or only some members of
3217
+ * a union of objects declare it. Inside an array: the field or a parent
3218
+ * is optional.
3219
+ * @since 0.1.155
3220
+ */
3221
+ isNullable(path: string): boolean;
3222
+ private _objectLeaves?;
3223
+ /**
3224
+ * The stored fields under the object field `path` that a null test on the
3225
+ * object reads (`rewriteObjectNullTests`, since 0.1.155): its leaf columns
3226
+ * on relational storage, its scalar / array / JSON fields on document
3227
+ * storage (not inside an array or a JSON value). `undefined` when `path`
3228
+ * is no stored object (a leaf, a `@db.json` / encrypted / ignored field,
3229
+ * a navigation relation, inside a JSON value, unknown).
3230
+ */
3231
+ objectLeaves(path: string): readonly string[] | undefined;
3232
+ /**
3233
+ * Whether the column of `path` is nullable: {@link isNullable}, except
3234
+ * inside an array (document storage only), where the field's own
3235
+ * optionality counts.
3236
+ */
3237
+ private _columnNullable;
3147
3238
  /**
3148
3239
  * {@link documentPath} over this table's `columnMap`. A `@db.column.derived`
3149
3240
  * field has no stored path of its own: it maps to its source leaf.
@@ -3184,10 +3275,13 @@ declare class TableMetadata {
3184
3275
  * into the synthetic flat entry of the prop's path, so a member's
3185
3276
  * annotations would reach the column (DDL type, size, default). Since
3186
3277
  * atscript 0.1.103 a built-in primitive member carries its built-in
3187
- * annotations (`number.timestamp.created | null` → `@db.default.now`,
3188
- * `string.char` → `@expect.maxLength 1`). Rebuild such an entry from the
3189
- * prop's own annotations plus the non-`db.*` annotations of named members
3190
- * (aliases, interfaces), so the column is described as before 0.1.103.
3278
+ * annotations (`string.char` → `@expect.maxLength 1`). Rebuild such an
3279
+ * entry from the prop's own annotations plus the non-`db.*` annotations of
3280
+ * named members (aliases, interfaces), so the column is described as before
3281
+ * 0.1.103. Exception: the one non-`null` member of `T | null` is the
3282
+ * column's type, so its `db.*` annotations apply too — `createdAt:
3283
+ * number.timestamp.created | null` gets `@db.default.now` like
3284
+ * `createdAt: number.timestamp.created`.
3191
3285
  */
3192
3286
  private _dropMemberMetadata;
3193
3287
  /**
@@ -3973,6 +4067,22 @@ interface TExistingColumn {
3973
4067
  * @since 0.1.141
3974
4068
  */
3975
4069
  type TDerivedChangeReason = "kind" | "expression" | "type";
4070
+ /**
4071
+ * One column {@link BaseDbAdapter.copyFromJsonColumn} fills from the JSON
4072
+ * text of a column the previous layout stored a whole value in (since 0.1.155).
4073
+ */
4074
+ interface TJsonCopyTarget {
4075
+ /** Physical column to fill. */
4076
+ column: string;
4077
+ /** Path of the value inside the source JSON (logical property names). */
4078
+ path: readonly string[];
4079
+ /**
4080
+ * How the value is read: `text` — a scalar as text, cast to the column
4081
+ * type; `boolean` — a JSON boolean; `json` — the sub-value as JSON.
4082
+ */
4083
+ kind: "text" | "boolean" | "json";
4084
+ field: TDbFieldMeta;
4085
+ }
3976
4086
  /** Result of comparing desired schema against existing database columns. */
3977
4087
  interface TColumnDiff {
3978
4088
  added: TDbFieldMeta[];
@@ -4573,4 +4683,4 @@ declare function isJsonValueField(fd: TDbFieldMeta): boolean;
4573
4683
  */
4574
4684
  declare function jsonValueAncestor(path: string, jsonValueParents: ReadonlySet<string>): string | undefined;
4575
4685
  //#endregion
4576
- export { TDbInsertResult as $, DbSpace as $t, TColumnDiff as A, TRelationFilterJunction as An, TReferencingForeignKey as At, TDbDefaultFn as B, TDbEncryptionOptions as Bn, TWriteOptions as Bt, NavPropsOf$1 as C, AtscriptDbReadable as Cn, TIdDescriptor as Ct, PrimaryKeyOf$1 as D, REL_FILTER_MAX_NODES as Dn, TMetaResponse as Dt, OwnPropsOf$1 as E, REL_FILTER_MAX_DEPTH as En, TInsertOptions as Et, TDbActionLevel as F, forEachResolvedRelation as Fn, TTableOptionDiff as Ft, TDbIndex as G, TGenericLogger as Gn, WithRelation$1 as Gt, TDbDeleteResult as H, FieldMappingStrategy as Hn, TypedWithRelation as Ht, TDbActionProcessor as I, hasRelationOp as In, TTableResolver as It, TDbInsertIgnoreOptions as J, TRowOrderKey as Jn, isGeoPointType as Jt, TDbIndexField as K, TExprAggregate as Kn, TableMetadata as Kt, TDbActionTargetSummary as L, isResolvedRelationFilter as Ln, TTouchManyOptions as Lt, TCrudPermissions as M, TRelationStaticFilter as Mn, TRowResolveOptions as Mt, TDbActionInfo as N, andFilters as Nn, TSearchIndexInfo as Nt, TCascadeResolver as O, ResolvedRelationFilter as On, TMetadataOverrides as Ot, TDbActionIntent as P, containsRelationFilter as Pn, TSyncColumnResult as Pt, TDbInsertManyResult as Q, TViewCapability as Qt, TDbAvailableActions as R, relationStaticFilter as Rn, TValueFormatterPair as Rt, FlatOf$1 as S, TCascadePin as Sn, TFkLookupTarget as St, NullsPlacement$1 as T, resolveDesignType as Tn, TIdentification as Tt, TDbFieldMeta as U, TReadControls as Un, Uniquery$1 as Ut, TDbDefaultValue as V, DocumentFieldMapper as Vn, TWriteTableResolver as Vt, TDbForeignKey as W, NoopLogger as Wn, UniqueryControls$1 as Wt, TDbInsertIgnoreSlot as X, ALL_VIEW_CAPABILITIES as Xt, TDbInsertIgnoreResult as Y, UniquSelect as Yn, ALL_BUCKET_UNITS as Yt, TDbInsertManyIgnoreResult as Z, BaseDbAdapter as Zt, DbPatch as _, isFieldRef as _n, TExistingColumn as _t, isJsonValueField as a, isViewType as an, TDbStorageType as at, FieldOpsFor as b, IntegrityStrategy as bn, TFieldMeta as bt, resolveCalendarBuckets as c, AtscriptExprNode$1 as cn, TDbWriteAction as ct, AggregateFn$1 as d, AtscriptQueryFieldRef$1 as dn, TDbWriteGuard as dt, TAdapterFactory as en, TDbObjectKind as et, AggregateQuery$1 as f, AtscriptQueryNode$1 as fn, TDbWriteGuardContext as ft, DbControls as g, evaluateExpr as gn, TEnsureTableOptions as gt, AtscriptDbWritable as h, TViewPlan as hn, TDerivedColumn as ht, isBucketableField as i, isAtscriptDbView as in, TDbRemoveGuardContext as it, TCrudOp as j, TRelationFilterTable as jn, TRelationInfo as jt, TCascadeTarget as k, TRelGuardState as kn, TPrimaryKeyChange as kt, AggregateControls as l, AtscriptOrderItem as ln, TDbWriteCheck as lt, AtscriptDbTableLike as m, TViewJoin as mn, TDerivedChangeReason as mt, TComputedSelect as n, AtscriptDbView as nn, TDbRelation as nt, jsonValueAncestor as o, TViewReadPlan as on, TDbUpdateOptions as ot, AggregateResult as p, AtscriptRef as pn, TDeleteOptions as pt, TDbIndexType as q, TFirstLast as qn, isGeoIndexableType as qt, TResolvedBucket as r, TViewColumnMapping as rn, TDbRemoveGuard as rt, normalizeComputedSelect as s, aliasTargetOf as sn, TDbUpdateResult as st, TBucketFieldSource as t, TDbSpaceOptions as tn, TDbReferentialAction as tt, AggregateExpr$1 as u, AtscriptQueryComparison as un, TDbWriteCheckContext as ut, DbQuery as v, translateQueryTree as vn, TExistingForeignKey as vt, NullableOptional as w, DbResponse as wn, TIdResolveOptions as wt, FilterExpr$1 as x, NativeIntegrity as xn, TFkLookupResolver as xt, DbRow as y, AtscriptDbTable as yn, TExistingTableOption as yt, TDbCollation as z, DbEncryption as zn, TViewJsonType as zt };
4686
+ export { TDbInsertResult as $, BaseDbAdapter as $t, TColumnDiff as A, ResolvedRelationFilter as An, TPrimaryKeyChange as At, TDbDefaultFn as B, relationStaticFilter as Bn, TViewJsonType as Bt, NavPropsOf$1 as C, NativeIntegrity as Cn, TIdDescriptor as Ct, PrimaryKeyOf$1 as D, resolveDesignType as Dn, TJsonCopyTarget as Dt, OwnPropsOf$1 as E, DbResponse as En, TInsertOptions as Et, TDbActionLevel as F, andFilters as Fn, TSyncColumnResult as Ft, TDbIndex as G, TReadControls as Gn, UniqueryControls$1 as Gt, TDbDeleteResult as H, TDbEncryptionOptions as Hn, TWriteTableResolver as Ht, TDbActionProcessor as I, containsRelationFilter as In, TTableOptionDiff as It, TDbInsertIgnoreOptions as J, TExprAggregate as Jn, isGeoIndexableType as Jt, TDbIndexField as K, NoopLogger as Kn, WithRelation$1 as Kt, TDbActionTargetSummary as L, forEachResolvedRelation as Ln, TTableResolver as Lt, TCrudPermissions as M, TRelationFilterJunction as Mn, TRelationInfo as Mt, TDbActionInfo as N, TRelationFilterTable as Nn, TRowResolveOptions as Nt, TCascadeResolver as O, REL_FILTER_MAX_DEPTH as On, TMetaResponse as Ot, TDbActionIntent as P, TRelationStaticFilter as Pn, TSearchIndexInfo as Pt, TDbInsertManyResult as Q, ALL_VIEW_CAPABILITIES as Qt, TDbAvailableActions as R, hasRelationOp as Rn, TTouchManyOptions as Rt, FlatOf$1 as S, IntegrityStrategy as Sn, TFkLookupTarget as St, NullsPlacement$1 as T, AtscriptDbReadable as Tn, TIdentification as Tt, TDbFieldMeta as U, DocumentFieldMapper as Un, TypedWithRelation as Ut, TDbDefaultValue as V, DbEncryption as Vn, TWriteOptions as Vt, TDbForeignKey as W, FieldMappingStrategy as Wn, Uniquery$1 as Wt, TDbInsertIgnoreSlot as X, TRowOrderKey as Xn, TPathPresence as Xt, TDbInsertIgnoreResult as Y, TFirstLast as Yn, isGeoPointType as Yt, TDbInsertManyIgnoreResult as Z, UniquSelect as Zn, ALL_BUCKET_UNITS as Zt, DbPatch as _, TViewPlan as _n, TExistingColumn as _t, isJsonValueField as a, TViewColumnMapping as an, TDbStorageType as at, FieldOpsFor as b, translateQueryTree as bn, TFieldMeta as bt, resolveCalendarBuckets as c, TViewReadPlan as cn, TDbWriteAction as ct, AggregateFn$1 as d, AtscriptOrderItem as dn, TDbWriteGuard as dt, TViewCapability as en, TDbObjectKind as et, AggregateQuery$1 as f, AtscriptQueryComparison as fn, TDbWriteGuardContext as ft, DbControls as g, TViewJoin as gn, TEnsureTableOptions as gt, AtscriptDbWritable as h, AtscriptRef as hn, TDerivedColumn as ht, isBucketableField as i, AtscriptDbView as in, TDbRemoveGuardContext as it, TCrudOp as j, TRelGuardState as jn, TReferencingForeignKey as jt, TCascadeTarget as k, REL_FILTER_MAX_NODES as kn, TMetadataOverrides as kt, AggregateControls as l, aliasTargetOf as ln, TDbWriteCheck as lt, AtscriptDbTableLike as m, AtscriptQueryNode$1 as mn, TDerivedChangeReason as mt, TComputedSelect as n, TAdapterFactory as nn, TDbRelation as nt, jsonValueAncestor as o, isAtscriptDbView as on, TDbUpdateOptions as ot, AggregateResult as p, AtscriptQueryFieldRef$1 as pn, TDeleteOptions as pt, TDbIndexType as q, TGenericLogger as qn, TableMetadata as qt, TResolvedBucket as r, TDbSpaceOptions as rn, TDbRemoveGuard as rt, normalizeComputedSelect as s, isViewType as sn, TDbUpdateResult as st, TBucketFieldSource as t, DbSpace as tn, TDbReferentialAction as tt, AggregateExpr$1 as u, AtscriptExprNode$1 as un, TDbWriteCheckContext as ut, DbQuery as v, evaluateExpr as vn, TExistingForeignKey as vt, NullableOptional as w, TCascadePin as wn, TIdResolveOptions as wt, FilterExpr$1 as x, AtscriptDbTable as xn, TFkLookupResolver as xt, DbRow as y, isFieldRef as yn, TExistingTableOption as yt, TDbCollation as z, isResolvedRelationFilter as zn, TValueFormatterPair as zt };