@fjell/core 4.4.61 → 4.4.62

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/index.d.ts CHANGED
@@ -15,7 +15,7 @@ export * from './validation';
15
15
  export * from './errors';
16
16
  export * from './operations';
17
17
  export * from './event';
18
- export type { Operations, OperationParams, AffectedKeys, CreateOptions } from './operations/Operations';
18
+ export type { Operations, OperationParams, AffectedKeys, CreateOptions, UpdateOptions } from './operations/Operations';
19
19
  export { isPriKey as isOperationPriKey, isComKey as isOperationComKey } from './operations/Operations';
20
20
  export type { GetMethod, CreateMethod, UpdateMethod, RemoveMethod, UpsertMethod, AllMethod, OneMethod, FindMethod, FindOneMethod, FinderMethod, ActionMethod, ActionOperationMethod, AllActionMethod, AllActionOperationMethod, FacetMethod, FacetOperationMethod, AllFacetMethod, AllFacetOperationMethod, OperationsExtensions } from './operations/methods';
21
21
  export * from './operations/wrappers';
package/dist/index.js CHANGED
@@ -1953,9 +1953,9 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
1953
1953
  var logger13 = logger_default.get("operations", "wrappers", "update");
1954
1954
  function createUpdateWrapper(coordinate, implementation, options = {}) {
1955
1955
  const operationName = options.operationName || "update";
1956
- return async (key, item) => {
1956
+ return async (key, item, updateOptions) => {
1957
1957
  if (options.debug) {
1958
- logger13.debug(`[${operationName}] Called with:`, { key, item });
1958
+ logger13.debug(`[${operationName}] Called with:`, { key, item, updateOptions });
1959
1959
  }
1960
1960
  if (!options.skipValidation) {
1961
1961
  validateKey(key, coordinate, operationName);
@@ -1969,7 +1969,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
1969
1969
  }
1970
1970
  }
1971
1971
  try {
1972
- const result = await implementation(key, item);
1972
+ const result = await implementation(key, item, updateOptions);
1973
1973
  if (options.debug) {
1974
1974
  logger13.debug(`[${operationName}] Updated item:`, result.key);
1975
1975
  }
@@ -1981,7 +1981,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
1981
1981
  if (options.onError) {
1982
1982
  const context = {
1983
1983
  operationName,
1984
- params: [key, item],
1984
+ params: [key, item, updateOptions],
1985
1985
  coordinate
1986
1986
  };
1987
1987
  throw options.onError(error, context);
@@ -1998,13 +1998,12 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
1998
1998
  var logger14 = logger_default.get("operations", "wrappers", "upsert");
1999
1999
  function createUpsertWrapper(coordinate, implementation, options = {}) {
2000
2000
  const operationName = options.operationName || "upsert";
2001
- return async (key, item, locations) => {
2001
+ return async (key, item, locations, updateOptions) => {
2002
2002
  if (options.debug) {
2003
- logger14.debug(`[${operationName}] Called with:`, { key, item, locations });
2003
+ logger14.debug(`[${operationName}] Called with:`, { key, item, locations, updateOptions });
2004
2004
  }
2005
2005
  if (!options.skipValidation) {
2006
2006
  validateKey(key, coordinate, operationName);
2007
- validateLocations(locations, coordinate, operationName);
2008
2007
  if (!item || typeof item !== "object" || Array.isArray(item)) {
2009
2008
  throw new Error(
2010
2009
  `[${operationName}] Invalid item parameter.
@@ -2015,7 +2014,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
2015
2014
  }
2016
2015
  }
2017
2016
  try {
2018
- const result = await implementation(key, item);
2017
+ const result = await implementation(key, item, locations, updateOptions);
2019
2018
  if (options.debug) {
2020
2019
  logger14.debug(`[${operationName}] Upserted item:`, result.key);
2021
2020
  }
@@ -2027,7 +2026,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
2027
2026
  if (options.onError) {
2028
2027
  const context = {
2029
2028
  operationName,
2030
- params: [key, item, locations],
2029
+ params: [key, item, locations, updateOptions],
2031
2030
  coordinate
2032
2031
  };
2033
2032
  throw options.onError(error, context);
@@ -19,6 +19,62 @@ export type CreateOptions<S extends string, L1 extends string = never, L2 extend
19
19
  key?: never;
20
20
  locations: LocKeyArray<L1, L2, L3, L4, L5>;
21
21
  };
22
+ /**
23
+ * Options for update operations across all Fjell libraries.
24
+ *
25
+ * These options provide explicit control over update behavior,
26
+ * with safe defaults that prevent accidental data loss.
27
+ *
28
+ * @public
29
+ */
30
+ export interface UpdateOptions {
31
+ /**
32
+ * Controls whether the update replaces the entire document/record or merges with existing data.
33
+ *
34
+ * **Default: `false` (merge/partial update)**
35
+ *
36
+ * When `false` (default):
37
+ * - Only the specified fields are updated
38
+ * - All other existing fields are preserved
39
+ * - Safe for partial updates
40
+ * - Recommended for most use cases
41
+ *
42
+ * When `true`:
43
+ * - The entire document/record is replaced with the provided data
44
+ * - Any fields not included in the update payload are DELETED
45
+ * - Use with extreme caution
46
+ * - Logs warning before operation (in implementations)
47
+ *
48
+ * ⚠️ **WARNING**: Setting `replace: true` can lead to permanent data loss.
49
+ * Always verify that your update payload contains ALL fields you want to preserve.
50
+ *
51
+ * @default false
52
+ *
53
+ * @example Merge update (default - safe)
54
+ * ```typescript
55
+ * // Existing: { id: '123', name: 'John', email: 'john@example.com', status: 'active' }
56
+ * await operations.update(
57
+ * { kt: 'user', pk: '123' },
58
+ * { status: 'inactive' }
59
+ * );
60
+ * // Result: { id: '123', name: 'John', email: 'john@example.com', status: 'inactive' }
61
+ * // ✅ All fields preserved except status
62
+ * ```
63
+ *
64
+ * @example Full replacement (use with caution)
65
+ * ```typescript
66
+ * // Existing: { id: '123', name: 'John', email: 'john@example.com', status: 'active' }
67
+ * await operations.update(
68
+ * { kt: 'user', pk: '123' },
69
+ * { status: 'inactive' },
70
+ * { replace: true }
71
+ * );
72
+ * // Result: { status: 'inactive' }
73
+ * // ❌ name and email are DELETED!
74
+ * ```
75
+ */
76
+ replace?: boolean;
77
+ }
22
78
  /**
23
79
  * Core Operations interface for Item-based data access.
24
80
  * This interface defines the standard contract for all fjell libraries
@@ -119,18 +175,32 @@ export interface Operations<V extends Item<S, L1, L2, L3, L4, L5>, S extends str
119
175
  *
120
176
  * @param key - Primary or composite key
121
177
  * @param item - Partial item properties to update
178
+ * @param options - Optional update options (controls merge vs replace behavior)
122
179
  * @returns The updated item
180
+ *
181
+ * @example Merge update (default - safe)
182
+ * ```typescript
183
+ * await operations.update(key, { status: 'active' });
184
+ * // Merges with existing data, preserves other fields
185
+ * ```
186
+ *
187
+ * @example Replace update (dangerous)
188
+ * ```typescript
189
+ * await operations.update(key, { status: 'active' }, { replace: true });
190
+ * // Replaces entire document, deletes unspecified fields
191
+ * ```
123
192
  */
124
- update(key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>): Promise<V>;
193
+ update(key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>, options?: UpdateOptions): Promise<V>;
125
194
  /**
126
195
  * Updates an item if it exists, creates it if it doesn't.
127
196
  *
128
197
  * @param key - Primary or composite key
129
198
  * @param item - Partial item properties
130
199
  * @param locations - Optional locations for creation
200
+ * @param options - Optional update options (used only if item exists, ignored for creation)
131
201
  * @returns The upserted item
132
202
  */
133
- upsert(key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>, locations?: LocKeyArray<L1, L2, L3, L4, L5>): Promise<V>;
203
+ upsert(key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>, locations?: LocKeyArray<L1, L2, L3, L4, L5>, options?: UpdateOptions): Promise<V>;
134
204
  /**
135
205
  * Removes an item.
136
206
  *
@@ -1,7 +1,7 @@
1
1
  import { Item } from "../items";
2
2
  import { ComKey, LocKeyArray, PriKey } from "../keys";
3
3
  import { ItemQuery } from "../item/ItemQuery";
4
- import { AffectedKeys, CreateOptions, OperationParams } from "./Operations";
4
+ import { AffectedKeys, CreateOptions, OperationParams, UpdateOptions } from "./Operations";
5
5
  /**
6
6
  * Get method signature - retrieves single item by key
7
7
  */
@@ -18,7 +18,7 @@ export interface CreateMethod<V extends Item<S, L1, L2, L3, L4, L5>, S extends s
18
18
  * Update method signature - updates existing item
19
19
  */
20
20
  export interface UpdateMethod<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
21
- (key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>): Promise<V>;
21
+ (key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>, options?: UpdateOptions): Promise<V>;
22
22
  }
23
23
  /**
24
24
  * Remove method signature - removes item
@@ -30,7 +30,7 @@ export interface RemoveMethod<V extends Item<S, L1, L2, L3, L4, L5>, S extends s
30
30
  * Upsert method signature - updates or creates item
31
31
  */
32
32
  export interface UpsertMethod<V extends Item<S, L1, L2, L3, L4, L5>, S extends string, L1 extends string = never, L2 extends string = never, L3 extends string = never, L4 extends string = never, L5 extends string = never> {
33
- (key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>): Promise<V>;
33
+ (key: PriKey<S> | ComKey<S, L1, L2, L3, L4, L5>, item: Partial<Item<S, L1, L2, L3, L4, L5>>, locations?: LocKeyArray<L1, L2, L3, L4, L5>, options?: UpdateOptions): Promise<V>;
34
34
  }
35
35
  /**
36
36
  * All method signature - retrieves all items matching query
@@ -3,8 +3,8 @@
3
3
  *
4
4
  * Provides automatic validation for upsert() operation parameters.
5
5
  */
6
- import type { Item } from "../../items";
7
6
  import type { Coordinate } from "../../Coordinate";
7
+ import type { Item } from "../../items";
8
8
  import type { UpsertMethod } from "../methods";
9
9
  import type { WrapperOptions } from "./types";
10
10
  /**
@@ -19,8 +19,8 @@ import type { WrapperOptions } from "./types";
19
19
  * ```typescript
20
20
  * const upsert = createUpsertWrapper(
21
21
  * coordinate,
22
- * async (key, item, locations) => {
23
- * return await database.upsert(key, item, locations);
22
+ * async (key, item, locations, options) => {
23
+ * return await database.upsert(key, item, locations, options);
24
24
  * }
25
25
  * );
26
26
  * ```
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fjell/core",
3
3
  "description": "Core Item and Key Framework for Fjell",
4
- "version": "4.4.61",
4
+ "version": "4.4.62",
5
5
  "keywords": [
6
6
  "core",
7
7
  "fjell"