houdini-svelte 0.17.0-next.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.md +17 -0
- package/LICENSE +21 -0
- package/package.json +57 -0
- package/src/plugin/codegen/adapter.ts +45 -0
- package/src/plugin/codegen/components/index.ts +149 -0
- package/src/plugin/codegen/index.ts +28 -0
- package/src/plugin/codegen/routes/index.ts +307 -0
- package/src/plugin/codegen/routes/kit.test.ts +276 -0
- package/src/plugin/codegen/stores/fragment.ts +83 -0
- package/src/plugin/codegen/stores/index.ts +55 -0
- package/src/plugin/codegen/stores/mutation.ts +56 -0
- package/src/plugin/codegen/stores/query.test.ts +504 -0
- package/src/plugin/codegen/stores/query.ts +97 -0
- package/src/plugin/codegen/stores/subscription.ts +57 -0
- package/src/plugin/extract.test.ts +290 -0
- package/src/plugin/extract.ts +127 -0
- package/src/plugin/extractLoadFunction.test.ts +247 -0
- package/src/plugin/extractLoadFunction.ts +249 -0
- package/src/plugin/fsPatch.ts +238 -0
- package/src/plugin/imports.ts +28 -0
- package/src/plugin/index.ts +165 -0
- package/src/plugin/kit.ts +382 -0
- package/src/plugin/transforms/index.ts +90 -0
- package/src/plugin/transforms/kit/index.ts +20 -0
- package/src/plugin/transforms/kit/init.test.ts +28 -0
- package/src/plugin/transforms/kit/init.ts +75 -0
- package/src/plugin/transforms/kit/load.test.ts +1234 -0
- package/src/plugin/transforms/kit/load.ts +506 -0
- package/src/plugin/transforms/kit/session.test.ts +268 -0
- package/src/plugin/transforms/kit/session.ts +161 -0
- package/src/plugin/transforms/query.test.ts +99 -0
- package/src/plugin/transforms/query.ts +263 -0
- package/src/plugin/transforms/reactive.ts +126 -0
- package/src/plugin/transforms/tags.ts +20 -0
- package/src/plugin/transforms/types.ts +9 -0
- package/src/plugin/validate.test.ts +95 -0
- package/src/plugin/validate.ts +50 -0
- package/src/preprocess/index.ts +33 -0
- package/src/runtime/adapter.ts +21 -0
- package/src/runtime/fragments.ts +86 -0
- package/src/runtime/index.ts +72 -0
- package/src/runtime/network.ts +6 -0
- package/src/runtime/session.ts +187 -0
- package/src/runtime/stores/fragment.ts +48 -0
- package/src/runtime/stores/index.ts +5 -0
- package/src/runtime/stores/mutation.ts +185 -0
- package/src/runtime/stores/pagination/cursor.ts +265 -0
- package/src/runtime/stores/pagination/fetch.ts +7 -0
- package/src/runtime/stores/pagination/fragment.ts +236 -0
- package/src/runtime/stores/pagination/index.ts +7 -0
- package/src/runtime/stores/pagination/offset.ts +162 -0
- package/src/runtime/stores/pagination/pageInfo.test.ts +39 -0
- package/src/runtime/stores/pagination/pageInfo.ts +67 -0
- package/src/runtime/stores/pagination/query.ts +132 -0
- package/src/runtime/stores/query.ts +524 -0
- package/src/runtime/stores/store.ts +13 -0
- package/src/runtime/stores/subscription.ts +107 -0
- package/src/runtime/types.ts +40 -0
- package/src/test/index.ts +208 -0
|
@@ -0,0 +1,504 @@
|
|
|
1
|
+
import { fs, CollectedGraphQLDocument, path } from 'houdini'
|
|
2
|
+
import { mockCollectedDoc } from 'houdini/test'
|
|
3
|
+
import * as recast from 'recast'
|
|
4
|
+
import * as typeScriptParser from 'recast/parsers/typescript'
|
|
5
|
+
import { test, expect } from 'vitest'
|
|
6
|
+
|
|
7
|
+
import runPipeline from '..'
|
|
8
|
+
import '../..'
|
|
9
|
+
import { pipeline_test, test_config } from '../../../test'
|
|
10
|
+
import { stores_directory } from '../../kit'
|
|
11
|
+
|
|
12
|
+
test('generates a store for every query', async function () {
|
|
13
|
+
const config = await test_config()
|
|
14
|
+
const plugin_root = config.pluginDirectory('test-plugin')
|
|
15
|
+
|
|
16
|
+
// the documents to test
|
|
17
|
+
const docs: CollectedGraphQLDocument[] = [
|
|
18
|
+
mockCollectedDoc(`query TestQuery1 { version }`),
|
|
19
|
+
mockCollectedDoc(`query TestQuery2 { version }`),
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
// execute the generator
|
|
23
|
+
await runPipeline({ config, documents: docs, plugin_root, framework: 'kit' })
|
|
24
|
+
|
|
25
|
+
// look up the files in the artifact directory
|
|
26
|
+
const files = await fs.readdir(stores_directory(plugin_root))
|
|
27
|
+
|
|
28
|
+
// and they have the right names
|
|
29
|
+
expect(files).toEqual(expect.arrayContaining(['TestQuery1.js', 'TestQuery2.js']))
|
|
30
|
+
// and type definitions exist
|
|
31
|
+
expect(files).toEqual(expect.arrayContaining(['TestQuery1.d.ts', 'TestQuery2.d.ts']))
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test('basic store', async function () {
|
|
35
|
+
const docs = [`query TestQuery { version }`]
|
|
36
|
+
|
|
37
|
+
const { plugin_root } = await pipeline_test(docs)
|
|
38
|
+
|
|
39
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
40
|
+
|
|
41
|
+
// parse the contents
|
|
42
|
+
const parsed = recast.parse(contents!, {
|
|
43
|
+
parser: typeScriptParser,
|
|
44
|
+
}).program
|
|
45
|
+
|
|
46
|
+
// check the file contents
|
|
47
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
48
|
+
import { QueryStore } from '../runtime/stores'
|
|
49
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
50
|
+
|
|
51
|
+
// create the query store
|
|
52
|
+
|
|
53
|
+
export class TestQueryStore extends QueryStore {
|
|
54
|
+
constructor() {
|
|
55
|
+
super({
|
|
56
|
+
artifact,
|
|
57
|
+
storeName: "TestQueryStore",
|
|
58
|
+
variables: false,
|
|
59
|
+
})
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export async function load_TestQuery(params) {
|
|
64
|
+
const store = new TestQueryStore()
|
|
65
|
+
|
|
66
|
+
await store.fetch(params)
|
|
67
|
+
|
|
68
|
+
return {
|
|
69
|
+
TestQuery: store,
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export const GQL_TestQuery = new TestQueryStore()
|
|
74
|
+
|
|
75
|
+
export default GQL_TestQuery
|
|
76
|
+
`)
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
test('change globalStorePrefix to "yop___"', async function () {
|
|
80
|
+
const docs = [`query TestQuery { version }`]
|
|
81
|
+
|
|
82
|
+
const { plugin_root } = await pipeline_test(docs, {
|
|
83
|
+
plugins: {
|
|
84
|
+
'houdini-svelte': {
|
|
85
|
+
client: '',
|
|
86
|
+
globalStorePrefix: 'yop___',
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
92
|
+
|
|
93
|
+
// parse the contents
|
|
94
|
+
const parsed = recast.parse(contents!, {
|
|
95
|
+
parser: typeScriptParser,
|
|
96
|
+
}).program
|
|
97
|
+
|
|
98
|
+
// check the file contents
|
|
99
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
100
|
+
import { QueryStore } from '../runtime/stores'
|
|
101
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
102
|
+
|
|
103
|
+
// create the query store
|
|
104
|
+
|
|
105
|
+
export class TestQueryStore extends QueryStore {
|
|
106
|
+
constructor() {
|
|
107
|
+
super({
|
|
108
|
+
artifact,
|
|
109
|
+
storeName: "TestQueryStore",
|
|
110
|
+
variables: false,
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export async function load_TestQuery(params) {
|
|
116
|
+
const store = new TestQueryStore()
|
|
117
|
+
|
|
118
|
+
await store.fetch(params)
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
TestQuery: store,
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export const yop___TestQuery = new TestQueryStore()
|
|
126
|
+
|
|
127
|
+
export default yop___TestQuery
|
|
128
|
+
`)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
test('change globalStorePrefix to ""', async function () {
|
|
132
|
+
const docs = [`query TestQuery { version }`]
|
|
133
|
+
|
|
134
|
+
const { plugin_root } = await pipeline_test(docs, {
|
|
135
|
+
plugins: {
|
|
136
|
+
'houdini-svelte': {
|
|
137
|
+
client: '',
|
|
138
|
+
globalStorePrefix: '',
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
144
|
+
|
|
145
|
+
// parse the contents
|
|
146
|
+
const parsed = recast.parse(contents!, {
|
|
147
|
+
parser: typeScriptParser,
|
|
148
|
+
}).program
|
|
149
|
+
|
|
150
|
+
// check the file contents
|
|
151
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
152
|
+
import { QueryStore } from '../runtime/stores'
|
|
153
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
154
|
+
|
|
155
|
+
// create the query store
|
|
156
|
+
|
|
157
|
+
export class TestQueryStore extends QueryStore {
|
|
158
|
+
constructor() {
|
|
159
|
+
super({
|
|
160
|
+
artifact,
|
|
161
|
+
storeName: "TestQueryStore",
|
|
162
|
+
variables: false,
|
|
163
|
+
})
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
export async function load_TestQuery(params) {
|
|
168
|
+
const store = new TestQueryStore()
|
|
169
|
+
|
|
170
|
+
await store.fetch(params)
|
|
171
|
+
|
|
172
|
+
return {
|
|
173
|
+
TestQuery: store,
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export const TestQuery = new TestQueryStore()
|
|
178
|
+
|
|
179
|
+
export default TestQuery
|
|
180
|
+
`)
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
test('store with required variables', async function () {
|
|
184
|
+
const docs = [`query TestQuery($intValue: Int!) { usersByOffset(offset: $intValue) { id } }`]
|
|
185
|
+
|
|
186
|
+
const { plugin_root } = await pipeline_test(docs)
|
|
187
|
+
|
|
188
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
189
|
+
|
|
190
|
+
// parse the contents
|
|
191
|
+
const parsed = recast.parse(contents!, {
|
|
192
|
+
parser: typeScriptParser,
|
|
193
|
+
}).program
|
|
194
|
+
|
|
195
|
+
// check the file contents
|
|
196
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
197
|
+
import { QueryStore } from '../runtime/stores'
|
|
198
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
199
|
+
|
|
200
|
+
// create the query store
|
|
201
|
+
|
|
202
|
+
export class TestQueryStore extends QueryStore {
|
|
203
|
+
constructor() {
|
|
204
|
+
super({
|
|
205
|
+
artifact,
|
|
206
|
+
storeName: "TestQueryStore",
|
|
207
|
+
variables: true,
|
|
208
|
+
})
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
export async function load_TestQuery(params) {
|
|
213
|
+
const store = new TestQueryStore()
|
|
214
|
+
|
|
215
|
+
await store.fetch(params)
|
|
216
|
+
|
|
217
|
+
return {
|
|
218
|
+
TestQuery: store,
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export const GQL_TestQuery = new TestQueryStore()
|
|
223
|
+
|
|
224
|
+
export default GQL_TestQuery
|
|
225
|
+
`)
|
|
226
|
+
})
|
|
227
|
+
|
|
228
|
+
test('store with nullable variables', async function () {
|
|
229
|
+
const docs = [`query TestQuery($intValue: Int) { usersByOffset(offset: $intValue) { id } }`]
|
|
230
|
+
|
|
231
|
+
const { plugin_root } = await pipeline_test(docs)
|
|
232
|
+
|
|
233
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
234
|
+
|
|
235
|
+
// parse the contents
|
|
236
|
+
const parsed = recast.parse(contents!, {
|
|
237
|
+
parser: typeScriptParser,
|
|
238
|
+
}).program
|
|
239
|
+
|
|
240
|
+
// check the file contents
|
|
241
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
242
|
+
import { QueryStore } from '../runtime/stores'
|
|
243
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
244
|
+
|
|
245
|
+
// create the query store
|
|
246
|
+
|
|
247
|
+
export class TestQueryStore extends QueryStore {
|
|
248
|
+
constructor() {
|
|
249
|
+
super({
|
|
250
|
+
artifact,
|
|
251
|
+
storeName: "TestQueryStore",
|
|
252
|
+
variables: false,
|
|
253
|
+
})
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export async function load_TestQuery(params) {
|
|
258
|
+
const store = new TestQueryStore()
|
|
259
|
+
|
|
260
|
+
await store.fetch(params)
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
TestQuery: store,
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
export const GQL_TestQuery = new TestQueryStore()
|
|
268
|
+
|
|
269
|
+
export default GQL_TestQuery
|
|
270
|
+
`)
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
test('store with non-null variables with default value', async function () {
|
|
274
|
+
const docs = [
|
|
275
|
+
`query TestQuery($intValue: Int = 2) { usersByOffset(offset: $intValue) { id } }`,
|
|
276
|
+
]
|
|
277
|
+
|
|
278
|
+
const { plugin_root } = await pipeline_test(docs)
|
|
279
|
+
|
|
280
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
281
|
+
|
|
282
|
+
// parse the contents
|
|
283
|
+
const parsed = recast.parse(contents!, {
|
|
284
|
+
parser: typeScriptParser,
|
|
285
|
+
}).program
|
|
286
|
+
|
|
287
|
+
// check the file contents
|
|
288
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
289
|
+
import { QueryStore } from '../runtime/stores'
|
|
290
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
291
|
+
|
|
292
|
+
// create the query store
|
|
293
|
+
|
|
294
|
+
export class TestQueryStore extends QueryStore {
|
|
295
|
+
constructor() {
|
|
296
|
+
super({
|
|
297
|
+
artifact,
|
|
298
|
+
storeName: "TestQueryStore",
|
|
299
|
+
variables: false,
|
|
300
|
+
})
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export async function load_TestQuery(params) {
|
|
305
|
+
const store = new TestQueryStore()
|
|
306
|
+
|
|
307
|
+
await store.fetch(params)
|
|
308
|
+
|
|
309
|
+
return {
|
|
310
|
+
TestQuery: store,
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
export const GQL_TestQuery = new TestQueryStore()
|
|
315
|
+
|
|
316
|
+
export default GQL_TestQuery
|
|
317
|
+
`)
|
|
318
|
+
})
|
|
319
|
+
|
|
320
|
+
test('forward cursor pagination', async function () {
|
|
321
|
+
const docs = [
|
|
322
|
+
`query TestQuery {
|
|
323
|
+
usersByForwardsCursor(first: 10) @paginate {
|
|
324
|
+
edges {
|
|
325
|
+
node {
|
|
326
|
+
id
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}`,
|
|
331
|
+
]
|
|
332
|
+
|
|
333
|
+
const { plugin_root } = await pipeline_test(docs)
|
|
334
|
+
|
|
335
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
336
|
+
|
|
337
|
+
// parse the contents
|
|
338
|
+
const parsed = recast.parse(contents!, {
|
|
339
|
+
parser: typeScriptParser,
|
|
340
|
+
}).program
|
|
341
|
+
|
|
342
|
+
// check the file contents
|
|
343
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
344
|
+
import { QueryStoreForwardCursor } from '../runtime/stores'
|
|
345
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
346
|
+
|
|
347
|
+
// create the query store
|
|
348
|
+
|
|
349
|
+
export class TestQueryStore extends QueryStoreForwardCursor {
|
|
350
|
+
constructor() {
|
|
351
|
+
super({
|
|
352
|
+
artifact,
|
|
353
|
+
storeName: "TestQueryStore",
|
|
354
|
+
variables: false,
|
|
355
|
+
})
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
export async function load_TestQuery(params) {
|
|
360
|
+
const store = new TestQueryStore()
|
|
361
|
+
|
|
362
|
+
await store.fetch(params)
|
|
363
|
+
|
|
364
|
+
return {
|
|
365
|
+
TestQuery: store,
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export const GQL_TestQuery = new TestQueryStore()
|
|
370
|
+
|
|
371
|
+
export default GQL_TestQuery
|
|
372
|
+
`)
|
|
373
|
+
})
|
|
374
|
+
|
|
375
|
+
test('backwards cursor pagination', async function () {
|
|
376
|
+
const docs = [
|
|
377
|
+
`query TestQuery {
|
|
378
|
+
usersByBackwardsCursor(last: 10) @paginate {
|
|
379
|
+
edges {
|
|
380
|
+
node {
|
|
381
|
+
id
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}`,
|
|
386
|
+
]
|
|
387
|
+
|
|
388
|
+
const { plugin_root } = await pipeline_test(docs)
|
|
389
|
+
|
|
390
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
391
|
+
|
|
392
|
+
// parse the contents
|
|
393
|
+
const parsed = recast.parse(contents!, {
|
|
394
|
+
parser: typeScriptParser,
|
|
395
|
+
}).program
|
|
396
|
+
|
|
397
|
+
// check the file contents
|
|
398
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
399
|
+
import { QueryStoreBackwardCursor } from '../runtime/stores'
|
|
400
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
401
|
+
|
|
402
|
+
// create the query store
|
|
403
|
+
|
|
404
|
+
export class TestQueryStore extends QueryStoreBackwardCursor {
|
|
405
|
+
constructor() {
|
|
406
|
+
super({
|
|
407
|
+
artifact,
|
|
408
|
+
storeName: "TestQueryStore",
|
|
409
|
+
variables: false,
|
|
410
|
+
})
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
export async function load_TestQuery(params) {
|
|
415
|
+
const store = new TestQueryStore()
|
|
416
|
+
|
|
417
|
+
await store.fetch(params)
|
|
418
|
+
|
|
419
|
+
return {
|
|
420
|
+
TestQuery: store,
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
export const GQL_TestQuery = new TestQueryStore()
|
|
425
|
+
|
|
426
|
+
export default GQL_TestQuery
|
|
427
|
+
`)
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
test('offset pagination', async function () {
|
|
431
|
+
const docs = [
|
|
432
|
+
`query TestQuery {
|
|
433
|
+
usersByOffset(limit: 10) @paginate {
|
|
434
|
+
id
|
|
435
|
+
}
|
|
436
|
+
}`,
|
|
437
|
+
]
|
|
438
|
+
|
|
439
|
+
const { plugin_root } = await pipeline_test(docs)
|
|
440
|
+
|
|
441
|
+
const contents = await fs.readFile(path.join(stores_directory(plugin_root), 'TestQuery.js'))
|
|
442
|
+
|
|
443
|
+
// parse the contents
|
|
444
|
+
const parsed = recast.parse(contents!, {
|
|
445
|
+
parser: typeScriptParser,
|
|
446
|
+
}).program
|
|
447
|
+
|
|
448
|
+
// check the file contents
|
|
449
|
+
await expect(parsed).toMatchInlineSnapshot(`
|
|
450
|
+
import { QueryStoreOffset } from '../runtime/stores'
|
|
451
|
+
import artifact from '$houdini/artifacts/TestQuery'
|
|
452
|
+
|
|
453
|
+
// create the query store
|
|
454
|
+
|
|
455
|
+
export class TestQueryStore extends QueryStoreOffset {
|
|
456
|
+
constructor() {
|
|
457
|
+
super({
|
|
458
|
+
artifact,
|
|
459
|
+
storeName: "TestQueryStore",
|
|
460
|
+
variables: false,
|
|
461
|
+
})
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
export async function load_TestQuery(params) {
|
|
466
|
+
const store = new TestQueryStore()
|
|
467
|
+
|
|
468
|
+
await store.fetch(params)
|
|
469
|
+
|
|
470
|
+
return {
|
|
471
|
+
TestQuery: store,
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
export const GQL_TestQuery = new TestQueryStore()
|
|
476
|
+
|
|
477
|
+
export default GQL_TestQuery
|
|
478
|
+
`)
|
|
479
|
+
})
|
|
480
|
+
|
|
481
|
+
test('does not generate pagination store', async function () {
|
|
482
|
+
const docs = [
|
|
483
|
+
`query TestQuery {
|
|
484
|
+
usersByBackwardsCursor(last: 10) @paginate {
|
|
485
|
+
edges {
|
|
486
|
+
node {
|
|
487
|
+
id
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}`,
|
|
492
|
+
]
|
|
493
|
+
|
|
494
|
+
const { plugin_root, config } = await pipeline_test(docs)
|
|
495
|
+
|
|
496
|
+
await expect(
|
|
497
|
+
fs.stat(
|
|
498
|
+
path.join(
|
|
499
|
+
stores_directory(plugin_root),
|
|
500
|
+
config.paginationQueryName('TestQuery') + '.js'
|
|
501
|
+
)
|
|
502
|
+
)
|
|
503
|
+
).rejects.toBeTruthy()
|
|
504
|
+
})
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import * as graphql from 'graphql'
|
|
2
|
+
import { CollectedGraphQLDocument, GenerateHookInput, path } from 'houdini'
|
|
3
|
+
import { operation_requires_variables, fs } from 'houdini'
|
|
4
|
+
|
|
5
|
+
import { global_store_name, stores_directory, store_name } from '../../kit'
|
|
6
|
+
|
|
7
|
+
export async function generateIndividualStoreQuery(
|
|
8
|
+
{ config, plugin_root }: GenerateHookInput,
|
|
9
|
+
doc: CollectedGraphQLDocument
|
|
10
|
+
) {
|
|
11
|
+
const fileName = doc.name
|
|
12
|
+
const artifactName = `${doc.name}`
|
|
13
|
+
const storeName = store_name({ config, name: doc.name })
|
|
14
|
+
const globalStoreName = global_store_name({ config, name: doc.name })
|
|
15
|
+
|
|
16
|
+
let variables = false
|
|
17
|
+
const operation = doc.originalDocument.definitions.find(
|
|
18
|
+
(defn) => defn.kind === 'OperationDefinition' && defn.operation === 'query'
|
|
19
|
+
) as graphql.OperationDefinitionNode
|
|
20
|
+
if (operation) {
|
|
21
|
+
// an operation requires variables if there is any non-null variable that doesn't have a default value
|
|
22
|
+
variables = operation_requires_variables(operation)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// which functions we pull from the handlers depends on the pagination method
|
|
26
|
+
// specified by the artifact
|
|
27
|
+
const paginationMethod = doc.refetch?.paginated && doc.refetch.method
|
|
28
|
+
|
|
29
|
+
// in order to build the store, we need to know what class we're going to import from
|
|
30
|
+
let queryClass = 'QueryStore'
|
|
31
|
+
if (paginationMethod === 'cursor') {
|
|
32
|
+
queryClass =
|
|
33
|
+
doc.refetch?.direction === 'forward'
|
|
34
|
+
? 'QueryStoreForwardCursor'
|
|
35
|
+
: 'QueryStoreBackwardCursor'
|
|
36
|
+
} else if (paginationMethod === 'offset') {
|
|
37
|
+
queryClass = 'QueryStoreOffset'
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// store definition
|
|
41
|
+
const storeData = `import { ${queryClass} } from '../runtime/stores'
|
|
42
|
+
import artifact from '$houdini/artifacts/${artifactName}'
|
|
43
|
+
|
|
44
|
+
// create the query store
|
|
45
|
+
|
|
46
|
+
export class ${storeName} extends ${queryClass} {
|
|
47
|
+
constructor() {
|
|
48
|
+
super({
|
|
49
|
+
artifact,
|
|
50
|
+
storeName: ${JSON.stringify(storeName)},
|
|
51
|
+
variables: ${JSON.stringify(variables)},
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export async function load_${artifactName}(params) {
|
|
57
|
+
const store = new ${storeName}()
|
|
58
|
+
|
|
59
|
+
await store.fetch(params)
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
${artifactName}: store,
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const ${globalStoreName} = new ${storeName}()
|
|
67
|
+
|
|
68
|
+
export default ${globalStoreName}
|
|
69
|
+
`
|
|
70
|
+
|
|
71
|
+
const _input = `${artifactName}$input`
|
|
72
|
+
const _data = `${artifactName}$result`
|
|
73
|
+
|
|
74
|
+
// the type definitions for the store
|
|
75
|
+
const typeDefs = `import type { ${_input}, ${_data}, ${queryClass}, QueryStoreFetchParams} from '$houdini'
|
|
76
|
+
|
|
77
|
+
export declare class ${storeName} extends ${queryClass}<${_data}, ${_input}> {
|
|
78
|
+
constructor() {
|
|
79
|
+
// @ts-ignore
|
|
80
|
+
super({})
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export const ${globalStoreName}: ${storeName}
|
|
85
|
+
|
|
86
|
+
export declare const load_${artifactName}: (params: QueryStoreFetchParams<${_data}, ${_input}>) => Promise<{${artifactName}: ${storeName}}>
|
|
87
|
+
|
|
88
|
+
export default ${storeName}
|
|
89
|
+
`
|
|
90
|
+
|
|
91
|
+
await Promise.all([
|
|
92
|
+
fs.writeFile(path.join(stores_directory(plugin_root), `${fileName}.js`), storeData),
|
|
93
|
+
fs.writeFile(path.join(stores_directory(plugin_root), `${fileName}.d.ts`), typeDefs),
|
|
94
|
+
])
|
|
95
|
+
|
|
96
|
+
return fileName
|
|
97
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { CollectedGraphQLDocument, fs, GenerateHookInput, path } from 'houdini'
|
|
2
|
+
|
|
3
|
+
import { global_store_name, stores_directory, store_name } from '../../kit'
|
|
4
|
+
|
|
5
|
+
export async function generateSubscriptionStore(
|
|
6
|
+
{ config, plugin_root }: GenerateHookInput,
|
|
7
|
+
doc: CollectedGraphQLDocument
|
|
8
|
+
) {
|
|
9
|
+
const fileName = doc.name
|
|
10
|
+
const storeName = store_name({ config, name: doc.name })
|
|
11
|
+
const globalStoreName = global_store_name({ config, name: doc.name })
|
|
12
|
+
const artifactName = `${doc.name}`
|
|
13
|
+
|
|
14
|
+
// the content of the store
|
|
15
|
+
const storeContent = `import artifact from '$houdini/artifacts/${artifactName}'
|
|
16
|
+
import { SubscriptionStore } from '../runtime/stores'
|
|
17
|
+
|
|
18
|
+
export class ${storeName} extends SubscriptionStore {
|
|
19
|
+
constructor() {
|
|
20
|
+
super({
|
|
21
|
+
artifact,
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const ${globalStoreName} = new ${storeName}()
|
|
27
|
+
|
|
28
|
+
export default ${globalStoreName}
|
|
29
|
+
`
|
|
30
|
+
|
|
31
|
+
const _input = `${artifactName}$input`
|
|
32
|
+
const _data = `${artifactName}$result`
|
|
33
|
+
|
|
34
|
+
// the type definitions for the store
|
|
35
|
+
const typeDefs = `import type { ${_input}, ${_data}, SubscriptionStore } from '$houdini'
|
|
36
|
+
|
|
37
|
+
export declare class ${storeName} extends SubscriptionStore<${_data} | undefined, ${_input}> {
|
|
38
|
+
constructor() {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
super({})
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const ${globalStoreName}: ${storeName}
|
|
45
|
+
|
|
46
|
+
export default ${storeName}
|
|
47
|
+
`
|
|
48
|
+
|
|
49
|
+
// write the store contents to disk
|
|
50
|
+
await Promise.all([
|
|
51
|
+
fs.writeFile(path.join(stores_directory(plugin_root), `${fileName}.d.ts`), typeDefs),
|
|
52
|
+
fs.writeFile(path.join(stores_directory(plugin_root), `${fileName}.js`), storeContent),
|
|
53
|
+
])
|
|
54
|
+
|
|
55
|
+
// return the store name to the generator so the index file can be created
|
|
56
|
+
return fileName
|
|
57
|
+
}
|