@fjell/core 4.4.61 → 4.4.63
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/errors/ActionError.d.ts +1 -0
- package/dist/errors/ValidationError.d.ts +7 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +17 -11
- package/dist/operations/Operations.d.ts +72 -2
- package/dist/operations/methods.d.ts +3 -3
- package/dist/operations/wrappers/createUpsertWrapper.d.ts +3 -3
- package/package.json +1 -1
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { ActionError } from './ActionError';
|
|
2
|
+
export interface FieldError {
|
|
3
|
+
path: (string | number)[];
|
|
4
|
+
message: string;
|
|
5
|
+
code: string;
|
|
6
|
+
}
|
|
2
7
|
export declare class ValidationError extends ActionError {
|
|
3
|
-
|
|
8
|
+
fieldErrors?: FieldError[];
|
|
9
|
+
constructor(message: string, validOptions?: string[], suggestedAction?: string, conflictingValue?: any, fieldErrors?: FieldError[]);
|
|
4
10
|
}
|
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
|
@@ -1300,7 +1300,8 @@ var ActionError = class extends Error {
|
|
|
1300
1300
|
|
|
1301
1301
|
// src/errors/ValidationError.ts
|
|
1302
1302
|
var ValidationError = class extends ActionError {
|
|
1303
|
-
|
|
1303
|
+
fieldErrors;
|
|
1304
|
+
constructor(message, validOptions, suggestedAction, conflictingValue, fieldErrors) {
|
|
1304
1305
|
super({
|
|
1305
1306
|
code: "VALIDATION_ERROR",
|
|
1306
1307
|
message,
|
|
@@ -1312,12 +1313,18 @@ var ValidationError = class extends ActionError {
|
|
|
1312
1313
|
validOptions,
|
|
1313
1314
|
suggestedAction,
|
|
1314
1315
|
retryable: true,
|
|
1315
|
-
conflictingValue
|
|
1316
|
+
conflictingValue,
|
|
1317
|
+
fieldErrors
|
|
1316
1318
|
},
|
|
1317
1319
|
technical: {
|
|
1318
1320
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
1319
1321
|
}
|
|
1320
1322
|
});
|
|
1323
|
+
this.fieldErrors = fieldErrors;
|
|
1324
|
+
if (fieldErrors) {
|
|
1325
|
+
if (!this.errorInfo.details) this.errorInfo.details = {};
|
|
1326
|
+
this.errorInfo.details.fieldErrors = fieldErrors;
|
|
1327
|
+
}
|
|
1321
1328
|
}
|
|
1322
1329
|
};
|
|
1323
1330
|
|
|
@@ -1953,9 +1960,9 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
|
|
|
1953
1960
|
var logger13 = logger_default.get("operations", "wrappers", "update");
|
|
1954
1961
|
function createUpdateWrapper(coordinate, implementation, options = {}) {
|
|
1955
1962
|
const operationName = options.operationName || "update";
|
|
1956
|
-
return async (key, item) => {
|
|
1963
|
+
return async (key, item, updateOptions) => {
|
|
1957
1964
|
if (options.debug) {
|
|
1958
|
-
logger13.debug(`[${operationName}] Called with:`, { key, item });
|
|
1965
|
+
logger13.debug(`[${operationName}] Called with:`, { key, item, updateOptions });
|
|
1959
1966
|
}
|
|
1960
1967
|
if (!options.skipValidation) {
|
|
1961
1968
|
validateKey(key, coordinate, operationName);
|
|
@@ -1969,7 +1976,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
|
|
|
1969
1976
|
}
|
|
1970
1977
|
}
|
|
1971
1978
|
try {
|
|
1972
|
-
const result = await implementation(key, item);
|
|
1979
|
+
const result = await implementation(key, item, updateOptions);
|
|
1973
1980
|
if (options.debug) {
|
|
1974
1981
|
logger13.debug(`[${operationName}] Updated item:`, result.key);
|
|
1975
1982
|
}
|
|
@@ -1981,7 +1988,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
|
|
|
1981
1988
|
if (options.onError) {
|
|
1982
1989
|
const context = {
|
|
1983
1990
|
operationName,
|
|
1984
|
-
params: [key, item],
|
|
1991
|
+
params: [key, item, updateOptions],
|
|
1985
1992
|
coordinate
|
|
1986
1993
|
};
|
|
1987
1994
|
throw options.onError(error, context);
|
|
@@ -1998,13 +2005,12 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
|
|
|
1998
2005
|
var logger14 = logger_default.get("operations", "wrappers", "upsert");
|
|
1999
2006
|
function createUpsertWrapper(coordinate, implementation, options = {}) {
|
|
2000
2007
|
const operationName = options.operationName || "upsert";
|
|
2001
|
-
return async (key, item, locations) => {
|
|
2008
|
+
return async (key, item, locations, updateOptions) => {
|
|
2002
2009
|
if (options.debug) {
|
|
2003
|
-
logger14.debug(`[${operationName}] Called with:`, { key, item, locations });
|
|
2010
|
+
logger14.debug(`[${operationName}] Called with:`, { key, item, locations, updateOptions });
|
|
2004
2011
|
}
|
|
2005
2012
|
if (!options.skipValidation) {
|
|
2006
2013
|
validateKey(key, coordinate, operationName);
|
|
2007
|
-
validateLocations(locations, coordinate, operationName);
|
|
2008
2014
|
if (!item || typeof item !== "object" || Array.isArray(item)) {
|
|
2009
2015
|
throw new Error(
|
|
2010
2016
|
`[${operationName}] Invalid item parameter.
|
|
@@ -2015,7 +2021,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
|
|
|
2015
2021
|
}
|
|
2016
2022
|
}
|
|
2017
2023
|
try {
|
|
2018
|
-
const result = await implementation(key, item);
|
|
2024
|
+
const result = await implementation(key, item, locations, updateOptions);
|
|
2019
2025
|
if (options.debug) {
|
|
2020
2026
|
logger14.debug(`[${operationName}] Upserted item:`, result.key);
|
|
2021
2027
|
}
|
|
@@ -2027,7 +2033,7 @@ Received: ${Array.isArray(item) ? "array" : typeof item}`
|
|
|
2027
2033
|
if (options.onError) {
|
|
2028
2034
|
const context = {
|
|
2029
2035
|
operationName,
|
|
2030
|
-
params: [key, item, locations],
|
|
2036
|
+
params: [key, item, locations, updateOptions],
|
|
2031
2037
|
coordinate
|
|
2032
2038
|
};
|
|
2033
2039
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
* ```
|