@signalium/query 0.0.0 → 0.0.2
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/.turbo/turbo-build.log +12 -0
- package/CHANGELOG.md +17 -0
- package/dist/cjs/EntityMap.js +46 -0
- package/dist/cjs/EntityMap.js.map +1 -0
- package/dist/cjs/QueryClient.js +368 -0
- package/dist/cjs/QueryClient.js.map +1 -0
- package/dist/cjs/QueryStore.js +222 -0
- package/dist/cjs/QueryStore.js.map +1 -0
- package/dist/cjs/errors.js +105 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.js +24 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/parseEntities.js +127 -0
- package/dist/cjs/parseEntities.js.map +1 -0
- package/dist/cjs/pathInterpolator.js +69 -0
- package/dist/cjs/pathInterpolator.js.map +1 -0
- package/dist/cjs/proxy.js +187 -0
- package/dist/cjs/proxy.js.map +1 -0
- package/dist/cjs/query.js +41 -0
- package/dist/cjs/query.js.map +1 -0
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -0
- package/dist/cjs/typeDefs.js +249 -0
- package/dist/cjs/typeDefs.js.map +1 -0
- package/dist/cjs/types.js +15 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils.js +65 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/esm/EntityMap.d.ts +18 -0
- package/dist/esm/EntityMap.d.ts.map +1 -0
- package/dist/esm/EntityMap.js +42 -0
- package/dist/esm/EntityMap.js.map +1 -0
- package/dist/esm/QueryClient.d.ts +123 -0
- package/dist/esm/QueryClient.d.ts.map +1 -0
- package/dist/esm/QueryClient.js +363 -0
- package/dist/esm/QueryClient.js.map +1 -0
- package/dist/esm/QueryStore.d.ts +77 -0
- package/dist/esm/QueryStore.d.ts.map +1 -0
- package/dist/esm/QueryStore.js +212 -0
- package/dist/esm/QueryStore.js.map +1 -0
- package/dist/esm/errors.d.ts +4 -0
- package/dist/esm/errors.d.ts.map +1 -0
- package/dist/esm/errors.js +101 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +7 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/parseEntities.d.ts +8 -0
- package/dist/esm/parseEntities.d.ts.map +1 -0
- package/dist/esm/parseEntities.js +120 -0
- package/dist/esm/parseEntities.js.map +1 -0
- package/dist/esm/pathInterpolator.d.ts +29 -0
- package/dist/esm/pathInterpolator.d.ts.map +1 -0
- package/dist/esm/pathInterpolator.js +66 -0
- package/dist/esm/pathInterpolator.js.map +1 -0
- package/dist/esm/proxy.d.ts +8 -0
- package/dist/esm/proxy.d.ts.map +1 -0
- package/dist/esm/proxy.js +180 -0
- package/dist/esm/proxy.js.map +1 -0
- package/dist/esm/query.d.ts +41 -0
- package/dist/esm/query.d.ts.map +1 -0
- package/dist/esm/query.js +38 -0
- package/dist/esm/query.js.map +1 -0
- package/dist/esm/typeDefs.d.ts +25 -0
- package/dist/esm/typeDefs.d.ts.map +1 -0
- package/dist/esm/typeDefs.js +239 -0
- package/dist/esm/typeDefs.js.map +1 -0
- package/dist/esm/types.d.ts +96 -0
- package/dist/esm/types.d.ts.map +1 -0
- package/dist/esm/types.js +12 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils.d.ts +6 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +60 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/tsconfig.esm.tsbuildinfo +1 -0
- package/package.json +3 -3
- package/src/QueryClient.ts +321 -105
- package/src/QueryStore.ts +15 -7
- package/src/__tests__/caching-persistence.test.ts +31 -2
- package/src/__tests__/entity-system.test.ts +5 -1
- package/src/__tests__/gc-time.test.ts +327 -0
- package/src/__tests__/mock-fetch.test.ts +8 -4
- package/src/__tests__/parse-entities.test.ts +5 -1
- package/src/__tests__/reactivity.test.ts +5 -1
- package/src/__tests__/refetch-interval.test.ts +262 -0
- package/src/__tests__/rest-query-api.test.ts +5 -1
- package/src/__tests__/stale-time.test.ts +357 -0
- package/src/__tests__/utils.ts +28 -12
- package/src/__tests__/validation-edge-cases.test.ts +1 -0
- package/src/query.ts +2 -1
- package/src/react/__tests__/basic.test.tsx +9 -4
- package/src/react/__tests__/component.test.tsx +10 -3
- package/src/types.ts +11 -0
- package/vitest.config.ts +4 -10
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* QueryStore - Minimal interface for query persistence
|
|
3
|
+
*
|
|
4
|
+
* Provides a clean abstraction over document storage, reference counting,
|
|
5
|
+
* and LRU cache management. Supports both synchronous (in-memory) and
|
|
6
|
+
* asynchronous (writer-backed) implementations.
|
|
7
|
+
*/
|
|
8
|
+
const DEFAULT_MAX_COUNT = 50;
|
|
9
|
+
const DEFAULT_GC_TIME = 1000 * 60 * 60 * 24; // 24 hours
|
|
10
|
+
export class MemoryPersistentStore {
|
|
11
|
+
kv = Object.create(null);
|
|
12
|
+
has(key) {
|
|
13
|
+
return key in this.kv;
|
|
14
|
+
}
|
|
15
|
+
getString(key) {
|
|
16
|
+
return this.kv[key];
|
|
17
|
+
}
|
|
18
|
+
setString(key, value) {
|
|
19
|
+
this.kv[key] = value;
|
|
20
|
+
}
|
|
21
|
+
getNumber(key) {
|
|
22
|
+
return this.kv[key];
|
|
23
|
+
}
|
|
24
|
+
setNumber(key, value) {
|
|
25
|
+
this.kv[key] = value;
|
|
26
|
+
}
|
|
27
|
+
getBuffer(key) {
|
|
28
|
+
return this.kv[key];
|
|
29
|
+
}
|
|
30
|
+
setBuffer(key, value) {
|
|
31
|
+
this.kv[key] = value;
|
|
32
|
+
}
|
|
33
|
+
delete(key) {
|
|
34
|
+
delete this.kv[key];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
// Query Instance keys
|
|
38
|
+
export const valueKeyFor = (id) => `sq:doc:value:${id}`;
|
|
39
|
+
export const refCountKeyFor = (id) => `sq:doc:refCount:${id}`;
|
|
40
|
+
export const refIdsKeyFor = (id) => `sq:doc:refIds:${id}`;
|
|
41
|
+
export const updatedAtKeyFor = (id) => `sq:doc:updatedAt:${id}`;
|
|
42
|
+
// Query Type keys
|
|
43
|
+
export const queueKeyFor = (queryDefId) => `sq:doc:queue:${queryDefId}`;
|
|
44
|
+
export class SyncQueryStore {
|
|
45
|
+
kv;
|
|
46
|
+
queues = new Map();
|
|
47
|
+
constructor(kv) {
|
|
48
|
+
this.kv = kv;
|
|
49
|
+
}
|
|
50
|
+
loadQuery(queryDef, queryKey, entityMap) {
|
|
51
|
+
const updatedAt = this.kv.getNumber(updatedAtKeyFor(queryKey));
|
|
52
|
+
if (updatedAt === undefined || updatedAt < Date.now() - (queryDef.cache?.gcTime ?? DEFAULT_GC_TIME)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
const valueStr = this.kv.getString(valueKeyFor(queryKey));
|
|
56
|
+
if (valueStr === undefined) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
const entityIds = this.kv.getBuffer(refIdsKeyFor(queryKey));
|
|
60
|
+
if (entityIds !== undefined) {
|
|
61
|
+
this.preloadEntities(entityIds, entityMap);
|
|
62
|
+
}
|
|
63
|
+
this.activateQuery(queryDef, queryKey);
|
|
64
|
+
return {
|
|
65
|
+
value: JSON.parse(valueStr),
|
|
66
|
+
updatedAt,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
preloadEntities(entityIds, entityMap) {
|
|
70
|
+
for (const entityId of entityIds) {
|
|
71
|
+
const entityValue = this.kv.getString(valueKeyFor(entityId));
|
|
72
|
+
if (entityValue === undefined) {
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const entity = JSON.parse(entityValue);
|
|
76
|
+
entityMap.setPreloadedEntity(entityId, entity);
|
|
77
|
+
const childIds = this.kv.getBuffer(refIdsKeyFor(entityId));
|
|
78
|
+
if (childIds === undefined) {
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
81
|
+
this.preloadEntities(childIds, entityMap);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
saveQuery(queryDef, queryKey, value, refIds) {
|
|
85
|
+
this.setValue(queryKey, value, refIds);
|
|
86
|
+
this.kv.setNumber(updatedAtKeyFor(queryKey), Date.now());
|
|
87
|
+
this.activateQuery(queryDef, queryKey);
|
|
88
|
+
}
|
|
89
|
+
saveEntity(entityKey, value, refIds) {
|
|
90
|
+
this.setValue(entityKey, value, refIds);
|
|
91
|
+
}
|
|
92
|
+
activateQuery(queryDef, queryKey) {
|
|
93
|
+
if (!this.kv.has(valueKeyFor(queryKey))) {
|
|
94
|
+
// Query not in store, nothing to do. This can happen if the query has
|
|
95
|
+
// been evicted from the cache, but is still active in memory.
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
let queue = this.queues.get(queryDef.id);
|
|
99
|
+
if (queue === undefined) {
|
|
100
|
+
const maxCount = queryDef.cache?.maxCount ?? DEFAULT_MAX_COUNT;
|
|
101
|
+
queue = this.kv.getBuffer(queueKeyFor(queryDef.id));
|
|
102
|
+
if (queue === undefined) {
|
|
103
|
+
queue = new Uint32Array(maxCount);
|
|
104
|
+
this.kv.setBuffer(queueKeyFor(queryDef.id), queue);
|
|
105
|
+
}
|
|
106
|
+
else if (queue.length !== maxCount) {
|
|
107
|
+
const newQueue = new Uint32Array(maxCount);
|
|
108
|
+
newQueue.set(queue);
|
|
109
|
+
queue = newQueue;
|
|
110
|
+
this.kv.setBuffer(queueKeyFor(queryDef.id), queue);
|
|
111
|
+
}
|
|
112
|
+
this.queues.set(queryDef.id, queue);
|
|
113
|
+
}
|
|
114
|
+
const indexOfKey = queue.indexOf(queryKey);
|
|
115
|
+
// Item already in queue, move to front
|
|
116
|
+
if (indexOfKey >= 0) {
|
|
117
|
+
if (indexOfKey === 0) {
|
|
118
|
+
// Already at front, nothing to do
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
// Shift items right to make space at front
|
|
122
|
+
queue.copyWithin(1, 0, indexOfKey);
|
|
123
|
+
queue[0] = queryKey;
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Item not in queue, add to front and evict tail
|
|
127
|
+
const evicted = queue[queue.length - 1];
|
|
128
|
+
queue.copyWithin(1, 0, queue.length - 1);
|
|
129
|
+
queue[0] = queryKey;
|
|
130
|
+
if (evicted !== 0) {
|
|
131
|
+
this.deleteValue(evicted);
|
|
132
|
+
this.kv.delete(updatedAtKeyFor(evicted));
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
setValue(id, value, refIds) {
|
|
136
|
+
const kv = this.kv;
|
|
137
|
+
kv.setString(valueKeyFor(id), JSON.stringify(value));
|
|
138
|
+
const refIdsKey = refIdsKeyFor(id);
|
|
139
|
+
const prevRefIds = kv.getBuffer(refIdsKey);
|
|
140
|
+
if (refIds === undefined || refIds.size === 0) {
|
|
141
|
+
kv.delete(refIdsKey);
|
|
142
|
+
// Decrement all previous refs
|
|
143
|
+
if (prevRefIds !== undefined) {
|
|
144
|
+
for (let i = 0; i < prevRefIds.length; i++) {
|
|
145
|
+
const refId = prevRefIds[i];
|
|
146
|
+
this.decrementRefCount(refId);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
// Convert the set to a Uint32Array and capture all the refIds before we
|
|
152
|
+
// delete previous ones from the set
|
|
153
|
+
const newRefIds = new Uint32Array(refIds);
|
|
154
|
+
if (prevRefIds !== undefined) {
|
|
155
|
+
// Process new refs: increment if not in old
|
|
156
|
+
for (let i = 0; i < prevRefIds.length; i++) {
|
|
157
|
+
const refId = prevRefIds[i];
|
|
158
|
+
if (refIds.has(refId)) {
|
|
159
|
+
refIds.delete(refId);
|
|
160
|
+
}
|
|
161
|
+
else {
|
|
162
|
+
this.decrementRefCount(refId);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
// No previous refs, increment all unique new refs
|
|
167
|
+
for (const refId of refIds) {
|
|
168
|
+
this.incrementRefCount(refId);
|
|
169
|
+
}
|
|
170
|
+
kv.setBuffer(refIdsKey, newRefIds);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
deleteValue(id) {
|
|
174
|
+
const kv = this.kv;
|
|
175
|
+
kv.delete(valueKeyFor(id));
|
|
176
|
+
kv.delete(refCountKeyFor(id));
|
|
177
|
+
const refIds = kv.getBuffer(refIdsKeyFor(id));
|
|
178
|
+
kv.delete(refIdsKeyFor(id)); // Clean up the refIds key
|
|
179
|
+
if (refIds === undefined) {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
// Decrement ref counts for all referenced entities
|
|
183
|
+
for (const refId of refIds) {
|
|
184
|
+
if (refId !== 0) {
|
|
185
|
+
this.decrementRefCount(refId);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
incrementRefCount(refId) {
|
|
190
|
+
const refCountKey = refCountKeyFor(refId);
|
|
191
|
+
const currentCount = this.kv.getNumber(refCountKey) ?? 0;
|
|
192
|
+
const newCount = currentCount + 1;
|
|
193
|
+
this.kv.setNumber(refCountKey, newCount);
|
|
194
|
+
}
|
|
195
|
+
decrementRefCount(refId) {
|
|
196
|
+
const refCountKey = refCountKeyFor(refId);
|
|
197
|
+
const currentCount = this.kv.getNumber(refCountKey);
|
|
198
|
+
if (currentCount === undefined) {
|
|
199
|
+
// Already deleted or never existed
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
const newCount = currentCount - 1;
|
|
203
|
+
if (newCount === 0) {
|
|
204
|
+
// Entity exists, cascade delete it
|
|
205
|
+
this.deleteValue(refId);
|
|
206
|
+
}
|
|
207
|
+
else {
|
|
208
|
+
this.kv.setNumber(refCountKey, newCount);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=QueryStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryStore.js","sourceRoot":"","sources":["../../src/QueryStore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA,OAAO,EAQL,kBAAkB,EAEnB,MAAM,YAAY,CAAC;AAEpB,wBAAgB,YAAY,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAuG7D;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,kBAAkB,EAAE,KAAK,EAAE,OAAO,GAAG,KAAK,CAM/F"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { ARRAY_KEY, RECORD_KEY, } from './types.js';
|
|
2
|
+
export function typeToString(type) {
|
|
3
|
+
// Handle Set-based constants/enums
|
|
4
|
+
if (type instanceof Set) {
|
|
5
|
+
const values = Array.from(type).map(v => (typeof v === 'string' ? `"${v}"` : String(v)));
|
|
6
|
+
return values.join(' | ');
|
|
7
|
+
}
|
|
8
|
+
// Handle constants
|
|
9
|
+
if (typeof type === 'string') {
|
|
10
|
+
return `"${type}"`;
|
|
11
|
+
}
|
|
12
|
+
if (typeof type === 'boolean') {
|
|
13
|
+
return String(type);
|
|
14
|
+
}
|
|
15
|
+
// Handle primitive masks
|
|
16
|
+
if (typeof type === 'number') {
|
|
17
|
+
const types = [];
|
|
18
|
+
if (type & 1 /* Mask.UNDEFINED */)
|
|
19
|
+
types.push('undefined');
|
|
20
|
+
if (type & 2 /* Mask.NULL */)
|
|
21
|
+
types.push('null');
|
|
22
|
+
if (type & 4 /* Mask.NUMBER */)
|
|
23
|
+
types.push('number');
|
|
24
|
+
if (type & 8 /* Mask.STRING */)
|
|
25
|
+
types.push('string');
|
|
26
|
+
if (type & 16 /* Mask.BOOLEAN */)
|
|
27
|
+
types.push('boolean');
|
|
28
|
+
if (type & 32 /* Mask.OBJECT */)
|
|
29
|
+
types.push('object');
|
|
30
|
+
if (type & 64 /* Mask.ARRAY */)
|
|
31
|
+
types.push('array');
|
|
32
|
+
if (types.length === 0) {
|
|
33
|
+
return 'unknown';
|
|
34
|
+
}
|
|
35
|
+
return types.length === 1 ? types[0] : types.join(' | ');
|
|
36
|
+
}
|
|
37
|
+
// Handle complex types - CHECK UNION FIRST since it contains other types
|
|
38
|
+
const mask = type.mask;
|
|
39
|
+
if (mask & 512 /* Mask.UNION */) {
|
|
40
|
+
const unionType = type;
|
|
41
|
+
const parts = [];
|
|
42
|
+
// Add primitive types from the mask
|
|
43
|
+
if (mask & 1 /* Mask.UNDEFINED */)
|
|
44
|
+
parts.push('undefined');
|
|
45
|
+
if (mask & 2 /* Mask.NULL */)
|
|
46
|
+
parts.push('null');
|
|
47
|
+
if (mask & 4 /* Mask.NUMBER */)
|
|
48
|
+
parts.push('number');
|
|
49
|
+
if (mask & 8 /* Mask.STRING */)
|
|
50
|
+
parts.push('string');
|
|
51
|
+
if (mask & 16 /* Mask.BOOLEAN */)
|
|
52
|
+
parts.push('boolean');
|
|
53
|
+
// Add const/enum values from the values Set
|
|
54
|
+
if (unionType.values !== undefined && unionType.values.size > 0) {
|
|
55
|
+
for (const val of unionType.values) {
|
|
56
|
+
const valStr = typeof val === 'string' ? `"${val}"` : String(val);
|
|
57
|
+
parts.push(valStr);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Add complex types from the shape object
|
|
61
|
+
if (unionType.shape !== undefined) {
|
|
62
|
+
if (unionType.shape[ARRAY_KEY] !== undefined) {
|
|
63
|
+
parts.push(`Array<${typeToString(unionType.shape[ARRAY_KEY])}>`);
|
|
64
|
+
}
|
|
65
|
+
if (unionType.shape[RECORD_KEY] !== undefined) {
|
|
66
|
+
parts.push(`Record<string, ${typeToString(unionType.shape[RECORD_KEY])}>`);
|
|
67
|
+
}
|
|
68
|
+
// Add entity/object types by typename
|
|
69
|
+
for (const [key, value] of Object.entries(unionType.shape)) {
|
|
70
|
+
if (key !== ARRAY_KEY && key !== RECORD_KEY) {
|
|
71
|
+
// key is the typename value (e.g., "User", "Post")
|
|
72
|
+
parts.push(key);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (parts.length === 0) {
|
|
77
|
+
return 'union';
|
|
78
|
+
}
|
|
79
|
+
return parts.join(' | ');
|
|
80
|
+
}
|
|
81
|
+
if (mask & 1024 /* Mask.ENTITY */) {
|
|
82
|
+
return `Entity<${type.typenameValue}>`;
|
|
83
|
+
}
|
|
84
|
+
if (mask & 64 /* Mask.ARRAY */) {
|
|
85
|
+
const shape = type.shape;
|
|
86
|
+
return `Array<${typeToString(shape)}>`;
|
|
87
|
+
}
|
|
88
|
+
if (mask & 256 /* Mask.RECORD */) {
|
|
89
|
+
const shape = type.shape;
|
|
90
|
+
return `Record<string, ${typeToString(shape)}>`;
|
|
91
|
+
}
|
|
92
|
+
if (mask & 32 /* Mask.OBJECT */) {
|
|
93
|
+
const typename = type.typenameValue;
|
|
94
|
+
return typename ? `Object<${typename}>` : 'object';
|
|
95
|
+
}
|
|
96
|
+
return 'unknown';
|
|
97
|
+
}
|
|
98
|
+
export function typeError(path, expectedType, value) {
|
|
99
|
+
return new TypeError(`Validation error at ${path}: expected ${typeToString(expectedType)}, got ${typeof value === 'object' ? (value === null ? 'null' : Array.isArray(value) ? 'array' : 'object') : typeof value}`);
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export * from './types.js';
|
|
2
|
+
export { QueryClient, QueryResultImpl as QueryResult } from './QueryClient.js';
|
|
3
|
+
export type { QueryContext } from './QueryClient.js';
|
|
4
|
+
export type { QueryStore } from './QueryStore.js';
|
|
5
|
+
export { query } from './query.js';
|
|
6
|
+
export type { ExtractType } from './query.js';
|
|
7
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,eAAe,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/E,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,YAAY,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAE3B,OAAO,EAAE,WAAW,EAAE,eAAe,IAAI,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAG/E,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { QueryClient } from './QueryClient.js';
|
|
2
|
+
import { ComplexTypeDef, EntityDef, ObjectDef, UnionDef } from './types.js';
|
|
3
|
+
export declare function parseUnionEntities(valueType: number, value: object | unknown[], unionDef: UnionDef, queryClient: QueryClient, entityRefs?: Set<number>): unknown;
|
|
4
|
+
export declare function parseArrayEntities(array: unknown[], arrayShape: ComplexTypeDef, queryClient: QueryClient, entityRefs?: Set<number>): unknown[];
|
|
5
|
+
export declare function parseRecordEntities(record: Record<string, unknown>, recordShape: ComplexTypeDef, queryClient: QueryClient, entityRefs?: Set<number>): Record<string, unknown>;
|
|
6
|
+
export declare function parseObjectEntities(obj: Record<string, unknown>, objectShape: ObjectDef | EntityDef, queryClient: QueryClient, entityRefs?: Set<number>): Record<string, unknown>;
|
|
7
|
+
export declare function parseEntities(value: unknown, def: ComplexTypeDef, queryClient: QueryClient, entityRefs?: Set<number>): unknown;
|
|
8
|
+
//# sourceMappingURL=parseEntities.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseEntities.d.ts","sourceRoot":"","sources":["../../src/parseEntities.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAGL,cAAc,EACd,SAAS,EAET,SAAS,EAGT,QAAQ,EACT,MAAM,YAAY,CAAC;AAKpB,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE,EACzB,QAAQ,EAAE,QAAQ,EAClB,WAAW,EAAE,WAAW,EACxB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,OAAO,CA+CT;AAED,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,OAAO,EAAE,EAChB,UAAU,EAAE,cAAc,EAC1B,WAAW,EAAE,WAAW,EACxB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,OAAO,EAAE,CAMX;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC/B,WAAW,EAAE,cAAc,EAC3B,WAAW,EAAE,WAAW,EACxB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAUzB;AAED,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,WAAW,EAAE,SAAS,GAAG,SAAS,EAClC,WAAW,EAAE,WAAW,EACxB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkDzB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,cAAc,EACnB,WAAW,EAAE,WAAW,EACxB,UAAU,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,OAAO,CA4CT"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// -----------------------------------------------------------------------------
|
|
2
|
+
// Entity System
|
|
3
|
+
// -----------------------------------------------------------------------------
|
|
4
|
+
import { hashValue } from 'signalium/utils';
|
|
5
|
+
import { ARRAY_KEY, RECORD_KEY, } from './types.js';
|
|
6
|
+
import { extractShape, typeMaskOf } from './utils.js';
|
|
7
|
+
const entries = Object.entries;
|
|
8
|
+
export function parseUnionEntities(valueType, value, unionDef, queryClient, entityRefs) {
|
|
9
|
+
if (valueType === 64 /* Mask.ARRAY */) {
|
|
10
|
+
const shape = unionDef.shape[ARRAY_KEY];
|
|
11
|
+
if (shape === undefined || typeof shape === 'number') {
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
return parseArrayEntities(value, { mask: 64 /* Mask.ARRAY */, shape, values: undefined }, queryClient, entityRefs);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
// Use the cached typename field from the union definition
|
|
18
|
+
const typenameField = unionDef.typenameField;
|
|
19
|
+
const typename = typenameField ? value[typenameField] : undefined;
|
|
20
|
+
if (typename === undefined || typeof typename !== 'string') {
|
|
21
|
+
const recordShape = unionDef.shape[RECORD_KEY];
|
|
22
|
+
if (recordShape === undefined || typeof recordShape === 'number') {
|
|
23
|
+
return value;
|
|
24
|
+
}
|
|
25
|
+
return parseRecordEntities(value, recordShape, queryClient, entityRefs);
|
|
26
|
+
}
|
|
27
|
+
const matchingDef = unionDef.shape[typename];
|
|
28
|
+
if (matchingDef === undefined || typeof matchingDef === 'number') {
|
|
29
|
+
return value;
|
|
30
|
+
}
|
|
31
|
+
return parseObjectEntities(value, matchingDef, queryClient, entityRefs);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function parseArrayEntities(array, arrayShape, queryClient, entityRefs) {
|
|
35
|
+
for (let i = 0; i < array.length; i++) {
|
|
36
|
+
array[i] = parseEntities(array[i], arrayShape, queryClient, entityRefs);
|
|
37
|
+
}
|
|
38
|
+
return array;
|
|
39
|
+
}
|
|
40
|
+
export function parseRecordEntities(record, recordShape, queryClient, entityRefs) {
|
|
41
|
+
if (typeof recordShape === 'number') {
|
|
42
|
+
return record;
|
|
43
|
+
}
|
|
44
|
+
for (const [key, value] of entries(record)) {
|
|
45
|
+
record[key] = parseEntities(value, recordShape, queryClient, entityRefs);
|
|
46
|
+
}
|
|
47
|
+
return record;
|
|
48
|
+
}
|
|
49
|
+
export function parseObjectEntities(obj, objectShape, queryClient, entityRefs) {
|
|
50
|
+
const entityRefId = obj.__entityRef;
|
|
51
|
+
// Check if this is an entity reference (from cache)
|
|
52
|
+
if (typeof entityRefId === 'number') {
|
|
53
|
+
return queryClient.hydrateEntity(entityRefId, objectShape).proxy;
|
|
54
|
+
}
|
|
55
|
+
// Process sub-entity paths (only these paths can contain entities)
|
|
56
|
+
const { mask } = objectShape;
|
|
57
|
+
const childRefs = mask & 1024 /* Mask.ENTITY */ ? new Set() : entityRefs;
|
|
58
|
+
// Extract shape first to resolve lazy definitions and set subEntityPaths
|
|
59
|
+
const shape = extractShape(objectShape);
|
|
60
|
+
const subEntityPaths = objectShape.subEntityPaths;
|
|
61
|
+
if (subEntityPaths !== undefined) {
|
|
62
|
+
if (typeof subEntityPaths === 'string') {
|
|
63
|
+
// Single path - avoid array allocation
|
|
64
|
+
const propDef = shape[subEntityPaths];
|
|
65
|
+
obj[subEntityPaths] = parseEntities(obj[subEntityPaths], propDef, queryClient, childRefs);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Multiple paths - iterate directly
|
|
69
|
+
for (const path of subEntityPaths) {
|
|
70
|
+
const propDef = shape[path];
|
|
71
|
+
obj[path] = parseEntities(obj[path], propDef, queryClient, childRefs);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// Handle entity replacement (entities get cached and replaced with proxies)
|
|
76
|
+
if (mask & 1024 /* Mask.ENTITY */) {
|
|
77
|
+
const entityDef = objectShape;
|
|
78
|
+
const typename = entityDef.typenameValue;
|
|
79
|
+
const id = obj[entityDef.idField];
|
|
80
|
+
const desc = `${typename}:${id}`;
|
|
81
|
+
const key = hashValue(desc);
|
|
82
|
+
// Add this entity's key to the parent's entityRefs (if provided)
|
|
83
|
+
if (entityRefs !== undefined) {
|
|
84
|
+
entityRefs.add(key);
|
|
85
|
+
}
|
|
86
|
+
return queryClient.saveEntity(key, obj, entityDef, childRefs).proxy;
|
|
87
|
+
}
|
|
88
|
+
// Return the processed object (even if not an entity)
|
|
89
|
+
return obj;
|
|
90
|
+
}
|
|
91
|
+
export function parseEntities(value, def, queryClient, entityRefs) {
|
|
92
|
+
const valueType = typeMaskOf(value);
|
|
93
|
+
const defType = def.mask;
|
|
94
|
+
// Skip primitives and incompatible types - they can't contain entities
|
|
95
|
+
// Note: We silently return incompatible values rather than erroring
|
|
96
|
+
if (valueType < 32 /* Mask.OBJECT */ || (defType & valueType) === 0) {
|
|
97
|
+
return value;
|
|
98
|
+
}
|
|
99
|
+
// Handle unions first - they can contain multiple types, and all of the union
|
|
100
|
+
// logic is handled above, so we return early here if it's a union
|
|
101
|
+
if ((defType & 512 /* Mask.UNION */) !== 0) {
|
|
102
|
+
return parseUnionEntities(valueType, value, def, queryClient, entityRefs);
|
|
103
|
+
}
|
|
104
|
+
// If it's not a union, AND the value IS an array, then the definition must
|
|
105
|
+
// be an ArrayDef, so we can cast safely here
|
|
106
|
+
if (valueType === 64 /* Mask.ARRAY */) {
|
|
107
|
+
return parseArrayEntities(value, def.shape, queryClient, entityRefs);
|
|
108
|
+
}
|
|
109
|
+
// Now we know the value is an object, so def must be a RecordDef, ObjectDef
|
|
110
|
+
// or EntityDef. We first check to see if it's a RecordDef, and if so, we can
|
|
111
|
+
// cast it here and return early.
|
|
112
|
+
if ((defType & 256 /* Mask.RECORD */) !== 0) {
|
|
113
|
+
return parseRecordEntities(value, def.shape, queryClient, entityRefs);
|
|
114
|
+
}
|
|
115
|
+
// Now we know the def is an ObjectDef or EntityDef. These are both handled
|
|
116
|
+
// the same way _mostly_, with Entities just returning a proxy instead of the
|
|
117
|
+
// object itself
|
|
118
|
+
return parseObjectEntities(value, def, queryClient, entityRefs);
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=parseEntities.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parseEntities.js","sourceRoot":"","sources":["../../src/parseEntities.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path interpolation utilities for URL templates with parameter substitution.
|
|
3
|
+
*
|
|
4
|
+
* Converts path templates like "/users/{userId}/posts/{postId}" into functions
|
|
5
|
+
* that efficiently interpolate parameter values.
|
|
6
|
+
*
|
|
7
|
+
* The implementation pre-parses the path template once into segments and parameter
|
|
8
|
+
* keys, then uses simple string concatenation at runtime for optimal performance.
|
|
9
|
+
*/
|
|
10
|
+
export type PathInterpolator = (params: Record<string, any>) => string;
|
|
11
|
+
/**
|
|
12
|
+
* Creates an optimized path interpolation function from a URL template.
|
|
13
|
+
*
|
|
14
|
+
* The template uses curly braces for parameters (e.g., "/items/{id}").
|
|
15
|
+
* Parameter values are URL-encoded when interpolated. Any parameters not
|
|
16
|
+
* found in the path template are appended as query string parameters.
|
|
17
|
+
*
|
|
18
|
+
* @param pathTemplate - URL template with {paramName} placeholders
|
|
19
|
+
* @returns Function that interpolates parameters into the path with search params
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const interpolate = createPathInterpolator('/users/{userId}/posts/{postId}');
|
|
24
|
+
* const url = interpolate({ userId: '123', postId: '456', page: 2, limit: 10 });
|
|
25
|
+
* // Returns: "/users/123/posts/456?page=2&limit=10"
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function createPathInterpolator(pathTemplate: string): PathInterpolator;
|
|
29
|
+
//# sourceMappingURL=pathInterpolator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathInterpolator.d.ts","sourceRoot":"","sources":["../../src/pathInterpolator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,gBAAgB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;AAEvE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,YAAY,EAAE,MAAM,GAAG,gBAAgB,CA4C7E"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Path interpolation utilities for URL templates with parameter substitution.
|
|
3
|
+
*
|
|
4
|
+
* Converts path templates like "/users/{userId}/posts/{postId}" into functions
|
|
5
|
+
* that efficiently interpolate parameter values.
|
|
6
|
+
*
|
|
7
|
+
* The implementation pre-parses the path template once into segments and parameter
|
|
8
|
+
* keys, then uses simple string concatenation at runtime for optimal performance.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Creates an optimized path interpolation function from a URL template.
|
|
12
|
+
*
|
|
13
|
+
* The template uses curly braces for parameters (e.g., "/items/{id}").
|
|
14
|
+
* Parameter values are URL-encoded when interpolated. Any parameters not
|
|
15
|
+
* found in the path template are appended as query string parameters.
|
|
16
|
+
*
|
|
17
|
+
* @param pathTemplate - URL template with {paramName} placeholders
|
|
18
|
+
* @returns Function that interpolates parameters into the path with search params
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* const interpolate = createPathInterpolator('/users/{userId}/posts/{postId}');
|
|
23
|
+
* const url = interpolate({ userId: '123', postId: '456', page: 2, limit: 10 });
|
|
24
|
+
* // Returns: "/users/123/posts/456?page=2&limit=10"
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export function createPathInterpolator(pathTemplate) {
|
|
28
|
+
// Pre-parse path into segments and param keys (parse once, concatenate many times)
|
|
29
|
+
const segments = [];
|
|
30
|
+
const paramKeys = [];
|
|
31
|
+
const paramKeysSet = new Set();
|
|
32
|
+
let lastIndex = 0;
|
|
33
|
+
const paramRegex = /\[([^\]]+)\]/g;
|
|
34
|
+
let match;
|
|
35
|
+
while ((match = paramRegex.exec(pathTemplate)) !== null) {
|
|
36
|
+
segments.push(pathTemplate.slice(lastIndex, match.index));
|
|
37
|
+
paramKeys.push(match[1]);
|
|
38
|
+
paramKeysSet.add(match[1]);
|
|
39
|
+
lastIndex = paramRegex.lastIndex;
|
|
40
|
+
}
|
|
41
|
+
segments.push(pathTemplate.slice(lastIndex));
|
|
42
|
+
// Return optimized interpolation function with pre-parsed segments
|
|
43
|
+
return (params) => {
|
|
44
|
+
// Build the path with interpolated path parameters
|
|
45
|
+
let result = segments[0];
|
|
46
|
+
for (let i = 0; i < paramKeys.length; i++) {
|
|
47
|
+
result += encodeURIComponent(String(params[paramKeys[i]])) + segments[i + 1];
|
|
48
|
+
}
|
|
49
|
+
// Collect remaining parameters as search params
|
|
50
|
+
let searchParams = null;
|
|
51
|
+
for (const key in params) {
|
|
52
|
+
if (!paramKeysSet.has(key) && params[key] !== undefined) {
|
|
53
|
+
if (searchParams === null) {
|
|
54
|
+
searchParams = new URLSearchParams();
|
|
55
|
+
}
|
|
56
|
+
searchParams.append(key, String(params[key]));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Append search params if any exist
|
|
60
|
+
if (searchParams !== null) {
|
|
61
|
+
result += '?' + searchParams.toString();
|
|
62
|
+
}
|
|
63
|
+
return result;
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=pathInterpolator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pathInterpolator.js","sourceRoot":"","sources":["../../src/pathInterpolator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CAAC,YAAoB;IACzD,mFAAmF;IACnF,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,MAAM,UAAU,GAAG,eAAe,CAAC;IACnC,IAAI,KAA6B,CAAC;IAElC,OAAO,CAAC,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACxD,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1D,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACzB,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3B,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC;IACnC,CAAC;IACD,QAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC;IAE7C,mEAAmE;IACnE,OAAO,CAAC,MAA2B,EAAU,EAAE;QAC7C,mDAAmD;QACnD,IAAI,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;QACzB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC1C,MAAM,IAAI,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/E,CAAC;QAED,gDAAgD;QAChD,IAAI,YAAY,GAA2B,IAAI,CAAC;QAChD,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;YACzB,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;gBACxD,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;oBAC1B,YAAY,GAAG,IAAI,eAAe,EAAE,CAAC;gBACvC,CAAC;gBAED,YAAY,CAAC,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAChD,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAI,GAAG,GAAG,YAAY,CAAC,QAAQ,EAAE,CAAC;QAC1C,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ComplexTypeDef, EntityDef, ObjectDef, ObjectFieldTypeDef, TypeDef } from './types.js';
|
|
2
|
+
import { PreloadedEntityRecord } from './EntityMap.js';
|
|
3
|
+
export declare function parseArrayValue(array: unknown[], arrayShape: TypeDef, path: string): unknown[];
|
|
4
|
+
export declare function parseRecordValue(record: Record<string, unknown>, recordShape: ComplexTypeDef, path: string): Record<string, unknown>;
|
|
5
|
+
export declare function parseObjectValue(object: Record<string, unknown>, objectShape: ObjectDef | EntityDef, path: string): Record<string, unknown>;
|
|
6
|
+
export declare function parseValue(value: unknown, propDef: ObjectFieldTypeDef, path: string): unknown;
|
|
7
|
+
export declare function createEntityProxy(id: number, entityRecord: PreloadedEntityRecord, def: ObjectDef | EntityDef, desc?: string): Record<string, unknown>;
|
|
8
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/proxy.ts"],"names":[],"mappings":"AAEA,OAAO,EAGL,cAAc,EACd,SAAS,EAET,SAAS,EAET,kBAAkB,EAElB,OAAO,EACR,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AA6CvD,wBAAgB,eAAe,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,aAMlF;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,2BAM1G;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,WAAW,EAAE,SAAS,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,2BAcjH;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAyE7F;AAID,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,YAAY,EAAE,qBAAqB,EACnC,GAAG,EAAE,SAAS,GAAG,SAAS,EAC1B,IAAI,CAAC,EAAE,MAAM,GACZ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAkFzB"}
|