akanjs 2.2.4-rc.3 → 2.2.4-rc.4

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,7 +6,7 @@ export const getDefault = <T>(fieldObj: FieldObject): DefaultOf<T> => {
6
6
  const result: Record<string, unknown> = {};
7
7
  for (const [key, field] of Object.entries(fieldObj)) {
8
8
  if (field.fieldType === "hidden") result[key] = null;
9
- else if (field.default) {
9
+ else if (field.default !== undefined && field.default !== null) {
10
10
  if (typeof field.default === "function") result[key] = (field.default as () => object)();
11
11
  else result[key] = field.default as object;
12
12
  } else if (field.isArray) result[key] = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "akanjs",
3
- "version": "2.2.4-rc.3",
3
+ "version": "2.2.4-rc.4",
4
4
  "sourceType": "module",
5
5
  "type": "module",
6
6
  "publishConfig": {
@@ -4,7 +4,7 @@ import { mkdir } from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import type { InArgs, InValue, Client as LibsqlClient } from "@libsql/client";
6
6
  import { type BaseEnv, dayjs, FIELD_META, type PromiseOrObject } from "akanjs/base";
7
- import type { ConstantModel } from "akanjs/constant";
7
+ import { type ConstantModel, getDefault } from "akanjs/constant";
8
8
  import {
9
9
  createDocumentId,
10
10
  type DatabaseModel,
@@ -773,6 +773,9 @@ export class SqliteDocumentStore {
773
773
  } else {
774
774
  doc[key] = value;
775
775
  }
776
+ if ((props.isClass as boolean) && (props.isScalar as boolean) && doc[key] !== undefined && doc[key] !== null) {
777
+ doc[key] = this.applyNestedDefaults(doc[key], props);
778
+ }
776
779
  if (props.enum && doc[key] !== undefined && doc[key] !== null) {
777
780
  const values = Array.isArray(doc[key]) ? doc[key] : [doc[key]];
778
781
  const fieldEnum = props.enum as { has: (value: unknown) => boolean } | undefined;
@@ -958,12 +961,28 @@ export class SqliteDocumentStore {
958
961
 
959
962
  private decodeDocumentPayload(payload: Record<string, unknown>) {
960
963
  const fields = this.database.doc[FIELD_META] as unknown as FieldMap;
961
- return Object.fromEntries(
962
- Object.entries(payload).map(([key, value]) => {
963
- const props = fields[key]?.getProps?.();
964
- return [key, props ? this.decodeFieldValue(value, props) : value];
965
- }),
966
- );
964
+ const result: Record<string, unknown> = {};
965
+ for (const [key, fieldMeta] of Object.entries(fields)) {
966
+ if (BASE_COLUMNS.has(key)) continue;
967
+ const props = fieldMeta.getProps();
968
+ const value = payload[key];
969
+ if (value === undefined) {
970
+ const def = props.default;
971
+ if (def !== undefined && def !== null) {
972
+ result[key] = typeof def === "function" ? (def as (data: unknown) => unknown)(payload) : def;
973
+ } else if (props.nullable) {
974
+ result[key] = null;
975
+ }
976
+ } else {
977
+ result[key] = this.decodeFieldValue(value, props);
978
+ }
979
+ }
980
+ for (const [key, value] of Object.entries(payload)) {
981
+ if (key in result || BASE_COLUMNS.has(key)) continue;
982
+ const props = fields[key]?.getProps?.();
983
+ result[key] = props ? this.decodeFieldValue(value, props) : value;
984
+ }
985
+ return result;
967
986
  }
968
987
 
969
988
  private decodeFieldValue(value: unknown, props: Record<string, unknown>): unknown {
@@ -991,12 +1010,39 @@ export class SqliteDocumentStore {
991
1010
  if (!props.isClass || !props.isScalar) return value;
992
1011
  const scalarFields = (props.modelRef as { [FIELD_META]?: FieldMap } | undefined)?.[FIELD_META];
993
1012
  if (!scalarFields) return value;
994
- return Object.fromEntries(
995
- Object.entries(value as Record<string, unknown>).map(([key, nested]) => {
996
- const nestedProps = scalarFields[key]?.getProps?.();
997
- return [key, nestedProps ? this.decodeFieldValue(nested, nestedProps) : nested];
998
- }),
999
- );
1013
+ const source = value as Record<string, unknown>;
1014
+ const defaults = getDefault(scalarFields as never) as Record<string, unknown>;
1015
+ const result: Record<string, unknown> = {};
1016
+ for (const [key, fieldMeta] of Object.entries(scalarFields)) {
1017
+ const nestedProps = fieldMeta.getProps();
1018
+ const nested = source[key];
1019
+ result[key] = nested === undefined ? defaults[key] : this.decodeFieldValue(nested, nestedProps);
1020
+ }
1021
+ for (const [key, nested] of Object.entries(source)) {
1022
+ if (!(key in result)) result[key] = nested;
1023
+ }
1024
+ return result;
1025
+ }
1026
+
1027
+ private applyNestedDefaults(value: unknown, props: Record<string, unknown>): unknown {
1028
+ if (value === undefined || value === null) return value;
1029
+ if (!props.isClass || !props.isScalar) return value;
1030
+ if (Array.isArray(value)) return value.map((item) => this.fillScalarDefaults(item, props));
1031
+ return this.fillScalarDefaults(value, props);
1032
+ }
1033
+
1034
+ private fillScalarDefaults(value: unknown, props: Record<string, unknown>): unknown {
1035
+ if (!value || typeof value !== "object") return value;
1036
+ const scalarFields = (props.modelRef as { [FIELD_META]?: FieldMap } | undefined)?.[FIELD_META];
1037
+ if (!scalarFields) return value;
1038
+ const defaults = getDefault(scalarFields as never) as Record<string, unknown>;
1039
+ const result = { ...(value as Record<string, unknown>) };
1040
+ for (const [key, fieldMeta] of Object.entries(scalarFields)) {
1041
+ const nestedProps = fieldMeta.getProps();
1042
+ if (result[key] === undefined) result[key] = defaults[key];
1043
+ else result[key] = this.applyNestedDefaults(result[key], nestedProps);
1044
+ }
1045
+ return result;
1000
1046
  }
1001
1047
 
1002
1048
  hydrate(data: DocumentRecord, originalData: DocumentRecord = data) {
@@ -1,7 +1,7 @@
1
1
  import { Database } from "bun:sqlite";
2
2
  import type { Client as LibsqlClient } from "@libsql/client";
3
3
  import { type BaseEnv, type PromiseOrObject } from "akanjs/base";
4
- import type { ConstantModel } from "akanjs/constant";
4
+ import { type ConstantModel } from "akanjs/constant";
5
5
  import { type DatabaseModel, type DocumentQuery, type DocumentSchema, type DocumentUpdate, type DocumentUpdateOptions, type SchemaOf } from "akanjs/document";
6
6
  import type { Sql } from "postgres";
7
7
  export interface SqliteDatabaseConfig {
@@ -256,6 +256,8 @@ export declare class SqliteDocumentStore {
256
256
  private decodeFieldValue;
257
257
  private decodeMapValue;
258
258
  private decodeNestedValue;
259
+ private applyNestedDefaults;
260
+ private fillScalarDefaults;
259
261
  hydrate(data: DocumentRecord, originalData?: DocumentRecord): any;
260
262
  private runHooks;
261
263
  private insertStmt;
@@ -185,7 +185,7 @@ export const Modal = ({ className, bodyClassName, confirmClose, children, onCanc
185
185
  return createPortal(
186
186
  <>
187
187
  <div
188
- className={clsx("fixed inset-0 z-10", showBackground && "animate-fadeIn bg-base-content/50 backdrop-blur-md")}
188
+ className={clsx("fixed inset-0 z-10", showBackground && "animate-fadeIn bg-black/50 backdrop-blur-md")}
189
189
  onClick={(event) => {
190
190
  if (event.target !== event.currentTarget) return;
191
191
  requestClose();