@fjell/client-api 4.4.46 → 4.4.48
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/package.json +22 -21
- package/LOCATION_KEY_ORDERING.md +0 -153
- package/LOCATION_KEY_VALIDATION_UPDATE.md +0 -120
- package/MIGRATION_v3.md +0 -231
- package/vitest.config.ts +0 -22
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fjell/client-api",
|
|
3
3
|
"description": "Client API for Fjell",
|
|
4
|
-
"version": "4.4.
|
|
4
|
+
"version": "4.4.48",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"client",
|
|
7
7
|
"api",
|
|
@@ -38,30 +38,31 @@
|
|
|
38
38
|
"docs:test": "cd docs && npm run test"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@fjell/core": "^4.4.
|
|
42
|
-
"@fjell/http-api": "^4.4.
|
|
43
|
-
"@fjell/logging": "^4.4.
|
|
44
|
-
"@fjell/registry": "^4.4.
|
|
41
|
+
"@fjell/core": "^4.4.53",
|
|
42
|
+
"@fjell/http-api": "^4.4.45",
|
|
43
|
+
"@fjell/logging": "^4.4.52",
|
|
44
|
+
"@fjell/registry": "^4.4.55",
|
|
45
45
|
"deepmerge": "^4.3.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@eslint/eslintrc": "^3.3.1",
|
|
49
|
-
"@eslint/js": "^9.
|
|
50
|
-
"@fjell/
|
|
49
|
+
"@eslint/js": "^9.38.0",
|
|
50
|
+
"@fjell/common-config": "^1.1.29",
|
|
51
51
|
"@tsconfig/recommended": "^1.0.10",
|
|
52
|
-
"@types/node": "^24.
|
|
53
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
54
|
-
"@typescript-eslint/parser": "^8.
|
|
55
|
-
"@vitest/coverage-istanbul": "^
|
|
56
|
-
"@vitest/coverage-v8": "^
|
|
57
|
-
"@vitest/ui": "^
|
|
58
|
-
"concurrently": "^9.2.
|
|
59
|
-
"esbuild": "0.25.
|
|
60
|
-
"eslint": "^9.
|
|
61
|
-
"jsdom": "^
|
|
62
|
-
"
|
|
63
|
-
"
|
|
64
|
-
"
|
|
52
|
+
"@types/node": "^24.9.1",
|
|
53
|
+
"@typescript-eslint/eslint-plugin": "^8.46.2",
|
|
54
|
+
"@typescript-eslint/parser": "^8.46.2",
|
|
55
|
+
"@vitest/coverage-istanbul": "^4.0.1",
|
|
56
|
+
"@vitest/coverage-v8": "^4.0.1",
|
|
57
|
+
"@vitest/ui": "^4.0.1",
|
|
58
|
+
"concurrently": "^9.2.1",
|
|
59
|
+
"esbuild": "0.25.11",
|
|
60
|
+
"eslint": "^9.38.0",
|
|
61
|
+
"jsdom": "^27.0.1",
|
|
62
|
+
"prismjs": ">=1.30.0",
|
|
63
|
+
"typescript": "^5.9.3",
|
|
64
|
+
"undici": "^7.16.0",
|
|
65
|
+
"vitest": "^4.0.1",
|
|
65
66
|
"vitest-fetch-mock": "^0.4.5"
|
|
66
67
|
},
|
|
67
68
|
"repository": {
|
|
@@ -69,6 +70,6 @@
|
|
|
69
70
|
"url": "git+https://github.com/getfjell/client-api.git"
|
|
70
71
|
},
|
|
71
72
|
"overrides": {
|
|
72
|
-
"esbuild": "0.25.
|
|
73
|
+
"esbuild": "0.25.11"
|
|
73
74
|
}
|
|
74
75
|
}
|
package/LOCATION_KEY_ORDERING.md
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
# Location Key Ordering in Client API
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
When accessing nested/contained entities in Fjell, the **order of location keys matters**. The client API now includes **automatic validation** that will throw an error if location keys are passed in the wrong order, preventing malformed URL paths from being generated.
|
|
6
|
-
|
|
7
|
-
## Automatic Validation (New Feature)
|
|
8
|
-
|
|
9
|
-
As of this update, the client API automatically validates location key ordering and will throw a descriptive error if keys are out of order. This prevents silent failures where malformed paths would result in 404 errors.
|
|
10
|
-
|
|
11
|
-
### What Gets Validated
|
|
12
|
-
|
|
13
|
-
- Location keys must appear in ascending order according to the `pathNames` hierarchy
|
|
14
|
-
- The validation compares each key's type (`kt`) against the `pathNames` array
|
|
15
|
-
- If a key appears "earlier" in the hierarchy than the previous key, an error is thrown
|
|
16
|
-
|
|
17
|
-
### Example Validation Error
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
Error: Location keys must be ordered from parent to child according to the entity hierarchy.
|
|
21
|
-
Expected order based on pathNames: [fjell/order, orderForm, orderNoseShape].
|
|
22
|
-
Received key types in order: [orderForm, order].
|
|
23
|
-
Key "order" is out of order - it should appear earlier in the hierarchy.
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
## How It Works
|
|
27
|
-
|
|
28
|
-
The `getPath()` function in `Utilities.ts` processes keys in the order they are provided. The new `validateLocationKeyOrder()` function checks that location keys match the expected hierarchy before building the path.
|
|
29
|
-
|
|
30
|
-
### Example: Three-Level Hierarchy
|
|
31
|
-
|
|
32
|
-
Given this entity hierarchy:
|
|
33
|
-
```
|
|
34
|
-
order (primary)
|
|
35
|
-
└─ orderForm (contained in order)
|
|
36
|
-
└─ orderNoseShape (contained in orderForm)
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
With `pathNames: ["fjell/order", "orderForm", "orderNoseShape"]`
|
|
40
|
-
|
|
41
|
-
### ✅ Correct Usage
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
const orderKey: LocKey<"order"> = { kt: "order", lk: "26669" };
|
|
45
|
-
const orderFormKey: LocKey<"orderForm"> = { kt: "orderForm", lk: "26693" };
|
|
46
|
-
|
|
47
|
-
// Keys must be ordered from PARENT to CHILD
|
|
48
|
-
const locations = [orderKey, orderFormKey];
|
|
49
|
-
|
|
50
|
-
api.one({}, locations);
|
|
51
|
-
// Result: /fjell/order/26669/orderForm/26693/orderNoseShape ✅
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### ❌ Wrong Usage (Now Throws Error)
|
|
55
|
-
|
|
56
|
-
```typescript
|
|
57
|
-
// WRONG: orderForm before order
|
|
58
|
-
const locations = [orderFormKey, orderKey];
|
|
59
|
-
|
|
60
|
-
api.one({}, locations);
|
|
61
|
-
// Throws Error: Location keys must be ordered from parent to child according to the entity hierarchy.
|
|
62
|
-
// Expected order based on pathNames: [fjell/order, orderForm, orderNoseShape].
|
|
63
|
-
// Received key types in order: [orderForm, order].
|
|
64
|
-
// Key "order" is out of order - it should appear earlier in the hierarchy.
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
**Before this update:** This would have silently created a malformed path: `/orderForm/26693/fjell/order/26669/orderNoseShape`
|
|
68
|
-
|
|
69
|
-
**Now:** An error is thrown immediately, making the issue obvious and preventing network requests with bad paths.
|
|
70
|
-
|
|
71
|
-
## Rules for Location Key Ordering
|
|
72
|
-
|
|
73
|
-
1. **Always order from outermost to innermost**: `[grandparent, parent, child]`
|
|
74
|
-
2. **Match the hierarchy defined by your data model**: The order should reflect how entities are nested
|
|
75
|
-
3. **For ComKeys**: The `loc` array should also follow this ordering
|
|
76
|
-
|
|
77
|
-
### ComKey Example
|
|
78
|
-
|
|
79
|
-
```typescript
|
|
80
|
-
// For accessing a specific orderNoseShape item
|
|
81
|
-
const comKey = {
|
|
82
|
-
kt: "orderNoseShape",
|
|
83
|
-
pk: "nose-123",
|
|
84
|
-
loc: [
|
|
85
|
-
{ kt: "order", lk: "26669" }, // Parent first
|
|
86
|
-
{ kt: "orderForm", lk: "26693" } // Child second
|
|
87
|
-
]
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
api.get(comKey);
|
|
91
|
-
// Result: /fjell/order/26669/orderForm/26693/orderNoseShape/nose-123 ✅
|
|
92
|
-
```
|
|
93
|
-
|
|
94
|
-
## Debugging Tips
|
|
95
|
-
|
|
96
|
-
1. **Enable logging**: The `Utilities.ts` logger logs the keys and pathNames being processed
|
|
97
|
-
2. **Check the generated path**: Use browser DevTools Network tab to see the actual HTTP request
|
|
98
|
-
3. **Verify key order**: Print/log your `locations` array before passing it to API methods
|
|
99
|
-
4. **Use the type system**: TypeScript generics enforce the location types but not their order
|
|
100
|
-
|
|
101
|
-
## Common Mistakes
|
|
102
|
-
|
|
103
|
-
### Mistake 1: Building keys in reverse
|
|
104
|
-
```typescript
|
|
105
|
-
// Building keys as you traverse from child to parent
|
|
106
|
-
const keys = [];
|
|
107
|
-
keys.push(orderFormKey); // ❌ Adding child first
|
|
108
|
-
keys.push(orderKey); // ❌ Adding parent second
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
**Fix**: Build keys from parent to child
|
|
112
|
-
```typescript
|
|
113
|
-
const keys = [];
|
|
114
|
-
keys.push(orderKey); // ✅ Parent first
|
|
115
|
-
keys.push(orderFormKey); // ✅ Child second
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
### Mistake 2: Not considering the full hierarchy
|
|
119
|
-
```typescript
|
|
120
|
-
// Only providing the immediate parent
|
|
121
|
-
const locations = [orderFormKey]; // ❌ Missing orderKey
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
**Fix**: Include all ancestors
|
|
125
|
-
```typescript
|
|
126
|
-
const locations = [orderKey, orderFormKey]; // ✅ Complete hierarchy
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
## Test Coverage
|
|
130
|
-
|
|
131
|
-
See `tests/Utilities.test.ts` for comprehensive examples:
|
|
132
|
-
- ✅ Correct ordering: "should generate path for collection access with location keys only"
|
|
133
|
-
- ✅ Error on wrong ordering: "should throw error when location keys are in wrong order"
|
|
134
|
-
- ✅ ComKey usage: "should generate path for nested entities with correct order"
|
|
135
|
-
- ✅ Error message validation: "should throw error with helpful message explaining the issue"
|
|
136
|
-
|
|
137
|
-
## Benefits of Validation
|
|
138
|
-
|
|
139
|
-
1. **Fail fast**: Errors are caught immediately at the API call site, not after a failed HTTP request
|
|
140
|
-
2. **Clear error messages**: The error tells you exactly what went wrong and what the correct order should be
|
|
141
|
-
3. **Prevents debugging confusion**: No more hunting through logs to figure out why you're getting 404 errors
|
|
142
|
-
4. **Type-safe**: Works seamlessly with TypeScript's type system
|
|
143
|
-
5. **Zero runtime cost for correct code**: Validation only runs when keys are actually used
|
|
144
|
-
|
|
145
|
-
## Implementation Details
|
|
146
|
-
|
|
147
|
-
The validation function (`validateLocationKeyOrder` in `Utilities.ts`):
|
|
148
|
-
- Extracts location keys from the provided keys array
|
|
149
|
-
- Builds a map of key types to their expected position in the hierarchy
|
|
150
|
-
- Validates that location keys appear in strictly ascending order
|
|
151
|
-
- Throws a detailed error if validation fails
|
|
152
|
-
- Handles path segments with slashes (e.g., "fjell/order" matches key type "order")
|
|
153
|
-
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
# Location Key Validation Update
|
|
2
|
-
|
|
3
|
-
## Summary
|
|
4
|
-
|
|
5
|
-
Added automatic runtime validation to the `client-api` library that prevents location keys from being passed in the wrong order. This validation throws a clear, actionable error message instead of silently generating malformed URL paths.
|
|
6
|
-
|
|
7
|
-
## Problem Being Solved
|
|
8
|
-
|
|
9
|
-
Previously, if location keys were passed in the wrong order (e.g., `[orderFormKey, orderKey]` instead of `[orderKey, orderFormKey]`), the library would silently generate a malformed URL path like:
|
|
10
|
-
```
|
|
11
|
-
/orderForm/26693/fjell/order/26669/orderNoseShape
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
Instead of the correct:
|
|
15
|
-
```
|
|
16
|
-
/fjell/order/26669/orderForm/26693/orderNoseShape
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
This resulted in 404 errors that were difficult to debug.
|
|
20
|
-
|
|
21
|
-
## Solution Implemented
|
|
22
|
-
|
|
23
|
-
### 1. Runtime Validation Function
|
|
24
|
-
|
|
25
|
-
Added `validateLocationKeyOrder()` in `src/Utilities.ts` that:
|
|
26
|
-
- Extracts location keys from the provided keys array
|
|
27
|
-
- Builds a map of key types to their expected hierarchy position
|
|
28
|
-
- Validates that location keys appear in strictly ascending order
|
|
29
|
-
- Handles path segments with slashes (e.g., "fjell/order" correctly matches key type "order")
|
|
30
|
-
- Throws a descriptive error if validation fails
|
|
31
|
-
|
|
32
|
-
### 2. Validation Error Message
|
|
33
|
-
|
|
34
|
-
When keys are out of order, users get a clear error:
|
|
35
|
-
```
|
|
36
|
-
Error: Location keys must be ordered from parent to child according to the entity hierarchy.
|
|
37
|
-
Expected order based on pathNames: [fjell/order, orderForm, orderNoseShape].
|
|
38
|
-
Received key types in order: [orderForm, order].
|
|
39
|
-
Key "order" is out of order - it should appear earlier in the hierarchy.
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 3. Test Coverage
|
|
43
|
-
|
|
44
|
-
Added comprehensive tests in `tests/Utilities.test.ts`:
|
|
45
|
-
- ✅ `should generate path for nested entities with correct order`
|
|
46
|
-
- ✅ `should generate path for collection access with location keys only`
|
|
47
|
-
- ✅ `should throw error when location keys are in wrong order`
|
|
48
|
-
- ✅ `should throw error with helpful message explaining the issue`
|
|
49
|
-
|
|
50
|
-
### 4. Documentation
|
|
51
|
-
|
|
52
|
-
Created/updated documentation:
|
|
53
|
-
- `LOCATION_KEY_ORDERING.md` - Complete guide on location key ordering with examples
|
|
54
|
-
- Explains the validation, shows correct vs incorrect usage
|
|
55
|
-
- Documents benefits and implementation details
|
|
56
|
-
|
|
57
|
-
## Benefits
|
|
58
|
-
|
|
59
|
-
1. **Fail Fast**: Errors caught at API call site, not after HTTP request
|
|
60
|
-
2. **Clear Error Messages**: Tells exactly what's wrong and the correct order
|
|
61
|
-
3. **Prevents Debugging Confusion**: No more hunting through logs for 404 causes
|
|
62
|
-
4. **Type-Safe + Runtime Safe**: TypeScript types prevent wrong order at compile time, runtime validation catches dynamic cases
|
|
63
|
-
5. **Zero Performance Cost for Correct Code**: Validation only runs when building paths
|
|
64
|
-
|
|
65
|
-
## Backwards Compatibility
|
|
66
|
-
|
|
67
|
-
✅ **Fully backwards compatible** - only throws errors for code that was already broken (passing keys in wrong order, which would have resulted in 404s)
|
|
68
|
-
|
|
69
|
-
## Files Changed
|
|
70
|
-
|
|
71
|
-
1. `src/Utilities.ts` - Added `validateLocationKeyOrder()` function and integrated it into `getPath()`
|
|
72
|
-
2. `tests/Utilities.test.ts` - Added 4 new tests for validation behavior
|
|
73
|
-
3. `LOCATION_KEY_ORDERING.md` - New comprehensive documentation
|
|
74
|
-
4. `LOCATION_KEY_VALIDATION_UPDATE.md` - This summary document
|
|
75
|
-
|
|
76
|
-
## Test Results
|
|
77
|
-
|
|
78
|
-
All 302 tests pass across the entire test suite:
|
|
79
|
-
```
|
|
80
|
-
Test Files 22 passed (22)
|
|
81
|
-
Tests 302 passed (302)
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
Coverage for `Utilities.ts`: **94.97%**
|
|
85
|
-
|
|
86
|
-
## Example Usage
|
|
87
|
-
|
|
88
|
-
### Before (Silent Failure)
|
|
89
|
-
```typescript
|
|
90
|
-
const locations = [orderFormKey, orderKey]; // Wrong order!
|
|
91
|
-
const items = await api.one({}, locations);
|
|
92
|
-
// Result: 404 error with confusing path
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### After (Clear Error)
|
|
96
|
-
```typescript
|
|
97
|
-
const locations = [orderFormKey, orderKey]; // Wrong order!
|
|
98
|
-
const items = await api.one({}, locations);
|
|
99
|
-
// Throws immediately:
|
|
100
|
-
// Error: Location keys must be ordered from parent to child...
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
### Correct Usage
|
|
104
|
-
```typescript
|
|
105
|
-
const locations = [orderKey, orderFormKey]; // Correct order!
|
|
106
|
-
const items = await api.one({}, locations);
|
|
107
|
-
// Result: Success! ✅
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
## Recommendation for Your Project
|
|
111
|
-
|
|
112
|
-
In your other project where you're experiencing the path ordering issue:
|
|
113
|
-
|
|
114
|
-
1. **Update the `@fjell/client-api` dependency** to get this validation
|
|
115
|
-
2. **Run your code** - the validation will immediately show you where keys are in wrong order
|
|
116
|
-
3. **Fix the order** based on the error messages
|
|
117
|
-
4. **Verify** the fix by checking that API calls succeed
|
|
118
|
-
|
|
119
|
-
The validation will pinpoint exactly which API calls have keys in the wrong order and what the correct order should be.
|
|
120
|
-
|
package/MIGRATION_v3.md
DELETED
|
@@ -1,231 +0,0 @@
|
|
|
1
|
-
# Migration Guide: v4.4.x to v4.5.0
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
|
|
5
|
-
Version 4.5.0 adopts the Operations interface from `@fjell/core`, providing a consistent API across all Fjell packages.
|
|
6
|
-
|
|
7
|
-
## Breaking Changes Summary
|
|
8
|
-
|
|
9
|
-
1. **Core Operations Interface**: `ClientApi` now extends `Operations` from `@fjell/core`
|
|
10
|
-
2. **Create Method**: Changed signature to use `CreateOptions`
|
|
11
|
-
3. **Action Methods**: Parameter name changed from `body` to `params`
|
|
12
|
-
4. **Upsert Operation**: Added missing `upsert` method
|
|
13
|
-
|
|
14
|
-
## Dependency Updates
|
|
15
|
-
|
|
16
|
-
Update your `package.json`:
|
|
17
|
-
|
|
18
|
-
```bash
|
|
19
|
-
npm install @fjell/core@latest @fjell/client-api@latest
|
|
20
|
-
```
|
|
21
|
-
|
|
22
|
-
## Code Migration
|
|
23
|
-
|
|
24
|
-
### 1. Create Method
|
|
25
|
-
|
|
26
|
-
The `create` method now uses `CreateOptions` instead of a simple `locations` parameter.
|
|
27
|
-
|
|
28
|
-
#### Before (v4.4.x)
|
|
29
|
-
|
|
30
|
-
```typescript
|
|
31
|
-
// With locations
|
|
32
|
-
const item = await api.create(
|
|
33
|
-
{ name: 'Alice' },
|
|
34
|
-
[{ kt: 'org', lk: 'org-123' }]
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
// Without locations
|
|
38
|
-
const item = await api.create({ name: 'Alice' });
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
#### After (v4.5.0)
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
// With locations - wrap in options object
|
|
45
|
-
const item = await api.create(
|
|
46
|
-
{ name: 'Alice' },
|
|
47
|
-
{ locations: [{ kt: 'org', lk: 'org-123' }] }
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
// Without locations - omit options or pass undefined
|
|
51
|
-
const item = await api.create({ name: 'Alice' });
|
|
52
|
-
|
|
53
|
-
// NEW: With specific key
|
|
54
|
-
const item = await api.create(
|
|
55
|
-
{ name: 'Alice' },
|
|
56
|
-
{ key: { kt: 'user', pk: 'custom-id' } }
|
|
57
|
-
);
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
### 2. Action Methods
|
|
61
|
-
|
|
62
|
-
The parameter name changed from `body` to `params` to match the core Operations interface. **Functionally, it's the same** - just a naming change.
|
|
63
|
-
|
|
64
|
-
#### Before (v4.4.x)
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
const [item, affectedKeys] = await api.action(
|
|
68
|
-
key,
|
|
69
|
-
'promote',
|
|
70
|
-
{ role: 'admin' } // called "body"
|
|
71
|
-
);
|
|
72
|
-
|
|
73
|
-
const [items, affectedKeys] = await api.allAction(
|
|
74
|
-
'archive',
|
|
75
|
-
{ reason: 'expired' }, // called "body"
|
|
76
|
-
locations
|
|
77
|
-
);
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
#### After (v4.5.0)
|
|
81
|
-
|
|
82
|
-
```typescript
|
|
83
|
-
// Same code - just know it's now called "params" internally
|
|
84
|
-
const [item, affectedKeys] = await api.action(
|
|
85
|
-
key,
|
|
86
|
-
'promote',
|
|
87
|
-
{ role: 'admin' } // now called "params"
|
|
88
|
-
);
|
|
89
|
-
|
|
90
|
-
const [items, affectedKeys] = await api.allAction(
|
|
91
|
-
'archive',
|
|
92
|
-
{ reason: 'expired' }, // now called "params"
|
|
93
|
-
locations
|
|
94
|
-
);
|
|
95
|
-
```
|
|
96
|
-
|
|
97
|
-
### 3. Upsert Operation (New)
|
|
98
|
-
|
|
99
|
-
A new `upsert` operation is now available:
|
|
100
|
-
|
|
101
|
-
```typescript
|
|
102
|
-
// Creates if doesn't exist, updates if it does
|
|
103
|
-
const user = await api.upsert(
|
|
104
|
-
{ kt: 'user', pk: 'user-123' },
|
|
105
|
-
{ name: 'Alice', email: 'alice@example.com' }
|
|
106
|
-
);
|
|
107
|
-
|
|
108
|
-
// With locations (for contained items)
|
|
109
|
-
const comment = await api.upsert(
|
|
110
|
-
{ kt: 'comment', pk: 'comment-456', loc: [{ kt: 'post', lk: 'post-123' }] },
|
|
111
|
-
{ text: 'Updated comment' },
|
|
112
|
-
[{ kt: 'post', lk: 'post-123' }]
|
|
113
|
-
);
|
|
114
|
-
```
|
|
115
|
-
|
|
116
|
-
### 4. Type Imports
|
|
117
|
-
|
|
118
|
-
Import types from the appropriate package:
|
|
119
|
-
|
|
120
|
-
#### Before (v4.4.x)
|
|
121
|
-
|
|
122
|
-
```typescript
|
|
123
|
-
import { ClientApi } from '@fjell/client-api';
|
|
124
|
-
// No OperationParams or AffectedKeys available
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
#### After (v4.5.0)
|
|
128
|
-
|
|
129
|
-
```typescript
|
|
130
|
-
import { ClientApi, OperationParams, AffectedKeys, CreateOptions } from '@fjell/client-api';
|
|
131
|
-
// Or import directly from core
|
|
132
|
-
import { Operations, OperationParams, AffectedKeys } from '@fjell/core';
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
## Type Compatibility
|
|
136
|
-
|
|
137
|
-
The `ClientApi` interface is now fully compatible with the core `Operations` interface:
|
|
138
|
-
|
|
139
|
-
```typescript
|
|
140
|
-
import type { Operations } from '@fjell/core';
|
|
141
|
-
import type { ClientApi } from '@fjell/client-api';
|
|
142
|
-
|
|
143
|
-
// These are now compatible
|
|
144
|
-
function processItems(ops: Operations<User, 'user'>) {
|
|
145
|
-
// Can pass either ClientApi or any other Operations implementation
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const clientApi: ClientApi<User, 'user'> = ...;
|
|
149
|
-
processItems(clientApi); // ✅ Works!
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
## Benefits of Migration
|
|
153
|
-
|
|
154
|
-
### 1. Consistent Interface
|
|
155
|
-
|
|
156
|
-
All Fjell packages now share the same Operations interface:
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
// All implement the same Operations interface
|
|
160
|
-
import { Operations } from '@fjell/lib';
|
|
161
|
-
import { ClientApi } from '@fjell/client-api';
|
|
162
|
-
import { Operations as FirestoreOps } from '@fjell/lib-firestore';
|
|
163
|
-
|
|
164
|
-
// Can be used interchangeably
|
|
165
|
-
function workWithOperations(ops: Operations<Item, string>) {
|
|
166
|
-
// Works with any implementation
|
|
167
|
-
}
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
### 2. Better Type Safety
|
|
171
|
-
|
|
172
|
-
```typescript
|
|
173
|
-
import { OperationParams, AffectedKeys, CreateOptions } from '@fjell/core';
|
|
174
|
-
|
|
175
|
-
// Strongly typed parameters
|
|
176
|
-
const params: OperationParams = {
|
|
177
|
-
status: 'active',
|
|
178
|
-
limit: 10
|
|
179
|
-
};
|
|
180
|
-
|
|
181
|
-
// Type-safe create options
|
|
182
|
-
const options: CreateOptions<'user'> = {
|
|
183
|
-
key: { kt: 'user', pk: 'user-123' }
|
|
184
|
-
};
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
### 3. Future Compatibility
|
|
188
|
-
|
|
189
|
-
By adopting the core interface, your code will be compatible with future Fjell enhancements and new operation implementations.
|
|
190
|
-
|
|
191
|
-
## Troubleshooting
|
|
192
|
-
|
|
193
|
-
### TypeScript Errors
|
|
194
|
-
|
|
195
|
-
If you see TypeScript errors after upgrading:
|
|
196
|
-
|
|
197
|
-
1. **Clear your TypeScript cache**: Delete `node_modules/.cache` and `dist/` directories
|
|
198
|
-
2. **Rebuild**: Run `npm run build`
|
|
199
|
-
3. **Update imports**: Ensure you're importing types from the correct packages
|
|
200
|
-
|
|
201
|
-
### Runtime Errors
|
|
202
|
-
|
|
203
|
-
If you encounter runtime errors:
|
|
204
|
-
|
|
205
|
-
1. **Check create calls**: Wrap `locations` in options object: `{ locations: [...] }`
|
|
206
|
-
2. **Verify dependencies**: Ensure `@fjell/core` is at the latest version
|
|
207
|
-
3. **Clear node_modules**: Delete and reinstall if necessary
|
|
208
|
-
|
|
209
|
-
## Migration Checklist
|
|
210
|
-
|
|
211
|
-
- [ ] Update package.json dependencies
|
|
212
|
-
- [ ] Run `npm install`
|
|
213
|
-
- [ ] Update `create` calls to use options object
|
|
214
|
-
- [ ] Update any type imports
|
|
215
|
-
- [ ] Test upsert operations if needed
|
|
216
|
-
- [ ] Run tests: `npm test`
|
|
217
|
-
- [ ] Build: `npm run build`
|
|
218
|
-
- [ ] Check for TypeScript errors: `npm run lint`
|
|
219
|
-
|
|
220
|
-
## Questions or Issues?
|
|
221
|
-
|
|
222
|
-
If you encounter any problems during migration:
|
|
223
|
-
|
|
224
|
-
1. Check the [API Reference](./docs/public/api-reference.md)
|
|
225
|
-
2. Review the [examples](./examples/)
|
|
226
|
-
3. File an issue on GitHub
|
|
227
|
-
|
|
228
|
-
## Previous Migrations
|
|
229
|
-
|
|
230
|
-
- For migrations from older versions, see previous migration guides
|
|
231
|
-
|
package/vitest.config.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/// <reference types="vitest" />
|
|
2
|
-
import { defineConfig } from 'vitest/config'
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
test: {
|
|
6
|
-
environment: 'jsdom',
|
|
7
|
-
setupFiles: ['./tests/setup.ts'],
|
|
8
|
-
globals: true,
|
|
9
|
-
testTimeout: 30000,
|
|
10
|
-
coverage: {
|
|
11
|
-
exclude: [
|
|
12
|
-
'build.js',
|
|
13
|
-
'docs/**',
|
|
14
|
-
'coverage/**',
|
|
15
|
-
'output/**',
|
|
16
|
-
'**/*.config.*',
|
|
17
|
-
'**/*.d.ts',
|
|
18
|
-
'dist/**',
|
|
19
|
-
]
|
|
20
|
-
}
|
|
21
|
-
},
|
|
22
|
-
})
|