@fgv/ts-json-base 5.0.0-3 → 5.0.0-31

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.
Files changed (59) hide show
  1. package/CHANGELOG.json +0 -18
  2. package/README.md +150 -0
  3. package/dist/ts-json-base.d.ts +674 -9
  4. package/dist/tsdoc-metadata.json +1 -1
  5. package/eslint.config.js +16 -0
  6. package/lib/index.d.ts +2 -1
  7. package/lib/index.js +3 -1
  8. package/lib/packlets/file-tree/directoryItem.d.ts +47 -0
  9. package/lib/packlets/file-tree/directoryItem.js +71 -0
  10. package/lib/packlets/file-tree/fileItem.d.ts +97 -0
  11. package/lib/packlets/file-tree/fileItem.js +130 -0
  12. package/lib/packlets/file-tree/fileTree.d.ts +49 -0
  13. package/lib/packlets/file-tree/fileTree.js +89 -0
  14. package/lib/packlets/file-tree/fileTreeAccessors.d.ts +158 -0
  15. package/lib/packlets/file-tree/fileTreeAccessors.js +24 -0
  16. package/lib/packlets/file-tree/fileTreeHelpers.d.ts +43 -0
  17. package/lib/packlets/file-tree/fileTreeHelpers.js +38 -0
  18. package/lib/packlets/file-tree/fsTree.d.ts +57 -0
  19. package/lib/packlets/file-tree/fsTree.js +129 -0
  20. package/lib/packlets/file-tree/in-memory/inMemoryTree.d.ts +83 -0
  21. package/lib/packlets/file-tree/in-memory/inMemoryTree.js +181 -0
  22. package/lib/packlets/file-tree/in-memory/index.d.ts +2 -0
  23. package/lib/packlets/file-tree/in-memory/index.js +39 -0
  24. package/lib/packlets/file-tree/in-memory/treeBuilder.d.ts +113 -0
  25. package/lib/packlets/file-tree/in-memory/treeBuilder.js +179 -0
  26. package/lib/packlets/file-tree/index.d.ts +8 -0
  27. package/lib/packlets/file-tree/index.js +50 -0
  28. package/lib/packlets/json/common.d.ts +56 -2
  29. package/lib/packlets/json/common.js +7 -3
  30. package/lib/packlets/json-file/index.d.ts +2 -1
  31. package/lib/packlets/json-file/index.js +6 -1
  32. package/lib/packlets/json-file/jsonFsHelper.js +14 -44
  33. package/lib/packlets/json-file/jsonTreeHelper.d.ts +65 -0
  34. package/lib/packlets/json-file/jsonTreeHelper.js +120 -0
  35. package/lib/packlets/validators/validators.js +4 -4
  36. package/package.json +22 -19
  37. package/CHANGELOG.md +0 -100
  38. package/lib/index.d.ts.map +0 -1
  39. package/lib/index.js.map +0 -1
  40. package/lib/packlets/converters/converters.d.ts.map +0 -1
  41. package/lib/packlets/converters/converters.js.map +0 -1
  42. package/lib/packlets/converters/index.d.ts.map +0 -1
  43. package/lib/packlets/converters/index.js.map +0 -1
  44. package/lib/packlets/json/common.d.ts.map +0 -1
  45. package/lib/packlets/json/common.js.map +0 -1
  46. package/lib/packlets/json/index.d.ts.map +0 -1
  47. package/lib/packlets/json/index.js.map +0 -1
  48. package/lib/packlets/json-file/file.d.ts.map +0 -1
  49. package/lib/packlets/json-file/file.js.map +0 -1
  50. package/lib/packlets/json-file/index.d.ts.map +0 -1
  51. package/lib/packlets/json-file/index.js.map +0 -1
  52. package/lib/packlets/json-file/jsonFsHelper.d.ts.map +0 -1
  53. package/lib/packlets/json-file/jsonFsHelper.js.map +0 -1
  54. package/lib/packlets/json-file/jsonLike.d.ts.map +0 -1
  55. package/lib/packlets/json-file/jsonLike.js.map +0 -1
  56. package/lib/packlets/validators/index.d.ts.map +0 -1
  57. package/lib/packlets/validators/index.js.map +0 -1
  58. package/lib/packlets/validators/validators.d.ts.map +0 -1
  59. package/lib/packlets/validators/validators.js.map +0 -1
package/CHANGELOG.json CHANGED
@@ -1,24 +1,6 @@
1
1
  {
2
2
  "name": "@fgv/ts-json-base",
3
3
  "entries": [
4
- {
5
- "version": "5.0.0",
6
- "tag": "@fgv/ts-json-base_v5.0.0",
7
- "date": "Thu, 17 Jul 2025 00:13:24 GMT",
8
- "comments": {
9
- "none": [
10
- {
11
- "comment": "add sanitizeJsonObject"
12
- },
13
- {
14
- "comment": "upgrade dependencies"
15
- },
16
- {
17
- "comment": "bump version"
18
- }
19
- ]
20
- }
21
- },
22
4
  {
23
5
  "version": "4.6.0",
24
6
  "tag": "@fgv/ts-json-base_v4.6.0",
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
+