polen 0.11.0-next.21 → 0.11.0-next.23
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/build/api/config/normalized.d.ts +200 -200
- package/build/api/examples/schemas/catalog.d.ts +4 -4
- package/build/api/examples/schemas/type-usage-index.d.ts +5 -5
- package/build/api/examples/schemas/type-usage-index.js +2 -2
- package/build/api/examples/schemas/type-usage-index.js.map +1 -1
- package/build/api/examples/type-usage-indexer.d.ts.map +1 -1
- package/build/api/examples/type-usage-indexer.js +43 -37
- package/build/api/examples/type-usage-indexer.js.map +1 -1
- package/build/api/schema/input-sources/directory.d.ts +1 -1
- package/build/api/schema/input-sources/directory.js +3 -3
- package/build/api/schema/input-sources/directory.js.map +1 -1
- package/build/api/schema/input-sources/file.d.ts +1 -1
- package/build/api/schema/input-sources/file.js +3 -3
- package/build/api/schema/input-sources/file.js.map +1 -1
- package/build/api/schema/input-sources/introspection-file.d.ts +1 -1
- package/build/api/schema/input-sources/introspection.d.ts +1 -1
- package/build/api/schema/input-sources/memory.d.ts +1 -1
- package/build/api/schema/input-sources/memory.js +3 -3
- package/build/api/schema/input-sources/memory.js.map +1 -1
- package/build/api/schema/input-sources/versioned-directory.d.ts +2 -2
- package/build/api/schema/input-sources/versioned-directory.js +3 -3
- package/build/api/schema/input-sources/versioned-directory.js.map +1 -1
- package/build/cli/commands/open.js +1 -1
- package/build/cli/commands/open.js.map +1 -1
- package/build/lib/catalog/catalog.d.ts +30 -30
- package/build/lib/catalog/unversioned.d.ts +8 -8
- package/build/lib/catalog/versioned.d.ts +16 -16
- package/build/lib/change/change.d.ts +6 -6
- package/build/lib/grafaid/$$.d.ts +2 -0
- package/build/lib/grafaid/$$.d.ts.map +1 -1
- package/build/lib/grafaid/$$.js +2 -0
- package/build/lib/grafaid/$$.js.map +1 -1
- package/build/lib/grafaid/parse-error.d.ts +46 -0
- package/build/lib/grafaid/parse-error.d.ts.map +1 -0
- package/build/lib/grafaid/parse-error.js +29 -0
- package/build/lib/grafaid/parse-error.js.map +1 -0
- package/build/lib/grafaid/parse.d.ts +70 -0
- package/build/lib/grafaid/parse.d.ts.map +1 -0
- package/build/lib/grafaid/parse.js +119 -0
- package/build/lib/grafaid/parse.js.map +1 -0
- package/build/lib/grafaid/schema/ast.d.ts +0 -2
- package/build/lib/grafaid/schema/ast.d.ts.map +1 -1
- package/build/lib/grafaid/schema/ast.js +1 -7
- package/build/lib/grafaid/schema/ast.js.map +1 -1
- package/build/lib/grafaid/schema/read.js +2 -2
- package/build/lib/grafaid/schema/read.js.map +1 -1
- package/build/lib/grafaid/schema/schema.d.ts +2 -1
- package/build/lib/grafaid/schema/schema.d.ts.map +1 -1
- package/build/lib/grafaid/schema/schema.js +5 -1
- package/build/lib/grafaid/schema/schema.js.map +1 -1
- package/build/lib/graphql-schema-loader/graphql-schema-loader.d.ts.map +1 -1
- package/build/lib/graphql-schema-loader/graphql-schema-loader.js +4 -4
- package/build/lib/graphql-schema-loader/graphql-schema-loader.js.map +1 -1
- package/build/lib/revision/revision.d.ts +30 -30
- package/build/lib/schema/schema.d.ts +18 -18
- package/build/lib/schema/unversioned.d.ts +28 -28
- package/build/lib/schema/versioned.d.ts +16 -16
- package/build/template/components/ExampleLink.d.ts.map +1 -1
- package/build/template/components/ExampleLink.js +4 -2
- package/build/template/components/ExampleLink.js.map +1 -1
- package/build/template/components/NamedType.d.ts.map +1 -1
- package/build/template/components/NamedType.js +1 -1
- package/build/template/components/NamedType.js.map +1 -1
- package/build/template/components/VersionCoveragePicker.d.ts.map +1 -1
- package/build/template/components/VersionCoveragePicker.js +6 -1
- package/build/template/components/VersionCoveragePicker.js.map +1 -1
- package/build/template/components/navbar/DefaultNavbar.js +1 -1
- package/build/template/layouts/SidebarLayout.js +1 -1
- package/build/template/routes/changelog/ChangelogBody.d.ts.map +1 -1
- package/build/template/routes/changelog/ChangelogBody.js +1 -1
- package/build/template/routes/changelog/ChangelogBody.js.map +1 -1
- package/build/template/routes/changelog/ChangelogSidebar.js +1 -1
- package/build/template/routes/changelog/ChangelogSidebar.js.map +1 -1
- package/build/template/routes/index.js +1 -1
- package/build/template/routes/index.js.map +1 -1
- package/build/template/routes/root.d.ts.map +1 -1
- package/build/template/routes/root.js +5 -3
- package/build/template/routes/root.js.map +1 -1
- package/build/template/stores/changelog.d.ts +1 -1
- package/build/template/theme/swiss-sharp.css +1 -0
- package/build/vite/plugins/examples.d.ts.map +1 -1
- package/build/vite/plugins/examples.js +1 -2
- package/build/vite/plugins/examples.js.map +1 -1
- package/package.json +1 -1
- package/src/api/examples/schemas/type-usage-index.ts +2 -2
- package/src/api/examples/type-usage-indexer.test.ts +152 -234
- package/src/api/examples/type-usage-indexer.ts +66 -54
- package/src/api/schema/$.test.ts +1 -1
- package/src/api/schema/input-sources/directory.ts +3 -3
- package/src/api/schema/input-sources/file.ts +3 -3
- package/src/api/schema/input-sources/memory.ts +3 -3
- package/src/api/schema/input-sources/versioned-directory.ts +3 -3
- package/src/cli/commands/open.ts +1 -1
- package/src/lib/grafaid/$$.ts +2 -0
- package/src/lib/grafaid/parse-error.ts +69 -0
- package/src/lib/grafaid/parse.test.ts +175 -0
- package/src/lib/grafaid/parse.ts +165 -0
- package/src/lib/grafaid/schema/ast.ts +1 -9
- package/src/lib/grafaid/schema/read.ts +2 -2
- package/src/lib/grafaid/schema/schema.ts +10 -2
- package/src/lib/graphql-schema-loader/graphql-schema-loader.ts +4 -12
- package/src/lib/path-map/$.test.ts +28 -13
- package/src/template/components/ExampleLink.tsx +4 -2
- package/src/template/components/NamedType.tsx +5 -3
- package/src/template/components/VersionCoveragePicker.tsx +8 -2
- package/src/template/components/navbar/DefaultNavbar.tsx +1 -1
- package/src/template/layouts/SidebarLayout.tsx +1 -1
- package/src/template/routes/changelog/ChangelogBody.tsx +6 -2
- package/src/template/routes/changelog/ChangelogSidebar.tsx +1 -1
- package/src/template/routes/index.tsx +1 -1
- package/src/template/routes/root.tsx +5 -0
- package/src/template/theme/swiss-sharp.css +1 -0
- package/src/vite/plugins/examples.ts +1 -2
@@ -2,82 +2,90 @@ import { Catalog } from '#lib/catalog/$'
|
|
2
2
|
import { Document } from '#lib/document/$'
|
3
3
|
import { Schema } from '#lib/schema/$'
|
4
4
|
import { Version } from '#lib/version/$'
|
5
|
-
import { HashMap, HashSet
|
6
|
-
import { buildSchema } from 'graphql'
|
5
|
+
import { HashMap, HashSet } from 'effect'
|
6
|
+
import { buildSchema, type GraphQLSchema } from 'graphql'
|
7
7
|
import { describe, expect, test } from 'vitest'
|
8
8
|
import { Example } from './schemas/example/example.js'
|
9
|
-
import
|
9
|
+
import { ExampleReference } from './schemas/type-usage-index.js'
|
10
10
|
import { createTypeUsageIndex, getExampleReferencesForType } from './type-usage-indexer.js'
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
describe('createTypeUsageIndex', () => {
|
44
|
-
test('indexes unversioned examples', () => {
|
45
|
-
const example = Example.make({
|
46
|
-
name: 'get-user',
|
47
|
-
path: 'examples/get-user.graphql',
|
48
|
-
document: Document.Unversioned.make({
|
49
|
-
document: 'query { user(id: "1") { id name } }',
|
50
|
-
}),
|
51
|
-
})
|
52
|
-
|
53
|
-
const catalog = Catalog.Unversioned.make({
|
54
|
-
schema: Schema.Unversioned.make({
|
55
|
-
definition: schemaDef,
|
56
|
-
revisions: [],
|
57
|
-
}),
|
58
|
-
})
|
59
|
-
|
60
|
-
const index = createTypeUsageIndex([example], catalog)
|
61
|
-
|
62
|
-
// For unversioned examples, they get indexed with the latest version (1.0.0 default)
|
63
|
-
const defaultVersion = Version.decodeSync('1.0.0')
|
12
|
+
// Test schema
|
13
|
+
const schemaString = `
|
14
|
+
type Query {
|
15
|
+
user(id: ID!): User
|
16
|
+
users: [User!]!
|
17
|
+
product(id: ID!): Product
|
18
|
+
}
|
19
|
+
type User {
|
20
|
+
id: ID!
|
21
|
+
name: String!
|
22
|
+
email: String!
|
23
|
+
}
|
24
|
+
type Product {
|
25
|
+
id: ID!
|
26
|
+
name: String!
|
27
|
+
price: Float!
|
28
|
+
}
|
29
|
+
interface Node {
|
30
|
+
id: ID!
|
31
|
+
}
|
32
|
+
union SearchResult = User | Product
|
33
|
+
`
|
34
|
+
const schemaDef = buildSchema(schemaString)
|
35
|
+
const version1 = Version.decodeSync('1.0.0')
|
36
|
+
const version2 = Version.decodeSync('2.0.0')
|
37
|
+
|
38
|
+
// Test helpers
|
39
|
+
const makeUnversionedCatalog = (definition: GraphQLSchema) =>
|
40
|
+
Catalog.Unversioned.make({
|
41
|
+
schema: Schema.Unversioned.make({ definition, revisions: [] }),
|
42
|
+
})
|
64
43
|
|
65
|
-
|
66
|
-
|
67
|
-
|
44
|
+
const makeVersionedCatalog = (definition: GraphQLSchema, versions: Version.Version[]) =>
|
45
|
+
Catalog.Versioned.make({
|
46
|
+
entries: HashMap.make(
|
47
|
+
...versions.map(v =>
|
48
|
+
[
|
49
|
+
v,
|
50
|
+
Schema.Versioned.make({
|
51
|
+
version: v,
|
52
|
+
definition,
|
53
|
+
branchPoint: null,
|
54
|
+
revisions: [],
|
55
|
+
}),
|
56
|
+
] as const
|
57
|
+
),
|
58
|
+
),
|
59
|
+
})
|
68
60
|
|
69
|
-
|
70
|
-
|
61
|
+
describe('createTypeUsageIndex', () => {
|
62
|
+
test.for([
|
63
|
+
{ type: 'Query', shouldExist: true },
|
64
|
+
{ type: 'User', shouldExist: true },
|
65
|
+
{ type: 'Product', shouldExist: false },
|
66
|
+
])('indexes unversioned example - type $type indexed=$shouldExist', ({ type, shouldExist }) => {
|
67
|
+
const example = Example.make({
|
68
|
+
name: 'get-user',
|
69
|
+
path: 'examples/get-user.graphql',
|
70
|
+
document: Document.Unversioned.make({
|
71
|
+
document: 'query { user(id: "1") { id name } }',
|
72
|
+
}),
|
73
|
+
})
|
71
74
|
|
72
|
-
|
73
|
-
|
75
|
+
const index = createTypeUsageIndex([example], makeUnversionedCatalog(schemaDef))
|
76
|
+
const refs = getExampleReferencesForType(index, type)
|
74
77
|
|
75
|
-
|
76
|
-
|
77
|
-
expect(
|
78
|
-
}
|
78
|
+
if (shouldExist) {
|
79
|
+
expect(HashSet.size(refs)).toBe(1)
|
80
|
+
expect([...refs][0]).toEqual({ name: 'get-user', version: null })
|
81
|
+
} else {
|
82
|
+
expect(HashSet.size(refs)).toBe(0)
|
83
|
+
}
|
84
|
+
})
|
79
85
|
|
80
|
-
|
86
|
+
test.for([version1, version2])(
|
87
|
+
'indexes versioned examples for version %s',
|
88
|
+
(version) => {
|
81
89
|
const example = Example.make({
|
82
90
|
name: 'get-user-versioned',
|
83
91
|
path: 'examples/get-user-versioned.graphql',
|
@@ -89,188 +97,98 @@ describe('type-usage-indexer', () => {
|
|
89
97
|
}),
|
90
98
|
})
|
91
99
|
|
92
|
-
const
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
Schema.Versioned.make({
|
97
|
-
version: version1,
|
98
|
-
definition: schemaDef,
|
99
|
-
branchPoint: null,
|
100
|
-
revisions: [],
|
101
|
-
}),
|
102
|
-
],
|
103
|
-
[
|
104
|
-
version2,
|
105
|
-
Schema.Versioned.make({
|
106
|
-
version: version2,
|
107
|
-
definition: schemaDef,
|
108
|
-
branchPoint: null,
|
109
|
-
revisions: [],
|
110
|
-
}),
|
111
|
-
],
|
112
|
-
),
|
113
|
-
})
|
114
|
-
|
115
|
-
const index = createTypeUsageIndex([example], catalog)
|
116
|
-
|
117
|
-
// Check version 1 references
|
118
|
-
const userRefsV1 = getExampleReferencesForType(index, 'User', version1)
|
119
|
-
expect(HashSet.size(userRefsV1)).toBe(1)
|
120
|
-
expect([...userRefsV1][0]).toEqual({ name: 'get-user-versioned', version: version1 })
|
121
|
-
|
122
|
-
// Check version 2 references
|
123
|
-
const userRefsV2 = getExampleReferencesForType(index, 'User', version2)
|
124
|
-
expect(HashSet.size(userRefsV2)).toBe(1)
|
125
|
-
expect([...userRefsV2][0]).toEqual({ name: 'get-user-versioned', version: version2 })
|
126
|
-
})
|
127
|
-
|
128
|
-
test('deduplicates example references using HashSet', () => {
|
129
|
-
// Create two examples that use the same types
|
130
|
-
const example1 = Example.make({
|
131
|
-
name: 'get-user-1',
|
132
|
-
path: 'examples/get-user-1.graphql',
|
133
|
-
document: Document.Unversioned.make({
|
134
|
-
document: 'query { user(id: "1") { id name } }',
|
135
|
-
}),
|
136
|
-
})
|
100
|
+
const index = createTypeUsageIndex(
|
101
|
+
[example],
|
102
|
+
makeVersionedCatalog(schemaDef, [version1, version2]),
|
103
|
+
)
|
137
104
|
|
138
|
-
const
|
139
|
-
|
140
|
-
|
105
|
+
const userRefs = getExampleReferencesForType(index, 'User', version)
|
106
|
+
expect(HashSet.size(userRefs)).toBe(1)
|
107
|
+
expect([...userRefs][0]).toEqual({ name: 'get-user-versioned', version })
|
108
|
+
},
|
109
|
+
)
|
110
|
+
|
111
|
+
test('deduplicates example references using HashSet', () => {
|
112
|
+
const examples = ['get-user-1', 'get-user-2'].map(name =>
|
113
|
+
Example.make({
|
114
|
+
name,
|
115
|
+
path: `examples/${name}.graphql`,
|
141
116
|
document: Document.Unversioned.make({
|
142
|
-
document:
|
117
|
+
document: `query { user(id: "${name}") { id name } }`,
|
143
118
|
}),
|
144
119
|
})
|
120
|
+
)
|
145
121
|
|
146
|
-
|
147
|
-
|
148
|
-
definition: schemaDef,
|
149
|
-
revisions: [],
|
150
|
-
}),
|
151
|
-
})
|
152
|
-
|
153
|
-
const index = createTypeUsageIndex([example1, example2], catalog)
|
154
|
-
|
155
|
-
// For unversioned examples with unversioned catalog, use default version
|
156
|
-
const defaultVersion = Version.decodeSync('1.0.0')
|
122
|
+
const index = createTypeUsageIndex(examples, makeUnversionedCatalog(schemaDef))
|
123
|
+
const userRefs = getExampleReferencesForType(index, 'User')
|
157
124
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
const refNames = [...userRefs].map(ref => ref.name).sort()
|
163
|
-
expect(refNames).toEqual(['get-user-1', 'get-user-2'])
|
125
|
+
expect(HashSet.size(userRefs)).toBe(2)
|
126
|
+
expect([...userRefs].map(ref => ref.name).sort()).toEqual(['get-user-1', 'get-user-2'])
|
127
|
+
expect([...userRefs].every(ref => ref.version === null)).toBe(true)
|
128
|
+
})
|
164
129
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
130
|
+
test('handles interface and union types', () => {
|
131
|
+
const example = Example.make({
|
132
|
+
name: 'search',
|
133
|
+
path: 'examples/search.graphql',
|
134
|
+
document: Document.Unversioned.make({
|
135
|
+
document: `query { user(id: "1") { ... on Node { id } } }`,
|
136
|
+
}),
|
169
137
|
})
|
170
138
|
|
171
|
-
|
172
|
-
|
173
|
-
name: 'search',
|
174
|
-
path: 'examples/search.graphql',
|
175
|
-
document: Document.Unversioned.make({
|
176
|
-
document: `
|
177
|
-
query {
|
178
|
-
user(id: "1") {
|
179
|
-
... on Node {
|
180
|
-
id
|
181
|
-
}
|
182
|
-
}
|
183
|
-
}
|
184
|
-
`,
|
185
|
-
}),
|
186
|
-
})
|
187
|
-
|
188
|
-
const catalog = Catalog.Unversioned.make({
|
189
|
-
schema: Schema.Unversioned.make({
|
190
|
-
definition: schemaDef,
|
191
|
-
revisions: [],
|
192
|
-
}),
|
193
|
-
})
|
194
|
-
|
195
|
-
const index = createTypeUsageIndex([example], catalog)
|
139
|
+
const index = createTypeUsageIndex([example], makeUnversionedCatalog(schemaDef))
|
140
|
+
const nodeRefs = getExampleReferencesForType(index, 'Node')
|
196
141
|
|
197
|
-
|
198
|
-
|
142
|
+
expect(HashSet.size(nodeRefs)).toBe(1)
|
143
|
+
expect([...nodeRefs][0]).toEqual({ name: 'search', version: null })
|
144
|
+
})
|
199
145
|
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
146
|
+
test('indexes examples with version sets', () => {
|
147
|
+
const versionSet = HashSet.make(version1, version2)
|
148
|
+
const example = Example.make({
|
149
|
+
name: 'shared-example',
|
150
|
+
path: 'examples/shared.graphql',
|
151
|
+
document: Document.Versioned.make({
|
152
|
+
versionDocuments: HashMap.make([versionSet, 'query { user(id: "1") { id name } }']),
|
153
|
+
}),
|
204
154
|
})
|
205
155
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
name: 'shared-example',
|
211
|
-
path: 'examples/shared.graphql',
|
212
|
-
document: Document.Versioned.make({
|
213
|
-
versionDocuments: HashMap.make(
|
214
|
-
[versionSet, 'query { user(id: "1") { id name } }'],
|
215
|
-
),
|
216
|
-
}),
|
217
|
-
})
|
218
|
-
|
219
|
-
const catalog = Catalog.Versioned.make({
|
220
|
-
entries: HashMap.make(
|
221
|
-
[
|
222
|
-
version1,
|
223
|
-
Schema.Versioned.make({
|
224
|
-
version: version1,
|
225
|
-
definition: schemaDef,
|
226
|
-
branchPoint: null,
|
227
|
-
revisions: [],
|
228
|
-
}),
|
229
|
-
],
|
230
|
-
[
|
231
|
-
version2,
|
232
|
-
Schema.Versioned.make({
|
233
|
-
version: version2,
|
234
|
-
definition: schemaDef,
|
235
|
-
branchPoint: null,
|
236
|
-
revisions: [],
|
237
|
-
}),
|
238
|
-
],
|
239
|
-
),
|
240
|
-
})
|
241
|
-
|
242
|
-
const index = createTypeUsageIndex([example], catalog)
|
243
|
-
|
244
|
-
// Both versions should have the same example reference
|
245
|
-
const userRefsV1 = getExampleReferencesForType(index, 'User', version1)
|
246
|
-
expect(HashSet.size(userRefsV1)).toBe(1)
|
247
|
-
expect([...userRefsV1][0]).toEqual({ name: 'shared-example', version: version1 })
|
156
|
+
const index = createTypeUsageIndex(
|
157
|
+
[example],
|
158
|
+
makeVersionedCatalog(schemaDef, [version1, version2]),
|
159
|
+
)
|
248
160
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
161
|
+
// Both versions should have the same example reference
|
162
|
+
for (const version of [version1, version2]) {
|
163
|
+
const userRefs = getExampleReferencesForType(index, 'User', version)
|
164
|
+
expect(HashSet.size(userRefs)).toBe(1)
|
165
|
+
expect([...userRefs][0]).toEqual({ name: 'shared-example', version })
|
166
|
+
}
|
253
167
|
})
|
168
|
+
})
|
254
169
|
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
170
|
+
describe('ExampleReference', () => {
|
171
|
+
test('structural equality works with HashSet', () => {
|
172
|
+
const version = Version.decodeSync('1.0.0')
|
173
|
+
|
174
|
+
// Create set with duplicates to test deduplication
|
175
|
+
const refs = [
|
176
|
+
ExampleReference.make({ name: 'example1', version }),
|
177
|
+
ExampleReference.make({ name: 'example1', version }), // duplicate
|
178
|
+
ExampleReference.make({ name: 'example2', version }),
|
179
|
+
ExampleReference.make({ name: 'example3', version: null }),
|
180
|
+
ExampleReference.make({ name: 'example3', version: null }), // duplicate
|
181
|
+
]
|
182
|
+
|
183
|
+
const set = refs.reduce(
|
184
|
+
(acc, ref) => HashSet.add(acc, ref),
|
185
|
+
HashSet.empty<ExampleReference>(),
|
186
|
+
)
|
187
|
+
|
188
|
+
// Should have only 3 unique references
|
189
|
+
expect(HashSet.size(set)).toBe(3)
|
190
|
+
expect(HashSet.has(set, ExampleReference.make({ name: 'example1', version }))).toBe(true)
|
191
|
+
expect(HashSet.has(set, ExampleReference.make({ name: 'example2', version }))).toBe(true)
|
192
|
+
expect(HashSet.has(set, ExampleReference.make({ name: 'example3', version: null }))).toBe(true)
|
275
193
|
})
|
276
194
|
})
|
@@ -1,19 +1,11 @@
|
|
1
1
|
import { Catalog } from '#lib/catalog/$'
|
2
2
|
import { Document } from '#lib/document/$'
|
3
|
+
import { Grafaid } from '#lib/grafaid'
|
4
|
+
import { Schema } from '#lib/schema/$'
|
3
5
|
import { Version } from '#lib/version/$'
|
4
|
-
import { HashMap, HashSet, Option } from 'effect'
|
6
|
+
import { Effect, HashMap, HashSet, Option } from 'effect'
|
5
7
|
import { Schema as S } from 'effect'
|
6
|
-
import {
|
7
|
-
type DocumentNode,
|
8
|
-
getNamedType,
|
9
|
-
type GraphQLSchema,
|
10
|
-
isInterfaceType,
|
11
|
-
isObjectType,
|
12
|
-
isUnionType,
|
13
|
-
Kind,
|
14
|
-
parse,
|
15
|
-
visit,
|
16
|
-
} from 'graphql'
|
8
|
+
import { getNamedType, type GraphQLSchema, isInterfaceType, isObjectType, isUnionType, Kind, visit } from 'graphql'
|
17
9
|
import type { Example } from './schemas/example/example.js'
|
18
10
|
import { ExampleReference, type TypeUsageIndex, UNVERSIONED_KEY, type VersionKey } from './schemas/type-usage-index.js'
|
19
11
|
|
@@ -30,20 +22,17 @@ import { ExampleReference, type TypeUsageIndex, UNVERSIONED_KEY, type VersionKey
|
|
30
22
|
* - For interfaces: both the interface and all implementations
|
31
23
|
* - For unions: both the union and all member types
|
32
24
|
*/
|
33
|
-
const
|
25
|
+
const extractTypesFromDocument = (
|
34
26
|
documentString: string,
|
35
27
|
schema: GraphQLSchema,
|
36
28
|
): Set<string> => {
|
37
29
|
const types = new Set<string>()
|
38
30
|
const visitedTypes = new Set<string>() // Prevent infinite recursion
|
39
31
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
// If parsing fails, return empty set
|
45
|
-
return types
|
46
|
-
}
|
32
|
+
// Use Effect to parse, but handle it synchronously since this function is synchronous
|
33
|
+
const ast = Effect.runSync(
|
34
|
+
Grafaid.Parse.parseDocument(documentString, { source: 'example' }),
|
35
|
+
)
|
47
36
|
|
48
37
|
// Helper to add a type and its related types
|
49
38
|
const addType = (typeName: string) => {
|
@@ -164,6 +153,43 @@ const extractTypesFromQuery = (
|
|
164
153
|
// Index Creation
|
165
154
|
// ============================================================================
|
166
155
|
|
156
|
+
/**
|
157
|
+
* Process a document version and add its type usage to the index.
|
158
|
+
*
|
159
|
+
* @param example - The example being processed
|
160
|
+
* @param documentContent - The document content to extract types from
|
161
|
+
* @param schema - The schema containing version and definition
|
162
|
+
* @param hashMap - The current type usage index
|
163
|
+
* @returns Updated type usage index
|
164
|
+
*/
|
165
|
+
const processDocumentVersion = (
|
166
|
+
example: Example,
|
167
|
+
documentContent: string,
|
168
|
+
schema: Schema.Schema,
|
169
|
+
hashMap: TypeUsageIndex,
|
170
|
+
): TypeUsageIndex => {
|
171
|
+
const types = extractTypesFromDocument(documentContent, schema.definition)
|
172
|
+
|
173
|
+
// Get version from schema (null for unversioned)
|
174
|
+
const version = Schema.getVersion(schema) ?? null
|
175
|
+
|
176
|
+
// Map to storage key: use version or UNVERSIONED_KEY
|
177
|
+
const versionKey: VersionKey = version ?? UNVERSIONED_KEY
|
178
|
+
|
179
|
+
// Create reference with nullable version
|
180
|
+
const exampleRef = ExampleReference.make({
|
181
|
+
name: example.name,
|
182
|
+
version,
|
183
|
+
})
|
184
|
+
|
185
|
+
let updatedMap = hashMap
|
186
|
+
for (const typeName of types) {
|
187
|
+
updatedMap = addExampleToIndex(updatedMap, versionKey, typeName, exampleRef)
|
188
|
+
}
|
189
|
+
|
190
|
+
return updatedMap
|
191
|
+
}
|
192
|
+
|
167
193
|
/**
|
168
194
|
* Create a type usage index from examples and schemas.
|
169
195
|
*
|
@@ -174,52 +200,42 @@ export const createTypeUsageIndex = (
|
|
174
200
|
examples: readonly Example[],
|
175
201
|
schemasCatalog: Catalog.Catalog,
|
176
202
|
): TypeUsageIndex => {
|
177
|
-
let
|
203
|
+
let hashMap = HashMap.empty<VersionKey, HashMap.HashMap<string, HashSet.HashSet<ExampleReference>>>()
|
178
204
|
|
179
205
|
for (const example of examples) {
|
180
|
-
// Process based on document type
|
181
206
|
if (Document.Unversioned.is(example.document)) {
|
182
|
-
//
|
207
|
+
// For unversioned: get latest schema from catalog
|
183
208
|
const schema = Catalog.getLatest(schemasCatalog)
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
() => Version.fromString('1.0.0'),
|
191
|
-
)
|
192
|
-
index = addExampleToIndex(index, UNVERSIONED_KEY, typeName, example, latestVersion)
|
193
|
-
}
|
209
|
+
hashMap = processDocumentVersion(
|
210
|
+
example,
|
211
|
+
example.document.document,
|
212
|
+
schema,
|
213
|
+
hashMap,
|
214
|
+
)
|
194
215
|
} else if (Document.Versioned.is(example.document)) {
|
195
|
-
//
|
216
|
+
// For versioned: process each version
|
196
217
|
const allVersions = Document.Versioned.getAllVersions(example.document)
|
197
218
|
|
198
219
|
for (const version of allVersions) {
|
199
|
-
// Use centralized resolution to get schema for version
|
200
220
|
const schemaOption = Option.liftThrowable(
|
201
221
|
() => Catalog.resolveCatalogSchema(schemasCatalog, version),
|
202
222
|
)()
|
203
|
-
if (Option.isNone(schemaOption))
|
204
|
-
// Skip if version not found in catalog
|
205
|
-
continue
|
206
|
-
}
|
207
|
-
const schema = schemaOption.value
|
208
|
-
|
209
|
-
const documentStringOption = Document.Versioned.getContentForVersion(example.document, version)
|
210
|
-
if (Option.isNone(documentStringOption)) continue
|
211
|
-
const documentString = documentStringOption.value
|
223
|
+
if (Option.isNone(schemaOption)) continue
|
212
224
|
|
213
|
-
const
|
225
|
+
const documentOption = Document.Versioned.getContentForVersion(example.document, version)
|
226
|
+
if (Option.isNone(documentOption)) continue
|
214
227
|
|
215
|
-
|
216
|
-
|
217
|
-
|
228
|
+
hashMap = processDocumentVersion(
|
229
|
+
example,
|
230
|
+
documentOption.value,
|
231
|
+
schemaOption.value,
|
232
|
+
hashMap,
|
233
|
+
)
|
218
234
|
}
|
219
235
|
}
|
220
236
|
}
|
221
237
|
|
222
|
-
return
|
238
|
+
return hashMap
|
223
239
|
}
|
224
240
|
|
225
241
|
/**
|
@@ -229,12 +245,8 @@ const addExampleToIndex = (
|
|
229
245
|
index: TypeUsageIndex,
|
230
246
|
versionKey: VersionKey,
|
231
247
|
typeName: string,
|
232
|
-
|
233
|
-
version: Version.Version,
|
248
|
+
exampleRef: ExampleReference,
|
234
249
|
): TypeUsageIndex => {
|
235
|
-
// Create lightweight reference using the schema's make constructor
|
236
|
-
const exampleRef = ExampleReference.make({ name: example.name, version })
|
237
|
-
|
238
250
|
// Get or create the version's type map
|
239
251
|
const versionMap = HashMap.get(index, versionKey).pipe(
|
240
252
|
Option.getOrElse(HashMap.empty<string, HashSet.HashSet<S.Schema.Type<typeof ExampleReference>>>),
|
package/src/api/schema/$.test.ts
CHANGED
@@ -112,7 +112,7 @@ const createTestConfig = (overrides?: Partial<Config.Config>): Config.Config =>
|
|
112
112
|
// Helper to build GraphQL schema using Grafaid to avoid realm issues
|
113
113
|
const buildSchemaWithGrafaid = (sdl: string) =>
|
114
114
|
Effect.gen(function*() {
|
115
|
-
const ast = yield* Grafaid.
|
115
|
+
const ast = yield* Grafaid.Parse.parseSchema(sdl, { source: 'test' })
|
116
116
|
return yield* Grafaid.Schema.fromAST(ast)
|
117
117
|
})
|
118
118
|
|
@@ -186,11 +186,11 @@ const read = (
|
|
186
186
|
Effect.gen(function*() {
|
187
187
|
const fs = yield* FileSystem
|
188
188
|
const content = yield* fs.readFileString(revisionInput.filePath)
|
189
|
-
const ast = yield* Grafaid.
|
189
|
+
const ast = yield* Grafaid.Parse.parseSchema(content, { source: revisionInput.filePath }).pipe(
|
190
190
|
Effect.mapError((error) =>
|
191
191
|
new InputSourceError({
|
192
192
|
source: 'directory',
|
193
|
-
message:
|
193
|
+
message: error.message,
|
194
194
|
cause: error,
|
195
195
|
})
|
196
196
|
),
|
@@ -199,7 +199,7 @@ const read = (
|
|
199
199
|
Effect.mapError((error) =>
|
200
200
|
new InputSourceError({
|
201
201
|
source: 'directory',
|
202
|
-
message:
|
202
|
+
message: error.message,
|
203
203
|
cause: error,
|
204
204
|
})
|
205
205
|
),
|
@@ -73,11 +73,11 @@ export const loader = InputSource.createEffect({
|
|
73
73
|
const fs = yield* FileSystem
|
74
74
|
const content = yield* fs.readFileString(config.path)
|
75
75
|
|
76
|
-
const ast = yield* Grafaid.
|
76
|
+
const ast = yield* Grafaid.Parse.parseSchema(content, { source: config.path }).pipe(
|
77
77
|
Effect.mapError((error) =>
|
78
78
|
new InputSource.InputSourceError({
|
79
79
|
source: 'file',
|
80
|
-
message:
|
80
|
+
message: error.message,
|
81
81
|
cause: error,
|
82
82
|
})
|
83
83
|
),
|
@@ -86,7 +86,7 @@ export const loader = InputSource.createEffect({
|
|
86
86
|
Effect.mapError((error) =>
|
87
87
|
new InputSource.InputSourceError({
|
88
88
|
source: 'file',
|
89
|
-
message:
|
89
|
+
message: error.message,
|
90
90
|
cause: error,
|
91
91
|
})
|
92
92
|
),
|