houdini 0.17.8 → 0.17.10
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/README.md +33 -0
- package/build/cmd-cjs/index.js +124 -38
- package/build/cmd-esm/index.js +124 -38
- package/build/codegen-cjs/index.js +112 -36
- package/build/codegen-esm/index.js +112 -36
- package/build/lib/config.d.ts +3 -0
- package/build/lib-cjs/index.js +31 -12
- package/build/lib-esm/index.js +31 -12
- package/build/runtime/cache/cache.d.ts +1 -1
- package/build/runtime/cache/lists.d.ts +1 -1
- package/build/runtime/lib/config.d.ts +10 -2
- package/build/runtime/lib/types.d.ts +1 -0
- package/build/runtime-cjs/cache/cache.d.ts +1 -1
- package/build/runtime-cjs/cache/cache.js +6 -6
- package/build/runtime-cjs/cache/lists.d.ts +1 -1
- package/build/runtime-cjs/cache/lists.js +15 -6
- package/build/runtime-cjs/cache/tests/list.test.js +160 -70
- package/build/runtime-cjs/lib/config.d.ts +10 -2
- package/build/runtime-cjs/lib/types.d.ts +1 -0
- package/build/runtime-esm/cache/cache.d.ts +1 -1
- package/build/runtime-esm/cache/cache.js +6 -6
- package/build/runtime-esm/cache/lists.d.ts +1 -1
- package/build/runtime-esm/cache/lists.js +15 -6
- package/build/runtime-esm/cache/tests/list.test.js +160 -70
- package/build/runtime-esm/lib/config.d.ts +10 -2
- package/build/runtime-esm/lib/types.d.ts +1 -0
- package/build/test-cjs/index.js +122 -36
- package/build/test-esm/index.js +122 -36
- package/build/vite-cjs/index.js +122 -36
- package/build/vite-esm/index.js +122 -36
- package/package.json +16 -1
- package/.turbo/turbo-compile.log +0 -5
- package/.turbo/turbo-typedefs.log +0 -5
- package/CHANGELOG.md +0 -367
- package/src/cmd/generate.ts +0 -54
- package/src/cmd/index.ts +0 -60
- package/src/cmd/init.ts +0 -637
- package/src/cmd/pullSchema.ts +0 -40
- package/src/codegen/generators/artifacts/artifacts.test.ts +0 -2978
- package/src/codegen/generators/artifacts/fieldKey.ts +0 -60
- package/src/codegen/generators/artifacts/index.ts +0 -330
- package/src/codegen/generators/artifacts/indexFile.ts +0 -24
- package/src/codegen/generators/artifacts/inputs.ts +0 -81
- package/src/codegen/generators/artifacts/operations.ts +0 -263
- package/src/codegen/generators/artifacts/pagination.test.ts +0 -664
- package/src/codegen/generators/artifacts/policy.test.ts +0 -298
- package/src/codegen/generators/artifacts/selection.ts +0 -208
- package/src/codegen/generators/artifacts/utils.test.ts +0 -118
- package/src/codegen/generators/artifacts/utils.ts +0 -108
- package/src/codegen/generators/definitions/enums.test.ts +0 -61
- package/src/codegen/generators/definitions/enums.ts +0 -68
- package/src/codegen/generators/definitions/index.ts +0 -11
- package/src/codegen/generators/definitions/schema.test.ts +0 -227
- package/src/codegen/generators/index.ts +0 -6
- package/src/codegen/generators/indexFile/index.ts +0 -63
- package/src/codegen/generators/indexFile/indexFile.test.ts +0 -72
- package/src/codegen/generators/persistedQueries/index.ts +0 -55
- package/src/codegen/generators/persistedQueries/persistedQuery.test.ts +0 -26
- package/src/codegen/generators/runtime/index.test.ts +0 -74
- package/src/codegen/generators/runtime/index.ts +0 -64
- package/src/codegen/generators/runtime/runtime.test.ts +0 -25
- package/src/codegen/generators/typescript/addReferencedInputTypes.ts +0 -77
- package/src/codegen/generators/typescript/index.ts +0 -412
- package/src/codegen/generators/typescript/inlineType.ts +0 -409
- package/src/codegen/generators/typescript/typeReference.ts +0 -44
- package/src/codegen/generators/typescript/types.ts +0 -81
- package/src/codegen/generators/typescript/typescript.test.ts +0 -1434
- package/src/codegen/index.ts +0 -406
- package/src/codegen/transforms/addID.test.ts +0 -93
- package/src/codegen/transforms/addID.ts +0 -86
- package/src/codegen/transforms/composeQueries.test.ts +0 -50
- package/src/codegen/transforms/composeQueries.ts +0 -154
- package/src/codegen/transforms/fragmentVariables.test.ts +0 -636
- package/src/codegen/transforms/fragmentVariables.ts +0 -417
- package/src/codegen/transforms/index.ts +0 -7
- package/src/codegen/transforms/list.ts +0 -485
- package/src/codegen/transforms/lists.test.ts +0 -530
- package/src/codegen/transforms/paginate.test.ts +0 -1481
- package/src/codegen/transforms/paginate.ts +0 -750
- package/src/codegen/transforms/schema.test.ts +0 -136
- package/src/codegen/transforms/schema.ts +0 -104
- package/src/codegen/transforms/typename.test.ts +0 -125
- package/src/codegen/transforms/typename.ts +0 -55
- package/src/codegen/utils/commonjs.ts +0 -26
- package/src/codegen/utils/flattenSelections.ts +0 -179
- package/src/codegen/utils/graphql.test.ts +0 -35
- package/src/codegen/utils/graphql.ts +0 -79
- package/src/codegen/utils/index.ts +0 -5
- package/src/codegen/utils/moduleExport.ts +0 -27
- package/src/codegen/utils/murmur.ts +0 -79
- package/src/codegen/validators/index.ts +0 -4
- package/src/codegen/validators/noIDAlias.test.ts +0 -71
- package/src/codegen/validators/noIDAlias.ts +0 -39
- package/src/codegen/validators/plugins.ts +0 -25
- package/src/codegen/validators/typeCheck.test.ts +0 -904
- package/src/codegen/validators/typeCheck.ts +0 -1031
- package/src/codegen/validators/uniqueNames.test.ts +0 -59
- package/src/codegen/validators/uniqueNames.ts +0 -39
- package/src/lib/cleanupFiles.ts +0 -20
- package/src/lib/config.test.ts +0 -13
- package/src/lib/config.ts +0 -943
- package/src/lib/constants.ts +0 -11
- package/src/lib/error.ts +0 -24
- package/src/lib/fs.ts +0 -285
- package/src/lib/graphql.test.ts +0 -211
- package/src/lib/graphql.ts +0 -200
- package/src/lib/imports.ts +0 -82
- package/src/lib/index.ts +0 -17
- package/src/lib/introspection.ts +0 -39
- package/src/lib/parse.test.ts +0 -75
- package/src/lib/parse.ts +0 -23
- package/src/lib/path.ts +0 -49
- package/src/lib/pipeline.ts +0 -17
- package/src/lib/types.ts +0 -34
- package/src/lib/walk.ts +0 -104
- package/src/runtime/cache/cache.ts +0 -1023
- package/src/runtime/cache/gc.ts +0 -56
- package/src/runtime/cache/index.ts +0 -3
- package/src/runtime/cache/lists.ts +0 -502
- package/src/runtime/cache/storage.ts +0 -574
- package/src/runtime/cache/stuff.ts +0 -77
- package/src/runtime/cache/subscription.ts +0 -329
- package/src/runtime/cache/tests/availability.test.ts +0 -408
- package/src/runtime/cache/tests/gc.test.ts +0 -319
- package/src/runtime/cache/tests/keys.test.ts +0 -36
- package/src/runtime/cache/tests/list.test.ts +0 -3747
- package/src/runtime/cache/tests/readwrite.test.ts +0 -1201
- package/src/runtime/cache/tests/scalars.test.ts +0 -218
- package/src/runtime/cache/tests/storage.test.ts +0 -426
- package/src/runtime/cache/tests/subscriptions.test.ts +0 -1757
- package/src/runtime/index.ts +0 -29
- package/src/runtime/lib/config.ts +0 -201
- package/src/runtime/lib/constants.ts +0 -17
- package/src/runtime/lib/deepEquals.ts +0 -32
- package/src/runtime/lib/errors.ts +0 -8
- package/src/runtime/lib/index.ts +0 -8
- package/src/runtime/lib/log.ts +0 -69
- package/src/runtime/lib/network.ts +0 -303
- package/src/runtime/lib/networkUtils.ts +0 -151
- package/src/runtime/lib/scalars.test.ts +0 -877
- package/src/runtime/lib/scalars.ts +0 -195
- package/src/runtime/lib/types.ts +0 -194
- package/src/test/index.ts +0 -294
- package/src/vite/ast.ts +0 -107
- package/src/vite/houdini.ts +0 -113
- package/src/vite/imports.ts +0 -129
- package/src/vite/index.ts +0 -55
- package/src/vite/schema.ts +0 -80
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
import { test, expect } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { testConfigFile } from '../../../test'
|
|
4
|
-
import { SubscriptionSelection } from '../../lib/types'
|
|
5
|
-
import { Cache, rootID } from '../cache'
|
|
6
|
-
|
|
7
|
-
const config = testConfigFile({
|
|
8
|
-
scalars: {
|
|
9
|
-
DateTime: {
|
|
10
|
-
type: 'Date',
|
|
11
|
-
marshal(val: Date) {
|
|
12
|
-
return val.getTime()
|
|
13
|
-
},
|
|
14
|
-
unmarshal(val: number) {
|
|
15
|
-
return new Date(val)
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
},
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test('extracting data with custom scalars unmarshals the value', () => {
|
|
22
|
-
// instantiate a cache we'll test against
|
|
23
|
-
const cache = new Cache(config)
|
|
24
|
-
|
|
25
|
-
// the selection we are gonna write
|
|
26
|
-
const selection = {
|
|
27
|
-
node: {
|
|
28
|
-
type: 'Node',
|
|
29
|
-
keyRaw: 'node',
|
|
30
|
-
fields: {
|
|
31
|
-
date: {
|
|
32
|
-
type: 'DateTime',
|
|
33
|
-
keyRaw: 'date',
|
|
34
|
-
},
|
|
35
|
-
id: {
|
|
36
|
-
type: 'ID',
|
|
37
|
-
keyRaw: 'id',
|
|
38
|
-
},
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// save the data
|
|
44
|
-
const data = {
|
|
45
|
-
node: {
|
|
46
|
-
id: '1',
|
|
47
|
-
date: new Date().getTime(),
|
|
48
|
-
},
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// write the data to cache
|
|
52
|
-
cache.write({ selection, data })
|
|
53
|
-
|
|
54
|
-
// pull the data out of the cache
|
|
55
|
-
expect(cache.read({ parent: rootID, selection }).data).toEqual({
|
|
56
|
-
node: {
|
|
57
|
-
id: '1',
|
|
58
|
-
date: new Date(data.node.date),
|
|
59
|
-
},
|
|
60
|
-
})
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
test('can store and retrieve lists of lists of scalars', function () {
|
|
64
|
-
// instantiate the cache
|
|
65
|
-
const cache = new Cache(config)
|
|
66
|
-
|
|
67
|
-
const selection = {
|
|
68
|
-
viewer: {
|
|
69
|
-
type: 'User',
|
|
70
|
-
keyRaw: 'viewer',
|
|
71
|
-
fields: {
|
|
72
|
-
id: {
|
|
73
|
-
type: 'ID',
|
|
74
|
-
keyRaw: 'id',
|
|
75
|
-
},
|
|
76
|
-
strings: {
|
|
77
|
-
type: 'String',
|
|
78
|
-
keyRaw: 'strings',
|
|
79
|
-
},
|
|
80
|
-
},
|
|
81
|
-
},
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
// add some data to the cache
|
|
85
|
-
cache.write({
|
|
86
|
-
selection,
|
|
87
|
-
data: {
|
|
88
|
-
viewer: {
|
|
89
|
-
id: '1',
|
|
90
|
-
strings: ['bob', 'john'],
|
|
91
|
-
},
|
|
92
|
-
},
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
// make sure we can get the linked lists back
|
|
96
|
-
expect(cache.read({ parent: rootID, selection }).data).toEqual({
|
|
97
|
-
viewer: {
|
|
98
|
-
id: '1',
|
|
99
|
-
strings: ['bob', 'john'],
|
|
100
|
-
},
|
|
101
|
-
})
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
test('can write list of scalars', function () {
|
|
105
|
-
// instantiate the cache
|
|
106
|
-
const cache = new Cache(config)
|
|
107
|
-
|
|
108
|
-
const selection = {
|
|
109
|
-
viewer: {
|
|
110
|
-
type: 'User',
|
|
111
|
-
keyRaw: 'viewer',
|
|
112
|
-
fields: {
|
|
113
|
-
id: {
|
|
114
|
-
type: 'ID',
|
|
115
|
-
keyRaw: 'id',
|
|
116
|
-
},
|
|
117
|
-
firstName: {
|
|
118
|
-
type: 'String',
|
|
119
|
-
keyRaw: 'firstName',
|
|
120
|
-
},
|
|
121
|
-
friends: {
|
|
122
|
-
type: 'Int',
|
|
123
|
-
keyRaw: 'friends',
|
|
124
|
-
},
|
|
125
|
-
},
|
|
126
|
-
},
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// add some data to the cache
|
|
130
|
-
cache.write({
|
|
131
|
-
selection,
|
|
132
|
-
data: {
|
|
133
|
-
viewer: {
|
|
134
|
-
id: '1',
|
|
135
|
-
firstName: 'bob',
|
|
136
|
-
friends: [1],
|
|
137
|
-
},
|
|
138
|
-
},
|
|
139
|
-
})
|
|
140
|
-
|
|
141
|
-
// make sure we can get the linked lists back
|
|
142
|
-
expect(cache.read({ parent: rootID, selection }).data).toEqual({
|
|
143
|
-
viewer: {
|
|
144
|
-
id: '1',
|
|
145
|
-
firstName: 'bob',
|
|
146
|
-
friends: [1],
|
|
147
|
-
},
|
|
148
|
-
})
|
|
149
|
-
})
|
|
150
|
-
|
|
151
|
-
test('writing a scalar marked with replace', function () {
|
|
152
|
-
// instantiate the cache
|
|
153
|
-
const cache = new Cache(config)
|
|
154
|
-
|
|
155
|
-
const selection = {
|
|
156
|
-
viewer: {
|
|
157
|
-
type: 'User',
|
|
158
|
-
keyRaw: 'viewer',
|
|
159
|
-
fields: {
|
|
160
|
-
id: {
|
|
161
|
-
type: 'ID',
|
|
162
|
-
keyRaw: 'id',
|
|
163
|
-
},
|
|
164
|
-
firstName: {
|
|
165
|
-
type: 'String',
|
|
166
|
-
keyRaw: 'firstName',
|
|
167
|
-
},
|
|
168
|
-
friends: {
|
|
169
|
-
type: 'Int',
|
|
170
|
-
keyRaw: 'friends',
|
|
171
|
-
update: 'append',
|
|
172
|
-
},
|
|
173
|
-
},
|
|
174
|
-
},
|
|
175
|
-
} as SubscriptionSelection
|
|
176
|
-
|
|
177
|
-
// add some data to the cache
|
|
178
|
-
cache.write({
|
|
179
|
-
selection,
|
|
180
|
-
data: {
|
|
181
|
-
viewer: {
|
|
182
|
-
id: '1',
|
|
183
|
-
firstName: 'bob',
|
|
184
|
-
friends: [1],
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
})
|
|
188
|
-
|
|
189
|
-
// make sure we can get the linked lists back
|
|
190
|
-
expect(cache.read({ parent: rootID, selection }).data).toEqual({
|
|
191
|
-
viewer: {
|
|
192
|
-
id: '1',
|
|
193
|
-
firstName: 'bob',
|
|
194
|
-
friends: [1],
|
|
195
|
-
},
|
|
196
|
-
})
|
|
197
|
-
|
|
198
|
-
// add some data to the cache
|
|
199
|
-
cache.write({
|
|
200
|
-
selection,
|
|
201
|
-
data: {
|
|
202
|
-
viewer: {
|
|
203
|
-
id: '1',
|
|
204
|
-
firstName: 'bob',
|
|
205
|
-
friends: [2],
|
|
206
|
-
},
|
|
207
|
-
},
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
// make sure we can get the updated lists back
|
|
211
|
-
expect(cache.read({ parent: rootID, selection }).data).toEqual({
|
|
212
|
-
viewer: {
|
|
213
|
-
id: '1',
|
|
214
|
-
firstName: 'bob',
|
|
215
|
-
friends: [2],
|
|
216
|
-
},
|
|
217
|
-
})
|
|
218
|
-
})
|
|
@@ -1,426 +0,0 @@
|
|
|
1
|
-
import { test, expect, describe } from 'vitest'
|
|
2
|
-
|
|
3
|
-
import { InMemoryStorage, OperationLocation } from '../storage'
|
|
4
|
-
|
|
5
|
-
describe('in memory layers', function () {
|
|
6
|
-
test('first layer written can be looked up', function () {
|
|
7
|
-
// instantiate an storage layer with an in-memory layer
|
|
8
|
-
const storage = new InMemoryStorage()
|
|
9
|
-
|
|
10
|
-
// create the layer and write some data
|
|
11
|
-
const layer = storage.createLayer()
|
|
12
|
-
layer.writeField('User:1', 'firstName', 'John')
|
|
13
|
-
|
|
14
|
-
// can get the data back
|
|
15
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
16
|
-
value: 'John',
|
|
17
|
-
displayLayers: [layer.id],
|
|
18
|
-
kind: 'scalar',
|
|
19
|
-
})
|
|
20
|
-
expect(storage.layerCount).toEqual(1)
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
test('non-optimistic layer overwrites base', function () {
|
|
24
|
-
// instantiate an storage layer with an in-memory layer
|
|
25
|
-
const storage = new InMemoryStorage()
|
|
26
|
-
|
|
27
|
-
// create the two layers and write overlapping data
|
|
28
|
-
storage.writeField('User:1', 'firstName', 'John')
|
|
29
|
-
const layerID = storage.writeField('User:1', 'firstName', 'Marshal')
|
|
30
|
-
|
|
31
|
-
// can get the data back
|
|
32
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
33
|
-
value: 'Marshal',
|
|
34
|
-
displayLayers: [layerID],
|
|
35
|
-
kind: 'scalar',
|
|
36
|
-
})
|
|
37
|
-
expect(storage.layerCount).toEqual(1)
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
test('optimistic layer overwrites base', function () {
|
|
41
|
-
// instantiate an storage layer with an in-memory layer
|
|
42
|
-
const storage = new InMemoryStorage()
|
|
43
|
-
|
|
44
|
-
// create the two layers and write overlapping data
|
|
45
|
-
storage.writeField('User:1', 'firstName', 'John')
|
|
46
|
-
const optimisticLayerID = storage
|
|
47
|
-
.createLayer(true)
|
|
48
|
-
.writeField('User:1', 'firstName', 'Marshal')
|
|
49
|
-
|
|
50
|
-
// can get the data back
|
|
51
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
52
|
-
value: 'Marshal',
|
|
53
|
-
kind: 'scalar',
|
|
54
|
-
displayLayers: [optimisticLayerID],
|
|
55
|
-
})
|
|
56
|
-
expect(storage.layerCount).toEqual(2)
|
|
57
|
-
})
|
|
58
|
-
|
|
59
|
-
test('resolving layer merges into base', function () {
|
|
60
|
-
// instantiate an storage layer with an in-memory layer
|
|
61
|
-
const storage = new InMemoryStorage()
|
|
62
|
-
|
|
63
|
-
// write the layer
|
|
64
|
-
const baseLayerID = storage.writeField('User:1', 'firstName', 'John')
|
|
65
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
66
|
-
value: 'John',
|
|
67
|
-
displayLayers: [baseLayerID],
|
|
68
|
-
kind: 'scalar',
|
|
69
|
-
})
|
|
70
|
-
expect(storage.layerCount).toEqual(1)
|
|
71
|
-
|
|
72
|
-
// add an optimistic layer
|
|
73
|
-
const optimisticLayer = storage.createLayer(true)
|
|
74
|
-
optimisticLayer.writeField('User:1', 'firstName', 'Marshal')
|
|
75
|
-
|
|
76
|
-
// sanity check
|
|
77
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
78
|
-
value: 'Marshal',
|
|
79
|
-
kind: 'scalar',
|
|
80
|
-
displayLayers: [optimisticLayer.id],
|
|
81
|
-
})
|
|
82
|
-
expect(storage.layerCount).toEqual(2)
|
|
83
|
-
|
|
84
|
-
// resolve the middle layer with different data
|
|
85
|
-
optimisticLayer.writeField('User:1', 'firstName', 'Mike')
|
|
86
|
-
storage.resolveLayer(optimisticLayer.id)
|
|
87
|
-
|
|
88
|
-
// make sure the layer was committed correctly
|
|
89
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
90
|
-
value: 'Mike',
|
|
91
|
-
displayLayers: [baseLayerID],
|
|
92
|
-
kind: 'scalar',
|
|
93
|
-
})
|
|
94
|
-
expect(storage.layerCount).toEqual(1)
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
test('resolving layer merges up', function () {
|
|
98
|
-
// instantiate an storage layer with an in-memory layer
|
|
99
|
-
const storage = new InMemoryStorage()
|
|
100
|
-
|
|
101
|
-
// write the layer
|
|
102
|
-
const baseLayerID = storage.writeField('User:1', 'firstName', 'John')
|
|
103
|
-
|
|
104
|
-
// write an optimistic layer above the base
|
|
105
|
-
const layer1 = storage.createLayer(true)
|
|
106
|
-
layer1.writeField('User:1', 'firstName', 'Michael')
|
|
107
|
-
|
|
108
|
-
// add a layer above it
|
|
109
|
-
const layer2 = storage.createLayer()
|
|
110
|
-
layer2.writeField('User:1', 'firstName', 'Jeremy')
|
|
111
|
-
layer2.writeField('User:1', 'lastName', 'Michelson')
|
|
112
|
-
|
|
113
|
-
// sanity check
|
|
114
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
115
|
-
value: 'Jeremy',
|
|
116
|
-
displayLayers: [layer2.id],
|
|
117
|
-
kind: 'scalar',
|
|
118
|
-
})
|
|
119
|
-
expect(storage.layerCount).toEqual(3)
|
|
120
|
-
|
|
121
|
-
// flatten the data down to a single layer
|
|
122
|
-
layer1.writeField('User:1', 'firstName', 'Michael')
|
|
123
|
-
layer1.writeField('User:1', 'lastName', "George'")
|
|
124
|
-
layer1.writeField('User:1', 'age', 5)
|
|
125
|
-
storage.resolveLayer(layer1.id)
|
|
126
|
-
|
|
127
|
-
// make sure the data is what we expect
|
|
128
|
-
expect(storage.layerCount).toEqual(1)
|
|
129
|
-
expect(storage.get('User:1', 'age')).toEqual({
|
|
130
|
-
value: 5,
|
|
131
|
-
displayLayers: [baseLayerID],
|
|
132
|
-
kind: 'scalar',
|
|
133
|
-
})
|
|
134
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
135
|
-
value: 'Jeremy',
|
|
136
|
-
displayLayers: [baseLayerID],
|
|
137
|
-
kind: 'scalar',
|
|
138
|
-
})
|
|
139
|
-
expect(storage.get('User:1', 'lastName')).toEqual({
|
|
140
|
-
value: 'Michelson',
|
|
141
|
-
displayLayers: [baseLayerID],
|
|
142
|
-
kind: 'scalar',
|
|
143
|
-
})
|
|
144
|
-
})
|
|
145
|
-
|
|
146
|
-
test('can write links', function () {
|
|
147
|
-
const storage = new InMemoryStorage()
|
|
148
|
-
const layerID = storage.writeLink('User:1', 'bestFriend', 'User:2')
|
|
149
|
-
expect(storage.get('User:1', 'bestFriend')).toEqual({
|
|
150
|
-
value: 'User:2',
|
|
151
|
-
displayLayers: [layerID],
|
|
152
|
-
kind: 'link',
|
|
153
|
-
})
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
test('can write list of links', function () {
|
|
157
|
-
const storage = new InMemoryStorage()
|
|
158
|
-
const layerID = storage.writeLink('User:1', 'friends', ['User:1'])
|
|
159
|
-
expect(storage.get('User:1', 'friends')).toEqual({
|
|
160
|
-
value: ['User:1'],
|
|
161
|
-
displayLayers: [layerID],
|
|
162
|
-
kind: 'link',
|
|
163
|
-
})
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
test('values are reset when layer is cleared', function () {
|
|
167
|
-
const storage = new InMemoryStorage()
|
|
168
|
-
const layer = storage.createLayer(true)
|
|
169
|
-
|
|
170
|
-
layer.writeField('User:1', 'firstName', 'Alec')
|
|
171
|
-
|
|
172
|
-
// sanity check
|
|
173
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
174
|
-
value: 'Alec',
|
|
175
|
-
displayLayers: [layer.id],
|
|
176
|
-
kind: 'scalar',
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
// clear the layer
|
|
180
|
-
layer.clear()
|
|
181
|
-
|
|
182
|
-
// make sure we dont have any data back
|
|
183
|
-
expect(storage.get('User:1', 'firstName').value).toBeUndefined()
|
|
184
|
-
})
|
|
185
|
-
|
|
186
|
-
test('can overwrite deletes for a specific link list', function () {
|
|
187
|
-
const storage = new InMemoryStorage()
|
|
188
|
-
|
|
189
|
-
// add a base layer with some value
|
|
190
|
-
storage.writeLink('User:1', 'friends', ['User:2'])
|
|
191
|
-
|
|
192
|
-
// add an optimistic layer that deletes the first entry
|
|
193
|
-
const layer = storage.createLayer(true)
|
|
194
|
-
layer.delete('User:2')
|
|
195
|
-
|
|
196
|
-
// make sure its removed
|
|
197
|
-
expect(storage.get('User:1', 'friends').value).toEqual([])
|
|
198
|
-
|
|
199
|
-
// resolve the optimistic layer
|
|
200
|
-
storage.resolveLayer(layer.id)
|
|
201
|
-
// sanity check
|
|
202
|
-
expect(storage.get('User:1', 'friends').value).toEqual([])
|
|
203
|
-
|
|
204
|
-
// add the entry back to the list
|
|
205
|
-
storage.writeLink('User:1', 'friends', ['User:2'])
|
|
206
|
-
|
|
207
|
-
expect(storage.get('User:1', 'friends').value).toEqual(['User:2'])
|
|
208
|
-
})
|
|
209
|
-
|
|
210
|
-
test('deleting specific fields removes the field', function () {
|
|
211
|
-
const storage = new InMemoryStorage()
|
|
212
|
-
|
|
213
|
-
// write some data to the storage we will delete
|
|
214
|
-
storage.writeField('User:1', 'firstName', 'Michael')
|
|
215
|
-
storage.writeField('User:1', 'lastName', 'Aivazis')
|
|
216
|
-
|
|
217
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
218
|
-
value: 'Michael',
|
|
219
|
-
displayLayers: [storage.topLayer.id],
|
|
220
|
-
kind: 'scalar',
|
|
221
|
-
})
|
|
222
|
-
|
|
223
|
-
// delete the value
|
|
224
|
-
storage.deleteField('User:1', 'firstName')
|
|
225
|
-
storage.topLayer.removeUndefinedFields()
|
|
226
|
-
|
|
227
|
-
// look up the value now that it's been deleted
|
|
228
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
229
|
-
value: undefined,
|
|
230
|
-
displayLayers: [],
|
|
231
|
-
kind: 'unknown',
|
|
232
|
-
})
|
|
233
|
-
|
|
234
|
-
// make sure that the top layer doesn't actually hold the value
|
|
235
|
-
expect(Object.keys(storage.topLayer.fields['User:1'])).toEqual(['lastName'])
|
|
236
|
-
})
|
|
237
|
-
|
|
238
|
-
test('deleting all fields of a record deletes the record', function () {
|
|
239
|
-
const storage = new InMemoryStorage()
|
|
240
|
-
|
|
241
|
-
// write some data to the storage we will delete
|
|
242
|
-
storage.writeField('User:1', 'firstName', 'Michael')
|
|
243
|
-
|
|
244
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
245
|
-
value: 'Michael',
|
|
246
|
-
displayLayers: [storage.topLayer.id],
|
|
247
|
-
kind: 'scalar',
|
|
248
|
-
})
|
|
249
|
-
|
|
250
|
-
// delete the value
|
|
251
|
-
storage.deleteField('User:1', 'firstName')
|
|
252
|
-
storage.topLayer.removeUndefinedFields()
|
|
253
|
-
|
|
254
|
-
// look up the value now that it's been deleted
|
|
255
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
256
|
-
value: undefined,
|
|
257
|
-
displayLayers: [],
|
|
258
|
-
kind: 'unknown',
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
// make sure that the top layer doesn't actually hold the value
|
|
262
|
-
expect(storage.topLayer.fields['User:1']).toBeUndefined()
|
|
263
|
-
})
|
|
264
|
-
|
|
265
|
-
test('create and resolve on base layer', function () {
|
|
266
|
-
// note: this situation happens if a mutation fires before any queries
|
|
267
|
-
// are sent to the server to create a non-optimistic layer
|
|
268
|
-
|
|
269
|
-
const storage = new InMemoryStorage()
|
|
270
|
-
|
|
271
|
-
// create an optimistic layer
|
|
272
|
-
const layer = storage.createLayer(true)
|
|
273
|
-
|
|
274
|
-
layer.writeField('User:1', 'firstName', 'bob')
|
|
275
|
-
|
|
276
|
-
// resolve the layer
|
|
277
|
-
storage.resolveLayer(layer.id)
|
|
278
|
-
|
|
279
|
-
expect(storage.get('User:1', 'firstName').value).toEqual('bob')
|
|
280
|
-
})
|
|
281
|
-
|
|
282
|
-
test.todo('links are reset when layer is cleared')
|
|
283
|
-
|
|
284
|
-
describe('operations', function () {
|
|
285
|
-
test('optimistic deletes', function () {
|
|
286
|
-
const storage = new InMemoryStorage()
|
|
287
|
-
|
|
288
|
-
// add some information on the base layer we will delete
|
|
289
|
-
storage.writeField('User:1', 'firstName', 'John')
|
|
290
|
-
storage.writeField('User:1', 'lastName', 'Schmidt')
|
|
291
|
-
|
|
292
|
-
// add the user we're going to delete to a linked list to make sure they are removed from it
|
|
293
|
-
const baseLayerID = storage.writeLink('User:2', 'friends', ['User:1', 'User:3'])
|
|
294
|
-
|
|
295
|
-
// create a layer that deletes the record
|
|
296
|
-
const middleLayer = storage.createLayer(true)
|
|
297
|
-
middleLayer.delete('User:1')
|
|
298
|
-
|
|
299
|
-
// add some more information for the record
|
|
300
|
-
const topLayerID = storage.writeField('User:1', 'middleName', 'Jingleheymer')
|
|
301
|
-
|
|
302
|
-
// we should be able to retrieve the top layer of information
|
|
303
|
-
expect(storage.get('User:1', 'middleName')).toEqual({
|
|
304
|
-
value: 'Jingleheymer',
|
|
305
|
-
displayLayers: [topLayerID],
|
|
306
|
-
kind: 'scalar',
|
|
307
|
-
})
|
|
308
|
-
expect(storage.get('User:2', 'friends')).toEqual({
|
|
309
|
-
value: ['User:3'],
|
|
310
|
-
kind: 'link',
|
|
311
|
-
displayLayers: [middleLayer.id, baseLayerID],
|
|
312
|
-
})
|
|
313
|
-
|
|
314
|
-
// and the information in the lower layer should be inaccessible
|
|
315
|
-
expect(storage.get('User:1', 'firstName').value).toBeUndefined()
|
|
316
|
-
expect(storage.get('User:1', 'lastName').value).toBeUndefined()
|
|
317
|
-
|
|
318
|
-
// resolving the middle layer should delete the information even if its different
|
|
319
|
-
// than the original source
|
|
320
|
-
middleLayer.clear()
|
|
321
|
-
middleLayer.delete('User:3')
|
|
322
|
-
storage.resolveLayer(middleLayer.id)
|
|
323
|
-
|
|
324
|
-
expect(storage.layerCount).toEqual(1)
|
|
325
|
-
|
|
326
|
-
// the original fields of User:1 should still exist
|
|
327
|
-
expect(storage.get('User:1', 'firstName')).toEqual({
|
|
328
|
-
value: 'John',
|
|
329
|
-
displayLayers: [baseLayerID],
|
|
330
|
-
kind: 'scalar',
|
|
331
|
-
})
|
|
332
|
-
expect(storage.get('User:1', 'lastName')).toEqual({
|
|
333
|
-
value: 'Schmidt',
|
|
334
|
-
displayLayers: [baseLayerID],
|
|
335
|
-
kind: 'scalar',
|
|
336
|
-
})
|
|
337
|
-
expect(storage.get('User:1', 'middleName')).toEqual({
|
|
338
|
-
value: 'Jingleheymer',
|
|
339
|
-
displayLayers: [baseLayerID],
|
|
340
|
-
kind: 'scalar',
|
|
341
|
-
})
|
|
342
|
-
expect(storage.get('User:2', 'friends')).toEqual({
|
|
343
|
-
value: ['User:1'],
|
|
344
|
-
displayLayers: [baseLayerID],
|
|
345
|
-
kind: 'link',
|
|
346
|
-
})
|
|
347
|
-
})
|
|
348
|
-
|
|
349
|
-
test('insert into linked list', function () {
|
|
350
|
-
const storage = new InMemoryStorage()
|
|
351
|
-
|
|
352
|
-
// add a linked list that we will append to in an optimistic layer
|
|
353
|
-
const baseLayerID = storage.writeLink('User:1', 'friends', ['User:2'])
|
|
354
|
-
|
|
355
|
-
// create an optimistic layer and insert a new friend
|
|
356
|
-
const layer = storage.createLayer(true)
|
|
357
|
-
layer.insert('User:1', 'friends', OperationLocation.end, 'User:3')
|
|
358
|
-
|
|
359
|
-
// insert some more records in a non-optimistic layer
|
|
360
|
-
storage.insert('User:1', 'friends', OperationLocation.end, 'User:5')
|
|
361
|
-
|
|
362
|
-
// make sure we got the full list back
|
|
363
|
-
expect(storage.get('User:1', 'friends')).toEqual({
|
|
364
|
-
value: ['User:2', 'User:3', 'User:5'],
|
|
365
|
-
displayLayers: [storage.topLayer.id, layer.id, baseLayerID],
|
|
366
|
-
kind: 'link',
|
|
367
|
-
})
|
|
368
|
-
|
|
369
|
-
// simulate a mutation response with different data (clear the layer, add a new record, and resolve it)
|
|
370
|
-
layer.clear()
|
|
371
|
-
layer.insert('User:1', 'friends', OperationLocation.end, 'User:4')
|
|
372
|
-
storage.resolveLayer(layer.id)
|
|
373
|
-
|
|
374
|
-
// look up the linked list
|
|
375
|
-
expect(storage.get('User:1', 'friends')).toEqual({
|
|
376
|
-
value: ['User:2', 'User:5', 'User:4'],
|
|
377
|
-
displayLayers: [baseLayerID],
|
|
378
|
-
kind: 'link',
|
|
379
|
-
})
|
|
380
|
-
// there should only be one layer
|
|
381
|
-
expect(storage.layerCount).toEqual(1)
|
|
382
|
-
})
|
|
383
|
-
|
|
384
|
-
test('remove from linked list', function () {
|
|
385
|
-
const storage = new InMemoryStorage()
|
|
386
|
-
|
|
387
|
-
// add a linked list we will remove from in a layer
|
|
388
|
-
const baseLayerID = storage.writeLink('User:1', 'friends', [
|
|
389
|
-
'User:2',
|
|
390
|
-
'User:3',
|
|
391
|
-
'User:4',
|
|
392
|
-
])
|
|
393
|
-
|
|
394
|
-
// create an optimistic layer we will use to mutate the list
|
|
395
|
-
const layer = storage.createLayer(true)
|
|
396
|
-
layer.remove('User:1', 'friends', 'User:2')
|
|
397
|
-
|
|
398
|
-
// make sure we removed the user from the list
|
|
399
|
-
expect(storage.get('User:1', 'friends')).toEqual({
|
|
400
|
-
value: ['User:3', 'User:4'],
|
|
401
|
-
displayLayers: [layer.id, baseLayerID],
|
|
402
|
-
kind: 'link',
|
|
403
|
-
})
|
|
404
|
-
|
|
405
|
-
// simulate a mutation response with different data (clear the layer, remove a different one, and resolve it)
|
|
406
|
-
layer.clear()
|
|
407
|
-
layer.remove('User:1', 'friends', 'User:4')
|
|
408
|
-
layer.remove('User:1', 'friends', 'User:3')
|
|
409
|
-
storage.resolveLayer(layer.id)
|
|
410
|
-
|
|
411
|
-
// make sure we got the correct final result
|
|
412
|
-
expect(storage.get('User:1', 'friends')).toEqual({
|
|
413
|
-
value: ['User:2'],
|
|
414
|
-
displayLayers: [baseLayerID],
|
|
415
|
-
kind: 'link',
|
|
416
|
-
})
|
|
417
|
-
expect(storage.layerCount).toEqual(1)
|
|
418
|
-
})
|
|
419
|
-
|
|
420
|
-
test.todo(
|
|
421
|
-
'resolving layer with deletes and fields removes old data and retains the new stuff'
|
|
422
|
-
)
|
|
423
|
-
|
|
424
|
-
test.todo('an optimistic layer after a stack non-optimistic survives resolution')
|
|
425
|
-
})
|
|
426
|
-
})
|