houdini-core 2.0.0-go.9 → 2.0.0-next.14
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/package.json +7 -7
- package/postInstall.js +1 -1
- package/runtime/cache.ts +1 -0
- package/runtime/client.ts +7 -2
- package/runtime/config.ts +1 -2
- package/runtime/index.ts +2 -1
- package/runtime/plugins/cache.ts +1 -1
- package/runtime/plugins/fetch.ts +9 -9
- package/runtime/plugins/fragment.ts +1 -1
- package/runtime/plugins/optimisticKeys.ts +10 -10
- package/runtime/plugins/query.ts +1 -1
- package/runtime/plugins/throwOnError.ts +1 -1
- package/runtime/plugins/utils/documentPlugins.ts +2 -2
- package/runtime/public/cache.ts +3 -3
- package/runtime/public/list.ts +1 -1
- package/runtime/public/record.ts +1 -1
- package/runtime/public/types.ts +10 -10
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "houdini-core",
|
|
3
|
-
"version": "2.0.0-
|
|
3
|
+
"version": "2.0.0-next.14",
|
|
4
4
|
"description": "The core GraphQL client for Houdini",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"graphql",
|
|
@@ -21,12 +21,12 @@
|
|
|
21
21
|
"minimatch": "^5.1.0"
|
|
22
22
|
},
|
|
23
23
|
"optionalDependencies": {
|
|
24
|
-
"houdini-core-darwin-x64": "2.0.0-
|
|
25
|
-
"houdini-core-darwin-arm64": "2.0.0-
|
|
26
|
-
"houdini-core-linux-x64": "2.0.0-
|
|
27
|
-
"houdini-core-linux-arm64": "2.0.0-
|
|
28
|
-
"houdini-core-win32-x64": "2.0.0-
|
|
29
|
-
"houdini-core-win32-arm64": "2.0.0-
|
|
24
|
+
"houdini-core-darwin-x64": "2.0.0-next.14",
|
|
25
|
+
"houdini-core-darwin-arm64": "2.0.0-next.14",
|
|
26
|
+
"houdini-core-linux-x64": "2.0.0-next.14",
|
|
27
|
+
"houdini-core-linux-arm64": "2.0.0-next.14",
|
|
28
|
+
"houdini-core-win32-x64": "2.0.0-next.14",
|
|
29
|
+
"houdini-core-win32-arm64": "2.0.0-next.14"
|
|
30
30
|
},
|
|
31
31
|
"bin": "bin/houdini-core",
|
|
32
32
|
"files": [
|
package/postInstall.js
CHANGED
|
@@ -5,7 +5,7 @@ const https = require('https')
|
|
|
5
5
|
const child_process = require('child_process')
|
|
6
6
|
|
|
7
7
|
// Adjust the version you want to install. You can also make this dynamic.
|
|
8
|
-
const BINARY_DISTRIBUTION_VERSION = '2.0.0-
|
|
8
|
+
const BINARY_DISTRIBUTION_VERSION = '2.0.0-next.14'
|
|
9
9
|
|
|
10
10
|
// Windows binaries end with .exe so we need to special case them.
|
|
11
11
|
const binaryName = process.platform === 'win32' ? 'houdini-core.exe' : 'houdini-core'
|
package/runtime/cache.ts
CHANGED
package/runtime/client.ts
CHANGED
|
@@ -64,13 +64,14 @@ export class HoudiniClient extends BaseClient {
|
|
|
64
64
|
)
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
const serverPort =
|
|
68
|
+
globalThis.process?.env?.HOUDINI_PORT ?? globalThis.process?.env?.PORT ?? '5173'
|
|
68
69
|
|
|
69
70
|
super({
|
|
70
71
|
config: getCurrentConfig,
|
|
71
72
|
url:
|
|
72
73
|
url ??
|
|
73
|
-
(globalThis.window ? '' : `
|
|
74
|
+
(globalThis.window ? '' : `http://localhost:${serverPort}`) +
|
|
74
75
|
localApiEndpoint(getCurrentConfig()),
|
|
75
76
|
plugins: flatten(
|
|
76
77
|
([] as NestedList<ClientPlugin>).concat(
|
|
@@ -109,6 +110,10 @@ export class HoudiniClient extends BaseClient {
|
|
|
109
110
|
this.throwOnError_operations = throwOnError?.operations ?? []
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
setCache(cache: Cache) {
|
|
114
|
+
this._cache = cache
|
|
115
|
+
}
|
|
116
|
+
|
|
112
117
|
// Override observe to properly handle cachePolicy plugin
|
|
113
118
|
observe<_Data extends GraphQLObject, _Input extends GraphQLVariables | undefined>({
|
|
114
119
|
enableCache = true,
|
package/runtime/config.ts
CHANGED
|
@@ -40,7 +40,7 @@ export function computeID(configFile: ConfigFile, type: string, data: any): stri
|
|
|
40
40
|
let id = ''
|
|
41
41
|
|
|
42
42
|
for (const field of fields) {
|
|
43
|
-
id += data[field]
|
|
43
|
+
id += `${data[field]}__`
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
return id.slice(0, -2)
|
|
@@ -50,7 +50,6 @@ export function computeID(configFile: ConfigFile, type: string, data: any): stri
|
|
|
50
50
|
let _configFile: ConfigFile | null = null
|
|
51
51
|
|
|
52
52
|
export function localApiEndpoint(configFile: ConfigFile) {
|
|
53
|
-
// @ts-ignore
|
|
54
53
|
return configFile.router?.apiEndpoint ?? '/_api'
|
|
55
54
|
}
|
|
56
55
|
|
package/runtime/index.ts
CHANGED
|
@@ -5,6 +5,7 @@ import type { CacheTypeDef } from './generated'
|
|
|
5
5
|
import { Cache } from './public'
|
|
6
6
|
|
|
7
7
|
export { CachePolicy, PendingValue } from 'houdini/runtime'
|
|
8
|
+
export type { QueryArtifact, GraphQLVariables } from 'houdini/runtime'
|
|
8
9
|
|
|
9
10
|
export * from './client'
|
|
10
11
|
export { getCurrentConfig } from './config'
|
|
@@ -18,7 +19,7 @@ export function graphql(str: string): never {
|
|
|
18
19
|
// the query instead of throwing an error. We don't want to bundle the graphql
|
|
19
20
|
// module into the runtime so all we can do is return the query string
|
|
20
21
|
if (globalThis?.process?.env?.HOUDINI_PLUGIN) {
|
|
21
|
-
// @ts-
|
|
22
|
+
// @ts-expect-error: this is a totally internal/hidden value. user will never see it and we won't
|
|
22
23
|
// and ever get a typed value of this since it's only used in the result of a dynamic
|
|
23
24
|
// import from the plugin which gives Record<string, any>
|
|
24
25
|
return str
|
package/runtime/plugins/cache.ts
CHANGED
package/runtime/plugins/fetch.ts
CHANGED
|
@@ -152,7 +152,8 @@ function handleMultipart(
|
|
|
152
152
|
if (req?.headers) {
|
|
153
153
|
const filtered = Object.entries(req?.headers).filter(([key, value]) => {
|
|
154
154
|
return !(
|
|
155
|
-
key.toLowerCase()
|
|
155
|
+
key.toLowerCase() === 'content-type' &&
|
|
156
|
+
value.toLowerCase() === 'application/json'
|
|
156
157
|
)
|
|
157
158
|
})
|
|
158
159
|
headers = Object.fromEntries(filtered)
|
|
@@ -163,7 +164,7 @@ function handleMultipart(
|
|
|
163
164
|
const form = new FormData()
|
|
164
165
|
|
|
165
166
|
// if we have a body, just use it.
|
|
166
|
-
if (args
|
|
167
|
+
if (args?.body) {
|
|
167
168
|
form.set('operations', args?.body as string)
|
|
168
169
|
} else {
|
|
169
170
|
form.set(
|
|
@@ -185,7 +186,7 @@ function handleMultipart(
|
|
|
185
186
|
form.set('map', JSON.stringify(map))
|
|
186
187
|
|
|
187
188
|
i = 0
|
|
188
|
-
files.forEach((
|
|
189
|
+
files.forEach((_paths, file) => {
|
|
189
190
|
form.set(`${++i}`, file as Blob, (file as File).name)
|
|
190
191
|
})
|
|
191
192
|
|
|
@@ -207,8 +208,8 @@ type ExtractableFile = File | Blob
|
|
|
207
208
|
|
|
208
209
|
/** @typedef {import("./isExtractableFile.mjs").default} isExtractableFile */
|
|
209
210
|
|
|
210
|
-
export function extractFiles(value
|
|
211
|
-
if (
|
|
211
|
+
export function extractFiles(value?: any) {
|
|
212
|
+
if (value === undefined) throw new TypeError('Argument 1 `value` is required.')
|
|
212
213
|
|
|
213
214
|
/**
|
|
214
215
|
* Map of values recursed within the input value and their clones, for reusing
|
|
@@ -249,9 +250,9 @@ export function extractFiles(value: any) {
|
|
|
249
250
|
clone = valueIsList
|
|
250
251
|
? []
|
|
251
252
|
: // Replicate if the plain object is an `Object` instance.
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
253
|
+
value instanceof /** @type {any} */ Object
|
|
254
|
+
? {}
|
|
255
|
+
: Object.create(null)
|
|
255
256
|
|
|
256
257
|
clones.set(value, /** @type {Clone} */ clone)
|
|
257
258
|
}
|
|
@@ -263,7 +264,6 @@ export function extractFiles(value: any) {
|
|
|
263
264
|
if (valueIsList) {
|
|
264
265
|
let index = 0
|
|
265
266
|
|
|
266
|
-
// @ts-ignore
|
|
267
267
|
for (const item of value) {
|
|
268
268
|
const itemClone = recurse(item, pathPrefix + index++, recursedDeeper)
|
|
269
269
|
|
|
@@ -7,7 +7,7 @@ import { documentPlugin } from './utils'
|
|
|
7
7
|
// the purpose of the fragment plugin is to provide fine-reactivity for cache updates
|
|
8
8
|
// there are no network requests that get sent. send() always returns the initial value
|
|
9
9
|
export const fragment = (cache: Cache) =>
|
|
10
|
-
documentPlugin(ArtifactKind.Fragment,
|
|
10
|
+
documentPlugin(ArtifactKind.Fragment, () => {
|
|
11
11
|
// track the bits of state we need to hold onto
|
|
12
12
|
let subscriptionSpec: SubscriptionSpec | null = null
|
|
13
13
|
|
|
@@ -173,9 +173,9 @@ function addKeysToResponse(args: {
|
|
|
173
173
|
}): any {
|
|
174
174
|
// we need to walk the selection and inject the optimistic keys into the response
|
|
175
175
|
// collect all of the fields that we need to write
|
|
176
|
-
|
|
176
|
+
const targetSelection = getFieldsForType(
|
|
177
177
|
args.selection,
|
|
178
|
-
args.response
|
|
178
|
+
args.response.__typename as string | undefined,
|
|
179
179
|
false
|
|
180
180
|
)
|
|
181
181
|
const newKeys = []
|
|
@@ -190,7 +190,7 @@ function addKeysToResponse(args: {
|
|
|
190
190
|
// if this field is marked as an optimistic key, add it to the obj
|
|
191
191
|
if (optimisticKey) {
|
|
192
192
|
// figure out the value we should use for the optimistic key
|
|
193
|
-
let keyValue
|
|
193
|
+
let keyValue: string | number | undefined
|
|
194
194
|
|
|
195
195
|
// if there is a value already in the response then we should use that
|
|
196
196
|
if (value) {
|
|
@@ -240,7 +240,7 @@ function addKeysToResponse(args: {
|
|
|
240
240
|
})
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
|
-
} else if (value && typeof value
|
|
243
|
+
} else if (value && typeof value === 'object') {
|
|
244
244
|
addKeysToResponse({
|
|
245
245
|
...args,
|
|
246
246
|
selection: fieldSelection,
|
|
@@ -306,9 +306,9 @@ function extractResponseKeys(
|
|
|
306
306
|
type: string = ''
|
|
307
307
|
) {
|
|
308
308
|
// collect all of the fields that we need to write
|
|
309
|
-
|
|
309
|
+
const targetSelection = getFieldsForType(
|
|
310
310
|
selection,
|
|
311
|
-
response
|
|
311
|
+
response.__typename as string | undefined,
|
|
312
312
|
false
|
|
313
313
|
)
|
|
314
314
|
|
|
@@ -334,7 +334,7 @@ function extractResponseKeys(
|
|
|
334
334
|
}
|
|
335
335
|
|
|
336
336
|
// look up the field in our schema
|
|
337
|
-
|
|
337
|
+
const { type, selection: fieldSelection } = targetSelection[field]
|
|
338
338
|
|
|
339
339
|
// walk down lists in the response
|
|
340
340
|
if (Array.isArray(value)) {
|
|
@@ -438,15 +438,15 @@ function replaceKeyWithVariable(
|
|
|
438
438
|
|
|
439
439
|
function generateKey(type: string) {
|
|
440
440
|
if (type === 'Int') {
|
|
441
|
-
return
|
|
441
|
+
return Date.now()
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
if (type === 'String') {
|
|
445
|
-
return
|
|
445
|
+
return Date.now().toString()
|
|
446
446
|
}
|
|
447
447
|
|
|
448
448
|
if (type === 'ID') {
|
|
449
|
-
return
|
|
449
|
+
return Date.now().toString()
|
|
450
450
|
}
|
|
451
451
|
|
|
452
452
|
throw new Error(
|
package/runtime/plugins/query.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { type SubscriptionSpec, ArtifactKind, DataSource } from 'houdini/runtime
|
|
|
5
5
|
import { documentPlugin } from './utils'
|
|
6
6
|
|
|
7
7
|
export const query = (cache: Cache) =>
|
|
8
|
-
documentPlugin(ArtifactKind.Query,
|
|
8
|
+
documentPlugin(ArtifactKind.Query, () => {
|
|
9
9
|
// track the bits of state we need to hold onto
|
|
10
10
|
let subscriptionSpec: SubscriptionSpec | null = null
|
|
11
11
|
|
|
@@ -22,7 +22,7 @@ export const documentPlugin = (kind: ArtifactKinds, source: () => ClientHooks):
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
return handler(ctx, handlers)
|
|
25
|
-
|
|
25
|
+
}
|
|
26
26
|
}
|
|
27
27
|
const exitWrapper = (
|
|
28
28
|
handler?: ClientPluginExitPhase
|
|
@@ -35,7 +35,7 @@ export const documentPlugin = (kind: ArtifactKinds, source: () => ClientHooks):
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
return handler(ctx, handlers)
|
|
38
|
-
|
|
38
|
+
}
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
// return the modified hooks
|
package/runtime/public/cache.ts
CHANGED
|
@@ -27,7 +27,7 @@ export class Cache<Def extends CacheTypeDef> {
|
|
|
27
27
|
// return the record proxy for the given type/id combo
|
|
28
28
|
get<T extends TypeNames<Def>>(type: T, data: IDFields<Def, T>): Record<Def, T> {
|
|
29
29
|
// compute the id for the record
|
|
30
|
-
|
|
30
|
+
const recordID = this._internal_unstable._internal_unstable.id(type, data)
|
|
31
31
|
if (!recordID) {
|
|
32
32
|
throw new Error('todo')
|
|
33
33
|
}
|
|
@@ -108,7 +108,7 @@ export class Cache<Def extends CacheTypeDef> {
|
|
|
108
108
|
when?: ArgType<Def, _Type, _Field>
|
|
109
109
|
}
|
|
110
110
|
): void {
|
|
111
|
-
|
|
111
|
+
this._internal_unstable.markTypeStale(type ? { ...options, type } : undefined)
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
/**
|
|
@@ -116,6 +116,6 @@ export class Cache<Def extends CacheTypeDef> {
|
|
|
116
116
|
*/
|
|
117
117
|
|
|
118
118
|
reset(): void {
|
|
119
|
-
|
|
119
|
+
this._internal_unstable.reset()
|
|
120
120
|
}
|
|
121
121
|
}
|
package/runtime/public/list.ts
CHANGED
|
@@ -138,7 +138,7 @@ export class ListCollection<Def extends CacheTypeDef, ListName extends ValidList
|
|
|
138
138
|
let selection: SubscriptionSelection = this.#collection!.selection
|
|
139
139
|
// if the list is a connection, we can't use this selection immediately
|
|
140
140
|
// we need to look for edges.node
|
|
141
|
-
const connectionSelection = selection.fields?.
|
|
141
|
+
const connectionSelection = selection.fields?.edges?.selection?.fields?.node.selection
|
|
142
142
|
if (connectionSelection) {
|
|
143
143
|
selection = connectionSelection
|
|
144
144
|
}
|
package/runtime/public/record.ts
CHANGED
|
@@ -41,7 +41,7 @@ export class Record<Def extends CacheTypeDef, Type extends ValidTypes<Def>> {
|
|
|
41
41
|
if (id !== rootID) {
|
|
42
42
|
for (const key of keyFieldsForType(this.#cache.config, type)) {
|
|
43
43
|
if (!(key in idFields)) {
|
|
44
|
-
throw new Error(
|
|
44
|
+
throw new Error(`Missing key in idFields: ${key}`)
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
}
|
package/runtime/public/types.ts
CHANGED
|
@@ -36,12 +36,12 @@ export type ValidTypes<Def extends CacheTypeDef> = keyof Def['types']
|
|
|
36
36
|
|
|
37
37
|
export type TypeFields<
|
|
38
38
|
Def extends CacheTypeDef,
|
|
39
|
-
Type extends keyof Def['types']
|
|
39
|
+
Type extends keyof Def['types'],
|
|
40
40
|
> = Def['types'][Type]['fields']
|
|
41
41
|
|
|
42
42
|
export type TypeFieldNames<
|
|
43
43
|
Def extends CacheTypeDef,
|
|
44
|
-
Type extends keyof Def['types']
|
|
44
|
+
Type extends keyof Def['types'],
|
|
45
45
|
// Extract is necessary because javascript allows numbers to be used as strings when indexing objects
|
|
46
46
|
// for more information: https://stackoverflow.com/questions/51808160/keyof-inferring-string-number-when-key-is-only-a-string
|
|
47
47
|
> = Extract<keyof TypeFields<Def, Type>, string>
|
|
@@ -53,44 +53,44 @@ export type TypeNames<Def extends CacheTypeDef> = Extract<
|
|
|
53
53
|
|
|
54
54
|
export type FragmentList<
|
|
55
55
|
Def extends CacheTypeDef,
|
|
56
|
-
Type extends ValidTypes<Def
|
|
56
|
+
Type extends ValidTypes<Def>,
|
|
57
57
|
> = Def['types'][Type]['fragments']
|
|
58
58
|
|
|
59
59
|
export type QueryList<Def extends CacheTypeDef> = Def['queries']
|
|
60
60
|
|
|
61
61
|
export type IDFields<
|
|
62
62
|
Def extends CacheTypeDef,
|
|
63
|
-
Type extends keyof Def['types']
|
|
63
|
+
Type extends keyof Def['types'],
|
|
64
64
|
> = Def['types'][Type]['idFields']
|
|
65
65
|
|
|
66
66
|
export type ProxyUnion<Def extends CacheTypeDef, U> = U extends null
|
|
67
67
|
? null
|
|
68
68
|
: U extends TypeNames<Def>
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
? Record<Def, U>
|
|
70
|
+
: never
|
|
71
71
|
|
|
72
72
|
export type FieldType<
|
|
73
73
|
Def extends CacheTypeDef,
|
|
74
74
|
Type extends keyof Def['types'],
|
|
75
|
-
Field extends keyof TypeFields<Def, Type
|
|
75
|
+
Field extends keyof TypeFields<Def, Type>,
|
|
76
76
|
> = TypeFields<Def, Type>[Field]['type']
|
|
77
77
|
|
|
78
78
|
export type ArgType<
|
|
79
79
|
Def extends CacheTypeDef,
|
|
80
80
|
Type extends keyof Def['types'],
|
|
81
|
-
Field extends keyof TypeFields<Def, Type
|
|
81
|
+
Field extends keyof TypeFields<Def, Type>,
|
|
82
82
|
> = TypeFields<Def, Type>[Field]['args']
|
|
83
83
|
|
|
84
84
|
export type ValidLists<Def extends CacheTypeDef> = Extract<keyof Def['lists'], string>
|
|
85
85
|
|
|
86
86
|
export type ListFilters<
|
|
87
87
|
Def extends CacheTypeDef,
|
|
88
|
-
ListName extends ValidLists<Def
|
|
88
|
+
ListName extends ValidLists<Def>,
|
|
89
89
|
> = Def['lists'][ListName]['filters'] extends any
|
|
90
90
|
? {
|
|
91
91
|
must?: Def['lists'][ListName]['filters']
|
|
92
92
|
must_not?: Def['lists'][ListName]['filters']
|
|
93
|
-
|
|
93
|
+
}
|
|
94
94
|
: never
|
|
95
95
|
|
|
96
96
|
export type ListType<Def extends CacheTypeDef, Name extends ValidLists<Def>> = ProxyUnion<
|