@fgv/ts-json-base 5.0.0-8 → 5.0.1-0
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/CHANGELOG.json +9 -6
- package/README.md +150 -0
- package/dist/ts-json-base.d.ts +674 -9
- package/dist/tsdoc-metadata.json +1 -1
- package/eslint.config.js +16 -0
- package/lib/index.browser.d.ts +7 -0
- package/lib/index.browser.js +72 -0
- package/lib/index.d.ts +2 -1
- package/lib/index.js +3 -1
- package/lib/packlets/file-tree/directoryItem.d.ts +47 -0
- package/lib/packlets/file-tree/directoryItem.js +71 -0
- package/lib/packlets/file-tree/fileItem.d.ts +97 -0
- package/lib/packlets/file-tree/fileItem.js +130 -0
- package/lib/packlets/file-tree/fileTree.d.ts +49 -0
- package/lib/packlets/file-tree/fileTree.js +89 -0
- package/lib/packlets/file-tree/fileTreeAccessors.d.ts +158 -0
- package/lib/packlets/file-tree/fileTreeAccessors.js +24 -0
- package/lib/packlets/file-tree/fileTreeHelpers.d.ts +43 -0
- package/lib/packlets/file-tree/fileTreeHelpers.js +38 -0
- package/lib/packlets/file-tree/fsTree.d.ts +57 -0
- package/lib/packlets/file-tree/fsTree.js +129 -0
- package/lib/packlets/file-tree/in-memory/inMemoryTree.d.ts +83 -0
- package/lib/packlets/file-tree/in-memory/inMemoryTree.js +181 -0
- package/lib/packlets/file-tree/in-memory/index.d.ts +2 -0
- package/lib/packlets/file-tree/in-memory/index.js +39 -0
- package/lib/packlets/file-tree/in-memory/treeBuilder.d.ts +113 -0
- package/lib/packlets/file-tree/in-memory/treeBuilder.js +179 -0
- package/lib/packlets/file-tree/index.browser.d.ts +6 -0
- package/lib/packlets/file-tree/index.browser.js +49 -0
- package/lib/packlets/file-tree/index.d.ts +8 -0
- package/lib/packlets/file-tree/index.js +50 -0
- package/lib/packlets/json/common.d.ts +56 -2
- package/lib/packlets/json/common.js +7 -3
- package/lib/packlets/json-file/index.browser.d.ts +4 -0
- package/lib/packlets/json-file/index.browser.js +46 -0
- package/lib/packlets/json-file/index.d.ts +2 -1
- package/lib/packlets/json-file/index.js +6 -1
- package/lib/packlets/json-file/jsonFsHelper.js +14 -44
- package/lib/packlets/json-file/jsonTreeHelper.d.ts +65 -0
- package/lib/packlets/json-file/jsonTreeHelper.js +120 -0
- package/lib/packlets/validators/validators.js +4 -4
- package/package.json +35 -19
- package/CHANGELOG.md +0 -100
- package/lib/index.d.ts.map +0 -1
- package/lib/index.js.map +0 -1
- package/lib/packlets/converters/converters.d.ts.map +0 -1
- package/lib/packlets/converters/converters.js.map +0 -1
- package/lib/packlets/converters/index.d.ts.map +0 -1
- package/lib/packlets/converters/index.js.map +0 -1
- package/lib/packlets/json/common.d.ts.map +0 -1
- package/lib/packlets/json/common.js.map +0 -1
- package/lib/packlets/json/index.d.ts.map +0 -1
- package/lib/packlets/json/index.js.map +0 -1
- package/lib/packlets/json-file/file.d.ts.map +0 -1
- package/lib/packlets/json-file/file.js.map +0 -1
- package/lib/packlets/json-file/index.d.ts.map +0 -1
- package/lib/packlets/json-file/index.js.map +0 -1
- package/lib/packlets/json-file/jsonFsHelper.d.ts.map +0 -1
- package/lib/packlets/json-file/jsonFsHelper.js.map +0 -1
- package/lib/packlets/json-file/jsonLike.d.ts.map +0 -1
- package/lib/packlets/json-file/jsonLike.js.map +0 -1
- package/lib/packlets/validators/index.d.ts.map +0 -1
- package/lib/packlets/validators/index.js.map +0 -1
- package/lib/packlets/validators/validators.d.ts.map +0 -1
- package/lib/packlets/validators/validators.js.map +0 -1
package/CHANGELOG.json
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fgv/ts-json-base",
|
|
3
3
|
"entries": [
|
|
4
|
+
{
|
|
5
|
+
"version": "5.0.1",
|
|
6
|
+
"tag": "@fgv/ts-json-base_v5.0.1",
|
|
7
|
+
"date": "Tue, 23 Sep 2025 03:13:55 GMT",
|
|
8
|
+
"comments": {}
|
|
9
|
+
},
|
|
4
10
|
{
|
|
5
11
|
"version": "5.0.0",
|
|
6
12
|
"tag": "@fgv/ts-json-base_v5.0.0",
|
|
7
|
-
"date": "
|
|
13
|
+
"date": "Tue, 23 Sep 2025 02:54:20 GMT",
|
|
8
14
|
"comments": {
|
|
9
15
|
"none": [
|
|
10
16
|
{
|
|
11
|
-
"comment": "
|
|
17
|
+
"comment": "FileTree moved from ts-utils and to use JsonTypes"
|
|
12
18
|
},
|
|
13
19
|
{
|
|
14
|
-
"comment": "
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
"comment": "bump version"
|
|
20
|
+
"comment": "update rushstack"
|
|
18
21
|
}
|
|
19
22
|
]
|
|
20
23
|
}
|
package/README.md
CHANGED
|
@@ -32,3 +32,153 @@ type JsonValue = JsonPrimitive | JsonObject | JsonArray;
|
|
|
32
32
|
interface JsonArray extends Array<JsonValue> { }
|
|
33
33
|
```
|
|
34
34
|
|
|
35
|
+
### JsonCompatible Type
|
|
36
|
+
|
|
37
|
+
The `JsonCompatible<T>` type provides compile-time validation that a type is JSON-serializable, unlike `JsonValue` which requires an index signature. This is particularly useful for strongly-typed interfaces.
|
|
38
|
+
|
|
39
|
+
#### Basic Usage
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
import { JsonCompatible } from '@fgv/ts-json-base';
|
|
43
|
+
|
|
44
|
+
// ✅ JSON-compatible interface
|
|
45
|
+
interface UserData {
|
|
46
|
+
id: string;
|
|
47
|
+
name: string;
|
|
48
|
+
preferences: {
|
|
49
|
+
theme: 'light' | 'dark';
|
|
50
|
+
notifications: boolean;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// ✅ This type remains unchanged because it's fully JSON-compatible
|
|
55
|
+
type ValidatedUserData = JsonCompatible<UserData>;
|
|
56
|
+
|
|
57
|
+
// ❌ Interface with non-JSON properties
|
|
58
|
+
interface UserWithMethods {
|
|
59
|
+
id: string;
|
|
60
|
+
name: string;
|
|
61
|
+
save(): Promise<void>; // Functions are not JSON-serializable
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// ❌ This type transforms 'save' to an error type
|
|
65
|
+
type InvalidUserData = JsonCompatible<UserWithMethods>;
|
|
66
|
+
// Result: { id: string; name: string; save: ['Error: Function is not JSON-compatible'] }
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
#### The MapOf Pattern
|
|
70
|
+
|
|
71
|
+
The most powerful application is using `JsonCompatible<T>` as a constraint with default type parameters:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
class MapOf<T, TV extends JsonCompatible<T> = JsonCompatible<T>> extends Map<string, TV> {
|
|
75
|
+
public override set(key: string, value: TV): this {
|
|
76
|
+
return super.set(key, value);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ✅ Works perfectly with JSON-compatible types
|
|
81
|
+
const userMap = new MapOf<UserData>();
|
|
82
|
+
userMap.set('user1', {
|
|
83
|
+
id: 'user1',
|
|
84
|
+
name: 'Alice',
|
|
85
|
+
preferences: { theme: 'dark', notifications: true }
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
// ❌ Prevents usage with non-JSON-compatible types
|
|
89
|
+
const badMap = new MapOf<UserWithMethods>();
|
|
90
|
+
// The 'save' method becomes type 'never', making the interface unusable
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Real-World Examples
|
|
94
|
+
|
|
95
|
+
**API Response Caching:**
|
|
96
|
+
```typescript
|
|
97
|
+
interface ApiResponse {
|
|
98
|
+
id: string;
|
|
99
|
+
data: unknown;
|
|
100
|
+
timestamp: number;
|
|
101
|
+
metadata: Record<string, string | number>;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
class ApiCache extends MapOf<ApiResponse> {
|
|
105
|
+
setWithTTL(key: string, response: ApiResponse, ttlMs: number) {
|
|
106
|
+
this.set(key, response);
|
|
107
|
+
setTimeout(() => this.delete(key), ttlMs);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Configuration Management:**
|
|
113
|
+
```typescript
|
|
114
|
+
interface AppConfig {
|
|
115
|
+
features: Record<string, boolean>;
|
|
116
|
+
limits: {
|
|
117
|
+
maxUsers: number;
|
|
118
|
+
maxStorage: number;
|
|
119
|
+
};
|
|
120
|
+
ui: {
|
|
121
|
+
theme: 'light' | 'dark';
|
|
122
|
+
language: string;
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Ensures config is always serializable for storage/transmission
|
|
127
|
+
const configStore = new MapOf<AppConfig>();
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
**Data Transfer Objects:**
|
|
131
|
+
```typescript
|
|
132
|
+
// ✅ Perfect for DTOs - no methods, just data
|
|
133
|
+
interface CreateUserRequest {
|
|
134
|
+
name: string;
|
|
135
|
+
email: string;
|
|
136
|
+
preferences?: {
|
|
137
|
+
newsletter: boolean;
|
|
138
|
+
theme: string;
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const requestCache = new MapOf<CreateUserRequest>();
|
|
143
|
+
|
|
144
|
+
// ❌ Domain objects with behavior are rejected
|
|
145
|
+
interface User extends CreateUserRequest {
|
|
146
|
+
id: string;
|
|
147
|
+
save(): Promise<void>;
|
|
148
|
+
validate(): boolean;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// This won't work - methods become 'never'
|
|
152
|
+
// const userStore = new MapOf<User>();
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Array and Nested Validation
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
// ✅ Arrays of JSON-compatible types work fine
|
|
159
|
+
interface DataStructure {
|
|
160
|
+
numbers: number[];
|
|
161
|
+
objects: Array<{ id: number; name: string }>;
|
|
162
|
+
matrix: number[][];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const dataMap = new MapOf<DataStructure>();
|
|
166
|
+
|
|
167
|
+
// ❌ Arrays with functions are detected
|
|
168
|
+
interface WithHandlers {
|
|
169
|
+
callbacks: Array<() => void>; // Functions in arrays also become 'never'
|
|
170
|
+
data: string[];
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// The 'callbacks' property becomes Array<['Error: Function is not JSON-compatible']>
|
|
174
|
+
const handlersMap = new MapOf<WithHandlers>();
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
#### Benefits
|
|
178
|
+
|
|
179
|
+
1. **Compile-time safety**: Non-serializable types are caught during development
|
|
180
|
+
2. **Clear interfaces**: Makes it obvious which types are meant for serialization
|
|
181
|
+
3. **Architecture enforcement**: Separates data objects from behavior objects
|
|
182
|
+
4. **Runtime protection**: Prevents serialization errors in production
|
|
183
|
+
5. **IDE support**: Full autocomplete and error highlighting
|
|
184
|
+
|