polen 0.11.0-next.24 → 0.11.0-next.25
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/input.d.ts +76 -77
- package/build/api/config/input.d.ts.map +1 -1
- package/build/api/config/normalized.d.ts +136 -143
- package/build/api/config/normalized.d.ts.map +1 -1
- package/build/api/config-template/template.d.ts +110 -121
- package/build/api/config-template/template.d.ts.map +1 -1
- package/build/api/examples/diagnostic/diagnostic.d.ts +0 -23
- package/build/api/examples/diagnostic/diagnostic.d.ts.map +1 -1
- package/build/api/examples/diagnostic/diagnostic.js +1 -3
- package/build/api/examples/diagnostic/diagnostic.js.map +1 -1
- package/build/api/examples/scanner.d.ts +27 -1
- package/build/api/examples/scanner.d.ts.map +1 -1
- package/build/api/examples/scanner.js +19 -17
- package/build/api/examples/scanner.js.map +1 -1
- package/build/api/examples/schemas/catalog.d.ts +20 -12
- package/build/api/examples/schemas/catalog.d.ts.map +1 -1
- package/build/api/examples/schemas/example/example.d.ts +17 -11
- package/build/api/examples/schemas/example/example.d.ts.map +1 -1
- package/build/api/schema/augmentations/$$.d.ts +7 -0
- package/build/api/schema/augmentations/$$.d.ts.map +1 -0
- package/build/api/schema/augmentations/$$.js +7 -0
- package/build/api/schema/augmentations/$$.js.map +1 -0
- package/build/api/schema/augmentations/$.d.ts +1 -1
- package/build/api/schema/augmentations/$.d.ts.map +1 -1
- package/build/api/schema/augmentations/$.js +1 -1
- package/build/api/schema/augmentations/$.js.map +1 -1
- package/build/api/schema/augmentations/apply.d.ts +29 -0
- package/build/api/schema/augmentations/apply.d.ts.map +1 -0
- package/build/api/schema/augmentations/apply.js +181 -0
- package/build/api/schema/augmentations/apply.js.map +1 -0
- package/build/api/schema/augmentations/augmentation.d.ts +31 -0
- package/build/api/schema/augmentations/augmentation.d.ts.map +1 -0
- package/build/api/schema/augmentations/augmentation.js +22 -0
- package/build/api/schema/augmentations/augmentation.js.map +1 -0
- package/build/api/schema/augmentations/config.d.ts +24 -0
- package/build/api/schema/augmentations/config.d.ts.map +1 -0
- package/build/api/schema/augmentations/config.js +9 -0
- package/build/api/schema/augmentations/config.js.map +1 -0
- package/build/api/schema/augmentations/diagnostics/diagnostic.d.ts +67 -0
- package/build/api/schema/augmentations/diagnostics/diagnostic.d.ts.map +1 -0
- package/build/api/schema/augmentations/diagnostics/diagnostic.js +13 -0
- package/build/api/schema/augmentations/diagnostics/diagnostic.js.map +1 -0
- package/build/api/schema/augmentations/diagnostics/duplicate-version.d.ts +45 -0
- package/build/api/schema/augmentations/diagnostics/duplicate-version.d.ts.map +1 -0
- package/build/api/schema/augmentations/diagnostics/duplicate-version.js +17 -0
- package/build/api/schema/augmentations/diagnostics/duplicate-version.js.map +1 -0
- package/build/api/schema/augmentations/diagnostics/invalid-path.d.ts +46 -0
- package/build/api/schema/augmentations/diagnostics/invalid-path.d.ts.map +1 -0
- package/build/api/schema/augmentations/diagnostics/invalid-path.js +18 -0
- package/build/api/schema/augmentations/diagnostics/invalid-path.js.map +1 -0
- package/build/api/schema/augmentations/diagnostics/version-mismatch.d.ts +46 -0
- package/build/api/schema/augmentations/diagnostics/version-mismatch.d.ts.map +1 -0
- package/build/api/schema/augmentations/diagnostics/version-mismatch.js +18 -0
- package/build/api/schema/augmentations/diagnostics/version-mismatch.js.map +1 -0
- package/build/api/schema/augmentations/input.d.ts +145 -0
- package/build/api/schema/augmentations/input.d.ts.map +1 -0
- package/build/api/schema/augmentations/input.js +191 -0
- package/build/api/schema/augmentations/input.js.map +1 -0
- package/build/api/schema/augmentations/placement.d.ts +8 -0
- package/build/api/schema/augmentations/placement.d.ts.map +1 -0
- package/build/api/schema/augmentations/placement.js +7 -0
- package/build/api/schema/augmentations/placement.js.map +1 -0
- package/build/api/schema/config-schema.d.ts +66 -66
- package/build/api/schema/config-schema.d.ts.map +1 -1
- package/build/api/schema/config-schema.js +2 -2
- package/build/api/schema/config-schema.js.map +1 -1
- package/build/api/schema/input-source/load.d.ts +2 -0
- package/build/api/schema/input-source/load.d.ts.map +1 -1
- package/build/api/schema/input-source/load.js.map +1 -1
- package/build/api/schema/input-sources/directory.d.ts +39 -39
- package/build/api/schema/input-sources/file.d.ts +39 -39
- package/build/api/schema/input-sources/introspection-file.d.ts +39 -39
- package/build/api/schema/input-sources/introspection.d.ts +39 -39
- package/build/api/schema/input-sources/memory.d.ts +39 -39
- package/build/api/schema/input-sources/versioned-directory.d.ts +79 -79
- package/build/api/schema/load.d.ts.map +1 -1
- package/build/api/schema/load.js +9 -2
- package/build/api/schema/load.js.map +1 -1
- package/build/lib/catalog/catalog.d.ts +1181 -1181
- package/build/lib/catalog/unversioned.d.ts +312 -312
- package/build/lib/catalog/versioned.d.ts +634 -634
- package/build/lib/change/change.d.ts +238 -238
- package/build/lib/document/document.d.ts +14 -8
- package/build/lib/document/document.d.ts.map +1 -1
- package/build/lib/document/versioned.d.ts +17 -10
- package/build/lib/document/versioned.d.ts.map +1 -1
- package/build/lib/grafaid/schema/KindMap/_.d.ts +1 -1
- package/build/lib/graphql-path/$$.d.ts +7 -13
- package/build/lib/graphql-path/$$.d.ts.map +1 -1
- package/build/lib/graphql-path/$$.js +7 -13
- package/build/lib/graphql-path/$$.js.map +1 -1
- package/build/lib/graphql-path/definition.d.ts +104 -94
- package/build/lib/graphql-path/definition.d.ts.map +1 -1
- package/build/lib/graphql-path/definition.js +126 -125
- package/build/lib/graphql-path/definition.js.map +1 -1
- package/build/lib/graphql-path/query.d.ts +25 -57
- package/build/lib/graphql-path/query.d.ts.map +1 -1
- package/build/lib/graphql-path/query.js +15 -93
- package/build/lib/graphql-path/query.js.map +1 -1
- package/build/lib/graphql-path/schema.d.ts +49 -0
- package/build/lib/graphql-path/schema.d.ts.map +1 -0
- package/build/lib/graphql-path/schema.js +89 -0
- package/build/lib/graphql-path/schema.js.map +1 -0
- package/build/lib/graphql-path/types.d.ts +76 -28
- package/build/lib/graphql-path/types.d.ts.map +1 -1
- package/build/lib/graphql-path/types.js +101 -2
- package/build/lib/graphql-path/types.js.map +1 -1
- package/build/lib/revision/revision.d.ts +1170 -1170
- package/build/lib/schema/schema.d.ts +708 -708
- package/build/lib/schema/unversioned.d.ts +1092 -1092
- package/build/lib/schema/versioned.d.ts +634 -634
- package/build/lib/semver/official-release.d.ts +10 -10
- package/build/lib/semver/pre-release.d.ts +10 -10
- package/build/lib/semver/semver.d.ts +50 -50
- package/build/lib/version-coverage/version-coverage.d.ts +43 -11
- package/build/lib/version-coverage/version-coverage.d.ts.map +1 -1
- package/build/lib/version-coverage/version-coverage.js +40 -6
- package/build/lib/version-coverage/version-coverage.js.map +1 -1
- package/build/template/hooks/use-examples.d.ts +1 -1
- package/build/template/routes/changelog/ChangelogSidebar.d.ts +2 -2
- package/build/template/routes/changelog/ChangelogSidebar.d.ts.map +1 -1
- package/build/template/routes/changelog/ChangelogSidebar.js +4 -4
- package/build/template/routes/changelog/ChangelogSidebar.js.map +1 -1
- package/build/template/routes/examples/_.d.ts +3 -3
- package/build/template/routes/examples/_index.d.ts +2 -2
- package/build/template/routes/examples/name.d.ts +3 -3
- package/build/template/stores/changelog.d.ts +39 -39
- package/build/vite/plugins/examples.d.ts.map +1 -1
- package/build/vite/plugins/examples.js +0 -2
- package/build/vite/plugins/examples.js.map +1 -1
- package/build/vite/plugins/schemas.d.ts.map +1 -1
- package/build/vite/plugins/schemas.js +38 -2
- package/build/vite/plugins/schemas.js.map +1 -1
- package/package.json +1 -1
- package/src/api/examples/diagnostic/diagnostic.ts +0 -3
- package/src/api/examples/scanner.test.ts +83 -0
- package/src/api/examples/scanner.ts +17 -21
- package/src/api/schema/augmentations/$$.ts +6 -0
- package/src/api/schema/augmentations/$.ts +1 -1
- package/src/api/schema/augmentations/apply.test.ts +89 -0
- package/src/api/schema/augmentations/apply.ts +277 -0
- package/src/api/schema/augmentations/augmentation.ts +24 -0
- package/src/api/schema/augmentations/config.ts +11 -0
- package/src/api/schema/augmentations/diagnostics/diagnostic.ts +20 -0
- package/src/api/schema/augmentations/diagnostics/duplicate-version.ts +20 -0
- package/src/api/schema/augmentations/diagnostics/invalid-path.ts +21 -0
- package/src/api/schema/augmentations/diagnostics/version-mismatch.ts +21 -0
- package/src/api/schema/augmentations/input.test.ts +144 -0
- package/src/api/schema/augmentations/input.ts +215 -0
- package/src/api/schema/augmentations/placement.ts +11 -0
- package/src/api/schema/config-schema.ts +2 -2
- package/src/api/schema/input-source/load.ts +2 -0
- package/src/api/schema/load.ts +19 -2
- package/src/lib/graphql-path/$$.ts +7 -13
- package/src/lib/graphql-path/$.test.ts +175 -0
- package/src/lib/graphql-path/definition.ts +162 -162
- package/src/lib/graphql-path/query.ts +15 -98
- package/src/lib/graphql-path/schema.ts +136 -0
- package/src/lib/graphql-path/types.ts +108 -28
- package/src/lib/version-coverage/version-coverage.ts +48 -6
- package/src/template/routes/changelog/ChangelogSidebar.tsx +4 -4
- package/src/vite/plugins/examples.ts +0 -2
- package/src/vite/plugins/schemas.ts +51 -2
- package/build/api/examples/diagnostic/unused-default.d.ts +0 -49
- package/build/api/examples/diagnostic/unused-default.d.ts.map +0 -1
- package/build/api/examples/diagnostic/unused-default.js +0 -19
- package/build/api/examples/diagnostic/unused-default.js.map +0 -1
- package/build/api/schema/augmentations/augmentations/description.d.ts +0 -26
- package/build/api/schema/augmentations/augmentations/description.d.ts.map +0 -1
- package/build/api/schema/augmentations/augmentations/description.js +0 -55
- package/build/api/schema/augmentations/augmentations/description.js.map +0 -1
- package/build/api/schema/augmentations/schema-augmentation.d.ts +0 -20
- package/build/api/schema/augmentations/schema-augmentation.d.ts.map +0 -1
- package/build/api/schema/augmentations/schema-augmentation.js +0 -22
- package/build/api/schema/augmentations/schema-augmentation.js.map +0 -1
- package/build/api/schema/augmentations/target.d.ts +0 -25
- package/build/api/schema/augmentations/target.d.ts.map +0 -1
- package/build/api/schema/augmentations/target.js +0 -39
- package/build/api/schema/augmentations/target.js.map +0 -1
- package/build/lib/graphql-path/constructors.d.ts +0 -57
- package/build/lib/graphql-path/constructors.d.ts.map +0 -1
- package/build/lib/graphql-path/constructors.js +0 -73
- package/build/lib/graphql-path/constructors.js.map +0 -1
- package/src/api/examples/diagnostic/unused-default.ts +0 -22
- package/src/api/schema/augmentations/augmentations/description.ts +0 -69
- package/src/api/schema/augmentations/schema-augmentation.ts +0 -32
- package/src/api/schema/augmentations/target.ts +0 -61
- package/src/lib/graphql-path/constructors.ts +0 -81
@@ -0,0 +1,215 @@
|
|
1
|
+
import type { Augmentation } from '#api/schema/augmentations/augmentation'
|
2
|
+
import type { AugmentationConfig } from '#api/schema/augmentations/config'
|
3
|
+
import { Placement } from '#api/schema/augmentations/placement'
|
4
|
+
import { GraphQLPath } from '#lib/graphql-path'
|
5
|
+
import { S } from '#lib/kit-temp/effect'
|
6
|
+
import { VersionCoverage } from '#lib/version-coverage'
|
7
|
+
import { Version } from '#lib/version/$'
|
8
|
+
import { HashMap } from 'effect'
|
9
|
+
|
10
|
+
/**
|
11
|
+
* Configuration for augmenting GraphQL schema descriptions.
|
12
|
+
*
|
13
|
+
* This schema supports two usage patterns:
|
14
|
+
*
|
15
|
+
* 1. **Unversioned augmentations** - Apply to all schema versions
|
16
|
+
* 2. **Version-specific augmentations** - Apply to specific schema versions with optional defaults
|
17
|
+
*
|
18
|
+
* @example
|
19
|
+
* ```ts
|
20
|
+
* // Unversioned - applies to all versions
|
21
|
+
* {
|
22
|
+
* on: 'Pokemon',
|
23
|
+
* placement: 'after',
|
24
|
+
* content: '**Note:** This type includes battle stats.'
|
25
|
+
* }
|
26
|
+
*
|
27
|
+
* // Version-specific with defaults
|
28
|
+
* {
|
29
|
+
* on: 'Pokemon', // Default for all versions
|
30
|
+
* placement: 'after', // Default for all versions
|
31
|
+
* content: 'Base Pokemon info.', // Default content
|
32
|
+
* versions: {
|
33
|
+
* '2': {
|
34
|
+
* content: 'Enhanced Pokemon with battle capabilities.' // Override for v2
|
35
|
+
* },
|
36
|
+
* '3': {
|
37
|
+
* on: 'BattlePokemon', // Different type in v3
|
38
|
+
* content: 'Battle-ready Pokemon with full stats.'
|
39
|
+
* }
|
40
|
+
* }
|
41
|
+
* }
|
42
|
+
* ```
|
43
|
+
*
|
44
|
+
* @remarks
|
45
|
+
* When using version-specific augmentations:
|
46
|
+
* - Top-level fields serve as defaults for all versions
|
47
|
+
* - Version-specific fields override defaults
|
48
|
+
* - A version entry must have complete configuration (after merging with defaults) to be valid
|
49
|
+
* - Invalid paths or missing types will generate build diagnostics rather than crashing
|
50
|
+
*/
|
51
|
+
export const AugmentationInput = S.Struct({
|
52
|
+
/**
|
53
|
+
* GraphQL path to the type or field to augment.
|
54
|
+
*
|
55
|
+
* @example
|
56
|
+
* - Type path: `'Pokemon'`, `'Query'`, `'User'`
|
57
|
+
* - Field path: `'Pokemon.name'`, `'Query.users'`, `'Mutation.createUser'`
|
58
|
+
*
|
59
|
+
* @remarks
|
60
|
+
* If the specified path doesn't exist in the schema, a diagnostic error will be generated
|
61
|
+
* during the build process rather than causing a crash.
|
62
|
+
*/
|
63
|
+
on: S.optional(S.String),
|
64
|
+
|
65
|
+
/**
|
66
|
+
* How to apply the augmentation content relative to existing description.
|
67
|
+
*
|
68
|
+
* - `'over'` - Replace the existing description entirely
|
69
|
+
* - `'before'` - Prepend content to the existing description
|
70
|
+
* - `'after'` - Append content to the existing description
|
71
|
+
*
|
72
|
+
* @default 'after'
|
73
|
+
*/
|
74
|
+
placement: S.optional(Placement),
|
75
|
+
|
76
|
+
/**
|
77
|
+
* The content to add to the description.
|
78
|
+
*
|
79
|
+
* Supports full Markdown syntax including:
|
80
|
+
* - Bold/italic text
|
81
|
+
* - Code blocks and inline code
|
82
|
+
* - Links
|
83
|
+
* - Lists
|
84
|
+
* - Tables
|
85
|
+
*
|
86
|
+
* @example
|
87
|
+
* ```ts
|
88
|
+
* content: `
|
89
|
+
* **Important:** This field requires authentication.
|
90
|
+
*
|
91
|
+
* Example query:
|
92
|
+
* \`\`\`graphql
|
93
|
+
* query {
|
94
|
+
* users(limit: 10) {
|
95
|
+
* id
|
96
|
+
* name
|
97
|
+
* }
|
98
|
+
* }
|
99
|
+
* \`\`\`
|
100
|
+
* `
|
101
|
+
* ```
|
102
|
+
*/
|
103
|
+
content: S.optional(S.String),
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Version-specific augmentation overrides.
|
107
|
+
*
|
108
|
+
* Keys are version identifiers (e.g., `'1'`, `'2'`, `'3'`).
|
109
|
+
* Values are partial augmentation configs that override top-level defaults.
|
110
|
+
*
|
111
|
+
* @example
|
112
|
+
* ```ts
|
113
|
+
* versions: {
|
114
|
+
* '1': { content: 'Legacy API - see migration guide.' },
|
115
|
+
* '2': { content: 'Current stable API.' },
|
116
|
+
* '3': {
|
117
|
+
* on: 'NewTypeName', // Type renamed in v3
|
118
|
+
* content: 'Beta API - subject to change.'
|
119
|
+
* }
|
120
|
+
* }
|
121
|
+
* ```
|
122
|
+
*
|
123
|
+
* @remarks
|
124
|
+
* - Version keys must be valid numeric strings
|
125
|
+
* - Each version inherits top-level defaults
|
126
|
+
* - Invalid version identifiers will generate build diagnostics
|
127
|
+
* - Duplicate version keys will generate build diagnostics
|
128
|
+
*/
|
129
|
+
versions: S.optional(
|
130
|
+
S.Record({
|
131
|
+
key: S.String,
|
132
|
+
value: S.Struct({
|
133
|
+
on: S.optional(S.String),
|
134
|
+
placement: S.optional(Placement),
|
135
|
+
content: S.optional(S.String),
|
136
|
+
}),
|
137
|
+
}),
|
138
|
+
),
|
139
|
+
}).annotations({
|
140
|
+
identifier: 'AugmentationInput',
|
141
|
+
description: 'Configuration for augmenting GraphQL schema descriptions with version support',
|
142
|
+
})
|
143
|
+
|
144
|
+
export type AugmentationInput = S.Schema.Type<typeof AugmentationInput>
|
145
|
+
|
146
|
+
/**
|
147
|
+
* Transform user-facing input to normalized internal representation.
|
148
|
+
*
|
149
|
+
* Rules:
|
150
|
+
* 1. If no versions field → create single unversioned entry
|
151
|
+
* 2. If versions field exists:
|
152
|
+
* - Create version-specific entries for each version
|
153
|
+
* - If top-level defaults exist, they are used as fallbacks for version entries
|
154
|
+
* - If a version entry would be incomplete without defaults, skip it
|
155
|
+
*/
|
156
|
+
export const normalizeAugmentationInput = (input: AugmentationInput): Augmentation | null => {
|
157
|
+
const map = HashMap.empty<VersionCoverage.VersionCoverage, AugmentationConfig>()
|
158
|
+
|
159
|
+
// Case 1: No versions field - create unversioned entry
|
160
|
+
if (!input.versions || Object.keys(input.versions).length === 0) {
|
161
|
+
// Must have complete top-level configuration
|
162
|
+
if (!input.on || !input.placement || !input.content) {
|
163
|
+
return null // Invalid: incomplete unversioned augmentation
|
164
|
+
}
|
165
|
+
|
166
|
+
const unversionedConfig: AugmentationConfig = {
|
167
|
+
on: GraphQLPath.Definition.decodeSync(input.on),
|
168
|
+
placement: input.placement,
|
169
|
+
content: input.content,
|
170
|
+
}
|
171
|
+
|
172
|
+
return {
|
173
|
+
versionAugmentations: HashMap.set(
|
174
|
+
map,
|
175
|
+
VersionCoverage.unversioned(),
|
176
|
+
unversionedConfig,
|
177
|
+
),
|
178
|
+
}
|
179
|
+
}
|
180
|
+
|
181
|
+
// Case 2: Has versions field - create version-specific entries
|
182
|
+
let resultMap = map
|
183
|
+
|
184
|
+
// Process each version
|
185
|
+
for (const [versionStr, versionOverrides] of Object.entries(input.versions)) {
|
186
|
+
// Merge with top-level defaults
|
187
|
+
const onString = versionOverrides.on ?? input.on
|
188
|
+
const placement = versionOverrides.placement ?? input.placement
|
189
|
+
const content = versionOverrides.content ?? input.content
|
190
|
+
|
191
|
+
// Skip if incomplete after merging with defaults
|
192
|
+
if (!onString || !placement || !content) {
|
193
|
+
continue
|
194
|
+
}
|
195
|
+
|
196
|
+
const config: AugmentationConfig = {
|
197
|
+
on: GraphQLPath.Definition.decodeSync(onString),
|
198
|
+
placement,
|
199
|
+
content,
|
200
|
+
}
|
201
|
+
const version = Version.decodeSync(versionStr)
|
202
|
+
const coverage = VersionCoverage.single(version)
|
203
|
+
|
204
|
+
resultMap = HashMap.set(resultMap, coverage, config)
|
205
|
+
}
|
206
|
+
|
207
|
+
// If no valid version configurations were created, return null
|
208
|
+
if (HashMap.size(resultMap) === 0) {
|
209
|
+
return null
|
210
|
+
}
|
211
|
+
|
212
|
+
return {
|
213
|
+
versionAugmentations: resultMap,
|
214
|
+
}
|
215
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { Augmentations } from '#api/schema/augmentations/$'
|
2
2
|
import { S } from '#lib/kit-temp/effect'
|
3
3
|
|
4
4
|
// ============================================================================
|
@@ -364,7 +364,7 @@ export const ConfigSchema = S.Struct({
|
|
364
364
|
* ]
|
365
365
|
* ```
|
366
366
|
*/
|
367
|
-
augmentations: S.optional(S.Array(
|
367
|
+
augmentations: S.optional(S.Array(Augmentations.AugmentationInput)),
|
368
368
|
/**
|
369
369
|
* Which data sources to use for loading schemas.
|
370
370
|
*
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { Config as PolenConfig } from '#api/config/$'
|
2
|
+
import type { Diagnostic } from '#api/schema/augmentations/diagnostics/diagnostic'
|
2
3
|
import type { Config } from '#api/schema/config'
|
3
4
|
import type { InputSource } from '#api/schema/input-source/input-source'
|
4
5
|
import type { Catalog } from '#lib/catalog/$'
|
@@ -9,6 +10,7 @@ import type { Catalog } from '#lib/catalog/$'
|
|
9
10
|
export interface LoadedCatalog {
|
10
11
|
data: Catalog.Catalog | null
|
11
12
|
source: InputSource
|
13
|
+
diagnostics?: Diagnostic[]
|
12
14
|
// {
|
13
15
|
// type: DataSourceType
|
14
16
|
// /**
|
package/src/api/schema/load.ts
CHANGED
@@ -141,16 +141,33 @@ export const loadOrNull = (
|
|
141
141
|
if (loadedSchema.data && config.schema?.augmentations) {
|
142
142
|
const augmentations = config.schema.augmentations
|
143
143
|
const catalog = loadedSchema.data as Catalog.Catalog
|
144
|
+
const allDiagnostics: Augmentations.Diagnostic[] = []
|
145
|
+
|
144
146
|
Catalog.fold(
|
145
147
|
(versioned) => {
|
146
148
|
for (const schema of Catalog.Versioned.getAll(versioned)) {
|
147
|
-
Augmentations.
|
149
|
+
const { diagnostics } = Augmentations.applyAll(
|
150
|
+
schema.definition,
|
151
|
+
augmentations,
|
152
|
+
schema.version,
|
153
|
+
)
|
154
|
+
allDiagnostics.push(...diagnostics)
|
148
155
|
}
|
149
156
|
},
|
150
157
|
(unversioned) => {
|
151
|
-
Augmentations.
|
158
|
+
const { diagnostics } = Augmentations.applyAll(
|
159
|
+
unversioned.schema.definition,
|
160
|
+
augmentations,
|
161
|
+
null,
|
162
|
+
)
|
163
|
+
allDiagnostics.push(...diagnostics)
|
152
164
|
},
|
153
165
|
)(catalog)
|
166
|
+
|
167
|
+
// Add diagnostics to loaded schema if any were generated
|
168
|
+
if (allDiagnostics.length > 0) {
|
169
|
+
loadedSchema.diagnostics = allDiagnostics
|
170
|
+
}
|
154
171
|
}
|
155
172
|
|
156
173
|
return loadedSchema
|
@@ -22,21 +22,15 @@
|
|
22
22
|
* const encoded = GraphQLPath.Definition.encode(userNameFieldPath) // "User.name"
|
23
23
|
* const decoded = GraphQLPath.Definition.decode("User.name") // field definition path
|
24
24
|
*
|
25
|
-
* //
|
26
|
-
* const queryPath = GraphQLPath.Query.
|
27
|
-
*
|
28
|
-
*
|
29
|
-
*
|
30
|
-
*
|
31
|
-
* .type('User')
|
32
|
-
* .field('name')
|
33
|
-
* .build()
|
34
|
-
*
|
35
|
-
* // Encode/decode query paths
|
36
|
-
* const encodedQuery = GraphQLPath.Query.encode(queryPath) // "User.posts.Post.author.User.name"
|
37
|
-
* const decodedQuery = GraphQLPath.Query.decode("User.posts.Post.author") // query path
|
25
|
+
* // Decode a query path from a string
|
26
|
+
* const queryPath = GraphQLPath.Query.decode("User.posts.Post.author.User.name")
|
27
|
+
* // Returns array of segments: [TypeSegment, FieldSegment, TypeSegment, FieldSegment, ...]
|
28
|
+
*
|
29
|
+
* // Encode query path segments to a string
|
30
|
+
* const encoded = GraphQLPath.Query.encode(queryPath) // "User.posts.Post.author.User.name"
|
38
31
|
* ```
|
39
32
|
*/
|
40
33
|
|
41
34
|
export * as Definition from './definition.js'
|
42
35
|
export * as Query from './query.js'
|
36
|
+
export * as Schema from './schema.js'
|
@@ -0,0 +1,175 @@
|
|
1
|
+
import { S } from '#lib/kit-temp/effect'
|
2
|
+
import { describe, expect, test } from 'vitest'
|
3
|
+
import { GraphQLPath } from './$.js'
|
4
|
+
|
5
|
+
describe('decode', () => {
|
6
|
+
test.for([
|
7
|
+
['User', [{ _tag: 'TypeSegment', type: 'User' }]],
|
8
|
+
['User.name', [
|
9
|
+
{ _tag: 'TypeSegment', type: 'User' },
|
10
|
+
{ _tag: 'FieldSegment', field: 'name' },
|
11
|
+
]],
|
12
|
+
['User.posts(limit)', [
|
13
|
+
{ _tag: 'TypeSegment', type: 'User' },
|
14
|
+
{ _tag: 'FieldSegment', field: 'posts' },
|
15
|
+
{ _tag: 'ArgumentSegment', argument: 'limit' },
|
16
|
+
]],
|
17
|
+
])('decodes "%s"', ([input, expected]) => {
|
18
|
+
expect(GraphQLPath.Definition.decodeSync(input)).toEqual(expected)
|
19
|
+
})
|
20
|
+
|
21
|
+
test.for([
|
22
|
+
'',
|
23
|
+
'Type.field.extra',
|
24
|
+
'Type(arg)',
|
25
|
+
'.field',
|
26
|
+
'Type.',
|
27
|
+
])('throws on invalid format "%s"', (input) => {
|
28
|
+
expect(() => GraphQLPath.Definition.decodeSync(input)).toThrow()
|
29
|
+
})
|
30
|
+
})
|
31
|
+
|
32
|
+
describe('encode', () => {
|
33
|
+
test.for(
|
34
|
+
[
|
35
|
+
[GraphQLPath.Definition.type('User'), 'User'],
|
36
|
+
[GraphQLPath.Definition.field('User', 'name'), 'User.name'],
|
37
|
+
[GraphQLPath.Definition.argument('User', 'posts', 'limit'), 'User.posts(limit)'],
|
38
|
+
] as const,
|
39
|
+
)('encodes path to "%s"', ([path, expected]) => {
|
40
|
+
expect(GraphQLPath.Definition.encodeSync(path as any)).toBe(expected)
|
41
|
+
})
|
42
|
+
})
|
43
|
+
|
44
|
+
describe('round-trip', () => {
|
45
|
+
test.for([
|
46
|
+
'Query',
|
47
|
+
'Mutation',
|
48
|
+
'User',
|
49
|
+
'User.id',
|
50
|
+
'User.name',
|
51
|
+
'Query.users',
|
52
|
+
'User.posts(limit)',
|
53
|
+
'Query.search(query)',
|
54
|
+
'Mutation.createUser(input)',
|
55
|
+
])('round-trips "%s"', (pathString) => {
|
56
|
+
const decoded = GraphQLPath.Definition.decodeSync(pathString)
|
57
|
+
const encoded = GraphQLPath.Definition.encodeSync(decoded)
|
58
|
+
expect(encoded).toBe(pathString)
|
59
|
+
})
|
60
|
+
})
|
61
|
+
|
62
|
+
describe('type guards', () => {
|
63
|
+
const typePath = GraphQLPath.Definition.decodeSync('User')
|
64
|
+
const fieldPath = GraphQLPath.Definition.decodeSync('User.name')
|
65
|
+
const argPath = GraphQLPath.Definition.decodeSync('User.posts(limit)')
|
66
|
+
|
67
|
+
test('isTypeDefinitionPath', () => {
|
68
|
+
expect(GraphQLPath.Definition.isTypeDefinitionPath(typePath)).toBe(true)
|
69
|
+
expect(GraphQLPath.Definition.isTypeDefinitionPath(fieldPath)).toBe(false)
|
70
|
+
expect(GraphQLPath.Definition.isTypeDefinitionPath(argPath)).toBe(false)
|
71
|
+
})
|
72
|
+
|
73
|
+
test('isFieldDefinitionPath', () => {
|
74
|
+
expect(GraphQLPath.Definition.isFieldDefinitionPath(typePath)).toBe(false)
|
75
|
+
expect(GraphQLPath.Definition.isFieldDefinitionPath(fieldPath)).toBe(true)
|
76
|
+
expect(GraphQLPath.Definition.isFieldDefinitionPath(argPath)).toBe(false)
|
77
|
+
})
|
78
|
+
|
79
|
+
test('isArgumentDefinitionPath', () => {
|
80
|
+
expect(GraphQLPath.Definition.isArgumentDefinitionPath(typePath)).toBe(false)
|
81
|
+
expect(GraphQLPath.Definition.isArgumentDefinitionPath(fieldPath)).toBe(false)
|
82
|
+
expect(GraphQLPath.Definition.isArgumentDefinitionPath(argPath)).toBe(true)
|
83
|
+
})
|
84
|
+
|
85
|
+
test('Effect Schema derived segment type guards', async () => {
|
86
|
+
// Import from the types module directly since constructors re-exports them
|
87
|
+
const { isTypeSegment, isFieldSegment, isArgumentSegment } = await import('./types.js')
|
88
|
+
|
89
|
+
const typeSegment = { _tag: 'TypeSegment', type: 'User' } as const
|
90
|
+
const fieldSegment = { _tag: 'FieldSegment', field: 'name' } as const
|
91
|
+
const argSegment = { _tag: 'ArgumentSegment', argument: 'limit' } as const
|
92
|
+
|
93
|
+
// Test that Effect Schema derived guards work correctly
|
94
|
+
expect(isTypeSegment(typeSegment)).toBe(true)
|
95
|
+
expect(isTypeSegment(fieldSegment)).toBe(false)
|
96
|
+
expect(isFieldSegment(fieldSegment)).toBe(true)
|
97
|
+
expect(isFieldSegment(typeSegment)).toBe(false)
|
98
|
+
expect(isArgumentSegment(argSegment)).toBe(true)
|
99
|
+
expect(isArgumentSegment(typeSegment)).toBe(false)
|
100
|
+
})
|
101
|
+
})
|
102
|
+
|
103
|
+
describe('helper functions', () => {
|
104
|
+
test('getType extracts type from all path types', () => {
|
105
|
+
expect(GraphQLPath.Definition.getType(GraphQLPath.Definition.decodeSync('User'))).toBe('User')
|
106
|
+
expect(GraphQLPath.Definition.getType(GraphQLPath.Definition.decodeSync('User.name'))).toBe('User')
|
107
|
+
expect(GraphQLPath.Definition.getType(GraphQLPath.Definition.decodeSync('User.posts(limit)'))).toBe('User')
|
108
|
+
})
|
109
|
+
|
110
|
+
test('getField extracts field name', () => {
|
111
|
+
const fieldPath = GraphQLPath.Definition.decodeSync('User.name')
|
112
|
+
const argPath = GraphQLPath.Definition.decodeSync('User.posts(limit)')
|
113
|
+
|
114
|
+
if (GraphQLPath.Definition.isFieldDefinitionPath(fieldPath)) {
|
115
|
+
expect(GraphQLPath.Definition.getField(fieldPath)).toBe('name')
|
116
|
+
}
|
117
|
+
if (GraphQLPath.Definition.isArgumentDefinitionPath(argPath)) {
|
118
|
+
expect(GraphQLPath.Definition.getField(argPath)).toBe('posts')
|
119
|
+
}
|
120
|
+
})
|
121
|
+
|
122
|
+
test('getArgument extracts argument name', () => {
|
123
|
+
const argPath = GraphQLPath.Definition.decodeSync('User.posts(limit)')
|
124
|
+
if (GraphQLPath.Definition.isArgumentDefinitionPath(argPath)) {
|
125
|
+
expect(GraphQLPath.Definition.getArgument(argPath)).toBe('limit')
|
126
|
+
}
|
127
|
+
})
|
128
|
+
})
|
129
|
+
|
130
|
+
describe('constructors', () => {
|
131
|
+
test.for([
|
132
|
+
[GraphQLPath.Definition.type('User'), [{ _tag: 'TypeSegment', type: 'User' }]],
|
133
|
+
[GraphQLPath.Definition.field('User', 'name'), [
|
134
|
+
{ _tag: 'TypeSegment', type: 'User' },
|
135
|
+
{ _tag: 'FieldSegment', field: 'name' },
|
136
|
+
]],
|
137
|
+
[GraphQLPath.Definition.argument('User', 'posts', 'limit'), [
|
138
|
+
{ _tag: 'TypeSegment', type: 'User' },
|
139
|
+
{ _tag: 'FieldSegment', field: 'posts' },
|
140
|
+
{ _tag: 'ArgumentSegment', argument: 'limit' },
|
141
|
+
]],
|
142
|
+
])('constructor creates correct structure', ([result, expected]) => {
|
143
|
+
expect(result).toEqual(expected)
|
144
|
+
})
|
145
|
+
})
|
146
|
+
|
147
|
+
describe('Schema validation', () => {
|
148
|
+
test.for(
|
149
|
+
[
|
150
|
+
[GraphQLPath.Definition.TypeDefinitionPath, 'User', [{ _tag: 'TypeSegment', type: 'User' }]],
|
151
|
+
[GraphQLPath.Definition.FieldDefinitionPath, 'User.name', [
|
152
|
+
{ _tag: 'TypeSegment', type: 'User' },
|
153
|
+
{ _tag: 'FieldSegment', field: 'name' },
|
154
|
+
]],
|
155
|
+
[GraphQLPath.Definition.ArgumentDefinitionPath, 'User.posts(limit)', [
|
156
|
+
{ _tag: 'TypeSegment', type: 'User' },
|
157
|
+
{ _tag: 'FieldSegment', field: 'posts' },
|
158
|
+
{ _tag: 'ArgumentSegment', argument: 'limit' },
|
159
|
+
]],
|
160
|
+
] as const,
|
161
|
+
)('validates through Effect Schema', ([schema, input, expected]) => {
|
162
|
+
const result = S.decodeUnknownSync(schema as any)(input)
|
163
|
+
expect(result).toEqual(expected)
|
164
|
+
})
|
165
|
+
|
166
|
+
test('union automatically selects correct type', () => {
|
167
|
+
const typePath = S.decodeUnknownSync(GraphQLPath.Definition.DefinitionPath)('User')
|
168
|
+
const fieldPath = S.decodeUnknownSync(GraphQLPath.Definition.DefinitionPath)('User.name')
|
169
|
+
const argPath = S.decodeUnknownSync(GraphQLPath.Definition.DefinitionPath)('User.posts(limit)')
|
170
|
+
|
171
|
+
expect(typePath.length).toBe(1)
|
172
|
+
expect(fieldPath.length).toBe(2)
|
173
|
+
expect(argPath.length).toBe(3)
|
174
|
+
})
|
175
|
+
})
|