js-bao 0.5.0 → 0.5.1

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/client.d.cts CHANGED
@@ -31,8 +31,32 @@ interface FieldOptions {
31
31
  unique?: boolean;
32
32
  default?: any | (() => any);
33
33
  autoAssign?: boolean;
34
+ /**
35
+ * Auto-timestamp this field with `Date.now()` (milliseconds) on save.
36
+ *
37
+ * - `'create'` — stamp only on the first save (when `isNew === true`).
38
+ * - `'update'` — stamp on every save (create AND update).
39
+ * - `'both'` — stamp on every save (create AND update).
40
+ *
41
+ * If the caller passes an explicit value for the field in `data`, the
42
+ * explicit value wins and the stamp is skipped. The stamp is applied
43
+ * in `beforeSave` BEFORE any user-defined hooks, so user hooks may
44
+ * still overwrite the value if they wish (last writer wins).
45
+ */
46
+ autoStamp?: "create" | "update" | "both";
34
47
  maxLength?: number;
35
48
  maxCount?: number;
49
+ /**
50
+ * Allowed-value set for a `string` field. When present, the codegen
51
+ * generators (database-type codegen + doc-model v2 codegen) emit a
52
+ * TypeScript string-literal union (`"a" | "b" | "c"`) instead of a bare
53
+ * `string` for this field.
54
+ *
55
+ * Advisory / codegen-only: this is a TS-emission hint. The runtime and the
56
+ * server do NOT enforce enum membership on write (see #843). Only valid on
57
+ * `string` fields, and must be a non-empty array of strings.
58
+ */
59
+ enum?: string[];
36
60
  }
37
61
  interface UniqueConstraintConfig {
38
62
  name: string;
@@ -394,6 +418,17 @@ declare class BaseModel implements StringSetChangeTracker {
394
418
  private ensureLocalChanges;
395
419
  private hasLocalChange;
396
420
  private getFromYjs;
421
+ /**
422
+ * Defensive normalization for the read/sync boundary (issue #625).
423
+ *
424
+ * Stringset fields are owned by getStringSetFromYjs (which expects the
425
+ * raw Y.Map / legacy plain-object shape — #561 / #601), so they pass
426
+ * through untouched. For any other field, a composite Yjs primitive
427
+ * (Y.Map / Y.Array / Y.Text) must never reach user code or the DB layer
428
+ * raw: normalize it to its plain-JS projection (toJSON / toString) and
429
+ * warn, rather than throwing. Scalars pass through unchanged.
430
+ */
431
+ private normalizeNonStringSetValue;
397
432
  private getValue;
398
433
  private setValue;
399
434
  get isDirty(): boolean;
@@ -682,6 +717,25 @@ interface SaveRequest {
682
717
  ifNotExists?: boolean;
683
718
  condition?: DocumentFilter;
684
719
  upsertOn?: string;
720
+ /**
721
+ * Per-call auto-timestamp directives for schemaless writes.
722
+ *
723
+ * Each entry is a list of field names to stamp with `Date.now()`
724
+ * (milliseconds) at the corresponding lifecycle event:
725
+ *
726
+ * - `create` — field is stamped only when the record is new
727
+ * (no row exists yet for this `modelName` + `id`).
728
+ * - `update` — field is stamped on every save (create AND update).
729
+ *
730
+ * If the caller already provided an explicit value for the field
731
+ * in `data`, the explicit value wins and the stamp is skipped.
732
+ * Stamping happens BEFORE the `beforeSave` user hook runs, so user
733
+ * hooks may still overwrite the stamped value if they wish.
734
+ */
735
+ autoStamps?: {
736
+ create?: string[];
737
+ update?: string[];
738
+ };
685
739
  }
686
740
  interface DeleteRequest {
687
741
  modelName: string;
@@ -745,6 +799,17 @@ interface PatchRequest {
745
799
  data: Record<string, any>;
746
800
  stringSets?: Record<string, string[]>;
747
801
  condition?: DocumentFilter;
802
+ /**
803
+ * Per-call auto-timestamp directives. A patch is always treated as
804
+ * an update (`isNew === false`), so only the `update` list is
805
+ * applied; the `create` list is ignored on patch.
806
+ *
807
+ * Explicit values in `data` win.
808
+ */
809
+ autoStamps?: {
810
+ create?: string[];
811
+ update?: string[];
812
+ };
748
813
  }
749
814
  interface PatchResponse {
750
815
  success: boolean;
@@ -760,6 +825,19 @@ interface BatchOperation {
760
825
  ifNotExists?: boolean;
761
826
  condition?: DocumentFilter;
762
827
  upsertOn?: string;
828
+ /**
829
+ * Per-operation auto-timestamp directives. Same semantics as
830
+ * `SaveRequest.autoStamps` / `PatchRequest.autoStamps`. Applied
831
+ * BEFORE the user `beforeSave` hook runs, with explicit values
832
+ * in `data` always winning.
833
+ *
834
+ * For `op: "patch"`, only the `update` list applies (patches are
835
+ * always treated as updates).
836
+ */
837
+ autoStamps?: {
838
+ create?: string[];
839
+ update?: string[];
840
+ };
763
841
  }
764
842
  interface BatchRequest {
765
843
  operations: BatchOperation[];
package/dist/client.d.ts CHANGED
@@ -31,8 +31,32 @@ interface FieldOptions {
31
31
  unique?: boolean;
32
32
  default?: any | (() => any);
33
33
  autoAssign?: boolean;
34
+ /**
35
+ * Auto-timestamp this field with `Date.now()` (milliseconds) on save.
36
+ *
37
+ * - `'create'` — stamp only on the first save (when `isNew === true`).
38
+ * - `'update'` — stamp on every save (create AND update).
39
+ * - `'both'` — stamp on every save (create AND update).
40
+ *
41
+ * If the caller passes an explicit value for the field in `data`, the
42
+ * explicit value wins and the stamp is skipped. The stamp is applied
43
+ * in `beforeSave` BEFORE any user-defined hooks, so user hooks may
44
+ * still overwrite the value if they wish (last writer wins).
45
+ */
46
+ autoStamp?: "create" | "update" | "both";
34
47
  maxLength?: number;
35
48
  maxCount?: number;
49
+ /**
50
+ * Allowed-value set for a `string` field. When present, the codegen
51
+ * generators (database-type codegen + doc-model v2 codegen) emit a
52
+ * TypeScript string-literal union (`"a" | "b" | "c"`) instead of a bare
53
+ * `string` for this field.
54
+ *
55
+ * Advisory / codegen-only: this is a TS-emission hint. The runtime and the
56
+ * server do NOT enforce enum membership on write (see #843). Only valid on
57
+ * `string` fields, and must be a non-empty array of strings.
58
+ */
59
+ enum?: string[];
36
60
  }
37
61
  interface UniqueConstraintConfig {
38
62
  name: string;
@@ -394,6 +418,17 @@ declare class BaseModel implements StringSetChangeTracker {
394
418
  private ensureLocalChanges;
395
419
  private hasLocalChange;
396
420
  private getFromYjs;
421
+ /**
422
+ * Defensive normalization for the read/sync boundary (issue #625).
423
+ *
424
+ * Stringset fields are owned by getStringSetFromYjs (which expects the
425
+ * raw Y.Map / legacy plain-object shape — #561 / #601), so they pass
426
+ * through untouched. For any other field, a composite Yjs primitive
427
+ * (Y.Map / Y.Array / Y.Text) must never reach user code or the DB layer
428
+ * raw: normalize it to its plain-JS projection (toJSON / toString) and
429
+ * warn, rather than throwing. Scalars pass through unchanged.
430
+ */
431
+ private normalizeNonStringSetValue;
397
432
  private getValue;
398
433
  private setValue;
399
434
  get isDirty(): boolean;
@@ -682,6 +717,25 @@ interface SaveRequest {
682
717
  ifNotExists?: boolean;
683
718
  condition?: DocumentFilter;
684
719
  upsertOn?: string;
720
+ /**
721
+ * Per-call auto-timestamp directives for schemaless writes.
722
+ *
723
+ * Each entry is a list of field names to stamp with `Date.now()`
724
+ * (milliseconds) at the corresponding lifecycle event:
725
+ *
726
+ * - `create` — field is stamped only when the record is new
727
+ * (no row exists yet for this `modelName` + `id`).
728
+ * - `update` — field is stamped on every save (create AND update).
729
+ *
730
+ * If the caller already provided an explicit value for the field
731
+ * in `data`, the explicit value wins and the stamp is skipped.
732
+ * Stamping happens BEFORE the `beforeSave` user hook runs, so user
733
+ * hooks may still overwrite the stamped value if they wish.
734
+ */
735
+ autoStamps?: {
736
+ create?: string[];
737
+ update?: string[];
738
+ };
685
739
  }
686
740
  interface DeleteRequest {
687
741
  modelName: string;
@@ -745,6 +799,17 @@ interface PatchRequest {
745
799
  data: Record<string, any>;
746
800
  stringSets?: Record<string, string[]>;
747
801
  condition?: DocumentFilter;
802
+ /**
803
+ * Per-call auto-timestamp directives. A patch is always treated as
804
+ * an update (`isNew === false`), so only the `update` list is
805
+ * applied; the `create` list is ignored on patch.
806
+ *
807
+ * Explicit values in `data` win.
808
+ */
809
+ autoStamps?: {
810
+ create?: string[];
811
+ update?: string[];
812
+ };
748
813
  }
749
814
  interface PatchResponse {
750
815
  success: boolean;
@@ -760,6 +825,19 @@ interface BatchOperation {
760
825
  ifNotExists?: boolean;
761
826
  condition?: DocumentFilter;
762
827
  upsertOn?: string;
828
+ /**
829
+ * Per-operation auto-timestamp directives. Same semantics as
830
+ * `SaveRequest.autoStamps` / `PatchRequest.autoStamps`. Applied
831
+ * BEFORE the user `beforeSave` hook runs, with explicit values
832
+ * in `data` always winning.
833
+ *
834
+ * For `op: "patch"`, only the `update` list applies (patches are
835
+ * always treated as updates).
836
+ */
837
+ autoStamps?: {
838
+ create?: string[];
839
+ update?: string[];
840
+ };
763
841
  }
764
842
  interface BatchRequest {
765
843
  operations: BatchOperation[];
package/dist/client.js CHANGED
@@ -57,8 +57,16 @@ var init_DocumentQueryTranslator = __esm({
57
57
  }
58
58
  });
59
59
 
60
- // src/models/metaSync.ts
60
+ // src/utils/yjsValues.ts
61
61
  import * as Y from "yjs";
62
+ var init_yjsValues = __esm({
63
+ "src/utils/yjsValues.ts"() {
64
+ "use strict";
65
+ }
66
+ });
67
+
68
+ // src/models/metaSync.ts
69
+ import * as Y2 from "yjs";
62
70
  function registerFunctionDefault(fn, name) {
63
71
  KNOWN_FUNCTION_DEFAULTS.set(fn, name);
64
72
  }
@@ -66,12 +74,13 @@ var KNOWN_FUNCTION_DEFAULTS;
66
74
  var init_metaSync = __esm({
67
75
  "src/models/metaSync.ts"() {
68
76
  "use strict";
77
+ init_yjsValues();
69
78
  KNOWN_FUNCTION_DEFAULTS = /* @__PURE__ */ new WeakMap();
70
79
  }
71
80
  });
72
81
 
73
82
  // src/models/BaseModel.ts
74
- import * as Y2 from "yjs";
83
+ import * as Y3 from "yjs";
75
84
  import { ulid } from "ulid";
76
85
  function generateULID() {
77
86
  return ulid();
@@ -86,6 +95,7 @@ var init_BaseModel = __esm({
86
95
  init_CursorManager();
87
96
  init_sql();
88
97
  init_metaSync();
98
+ init_yjsValues();
89
99
  Logger = class {
90
100
  static _logLevel = 1 /* ERROR */;
91
101
  static _logCallback = null;