polen 0.11.0-next.16 → 0.11.0-next.18
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/builder/ssg/generate.d.ts.map +1 -1
- package/build/api/builder/ssg/generate.js +5 -5
- package/build/api/builder/ssg/generate.js.map +1 -1
- package/build/api/builder/ssg/page-generator.worker.js +13 -3
- package/build/api/builder/ssg/page-generator.worker.js.map +1 -1
- package/build/api/config/input.d.ts +88 -3
- package/build/api/config/input.d.ts.map +1 -1
- package/build/api/config/normalized.d.ts +92 -7
- package/build/api/config/normalized.d.ts.map +1 -1
- package/build/api/config/normalized.js +11 -3
- package/build/api/config/normalized.js.map +1 -1
- package/build/api/config-template/template.js +2 -2
- package/build/api/config-template/template.js.map +1 -1
- package/build/api/content/sidebar.d.ts.map +1 -1
- package/build/api/content/sidebar.js +2 -1
- package/build/api/content/sidebar.js.map +1 -1
- package/build/api/examples/config.d.ts +366 -3
- package/build/api/examples/config.d.ts.map +1 -1
- package/build/api/examples/config.js +25 -3
- package/build/api/examples/config.js.map +1 -1
- package/build/api/examples/diagnostic/diagnostic.d.ts +5 -5
- package/build/api/examples/diagnostic/missing-versions.d.ts +5 -4
- package/build/api/examples/diagnostic/missing-versions.d.ts.map +1 -1
- package/build/api/examples/diagnostic/missing-versions.js +3 -2
- package/build/api/examples/diagnostic/missing-versions.js.map +1 -1
- package/build/api/examples/diagnostic/unknown-version.d.ts +5 -4
- package/build/api/examples/diagnostic/unknown-version.d.ts.map +1 -1
- package/build/api/examples/diagnostic/unknown-version.js +3 -2
- package/build/api/examples/diagnostic/unknown-version.js.map +1 -1
- package/build/api/examples/diagnostic/validation-error.d.ts +3 -2
- package/build/api/examples/diagnostic/validation-error.d.ts.map +1 -1
- package/build/api/examples/diagnostic/validation-error.js +9 -3
- package/build/api/examples/diagnostic/validation-error.js.map +1 -1
- package/build/api/examples/diagnostic/validator.d.ts.map +1 -1
- package/build/api/examples/diagnostic/validator.js +115 -69
- package/build/api/examples/diagnostic/validator.js.map +1 -1
- package/build/api/examples/filter.d.ts.map +1 -1
- package/build/api/examples/filter.js +9 -6
- package/build/api/examples/filter.js.map +1 -1
- package/build/api/examples/scanner.d.ts.map +1 -1
- package/build/api/examples/scanner.js +93 -103
- package/build/api/examples/scanner.js.map +1 -1
- package/build/api/examples/type-usage-indexer.d.ts.map +1 -1
- package/build/api/examples/type-usage-indexer.js +18 -32
- package/build/api/examples/type-usage-indexer.js.map +1 -1
- package/build/api/iso/schema/routing.d.ts.map +1 -1
- package/build/api/iso/schema/routing.js +8 -8
- package/build/api/iso/schema/routing.js.map +1 -1
- package/build/api/iso/schema/validation.d.ts.map +1 -1
- package/build/api/iso/schema/validation.js +3 -2
- package/build/api/iso/schema/validation.js.map +1 -1
- package/build/api/schema/input-sources/directory.js +2 -2
- package/build/api/schema/input-sources/directory.js.map +1 -1
- package/build/api/schema/input-sources/versioned-directory.d.ts +3 -3
- package/build/api/schema/input-sources/versioned-directory.d.ts.map +1 -1
- package/build/api/schema/input-sources/versioned-directory.js +6 -4
- package/build/api/schema/input-sources/versioned-directory.js.map +1 -1
- package/build/api/schema/load.d.ts.map +1 -1
- package/build/api/schema/load.js +2 -2
- package/build/api/schema/load.js.map +1 -1
- package/build/cli/commands/hero-image.js +1 -1
- package/build/cli/commands/hero-image.js.map +1 -1
- package/build/lib/catalog/catalog.d.ts +65 -24
- package/build/lib/catalog/catalog.d.ts.map +1 -1
- package/build/lib/catalog/catalog.js +72 -16
- package/build/lib/catalog/catalog.js.map +1 -1
- package/build/lib/catalog/versioned.d.ts +46 -26
- package/build/lib/catalog/versioned.d.ts.map +1 -1
- package/build/lib/catalog/versioned.js +44 -7
- package/build/lib/catalog/versioned.js.map +1 -1
- package/build/lib/catalog-statistics/analyze-catalog.js +3 -3
- package/build/lib/catalog-statistics/analyze-catalog.js.map +1 -1
- package/build/lib/document/document.d.ts +55 -5
- package/build/lib/document/document.d.ts.map +1 -1
- package/build/lib/document/document.js +96 -2
- package/build/lib/document/document.js.map +1 -1
- package/build/lib/document/versioned.d.ts +2 -2
- package/build/lib/document/versioned.d.ts.map +1 -1
- package/build/lib/document/versioned.js +7 -7
- package/build/lib/document/versioned.js.map +1 -1
- package/build/lib/lifecycles/lifecycles.d.ts +5 -4
- package/build/lib/lifecycles/lifecycles.d.ts.map +1 -1
- package/build/lib/lifecycles/lifecycles.js +15 -13
- package/build/lib/lifecycles/lifecycles.js.map +1 -1
- package/build/lib/version-coverage/$$.d.ts +2 -0
- package/build/lib/version-coverage/$$.d.ts.map +1 -0
- package/build/lib/version-coverage/$$.js +2 -0
- package/build/lib/version-coverage/$$.js.map +1 -0
- package/build/lib/version-coverage/$.d.ts.map +1 -0
- package/build/lib/version-coverage/$.js.map +1 -0
- package/build/lib/{version-selection/version-selection.d.ts → version-coverage/version-coverage.d.ts} +1 -1
- package/build/lib/version-coverage/version-coverage.d.ts.map +1 -0
- package/build/lib/{version-selection/version-selection.js → version-coverage/version-coverage.js} +2 -2
- package/build/lib/version-coverage/version-coverage.js.map +1 -0
- package/build/template/components/Changelog/Changelog.d.ts.map +1 -1
- package/build/template/components/Changelog/Changelog.js +7 -7
- package/build/template/components/Changelog/Changelog.js.map +1 -1
- package/build/template/components/GraphQLDocument.d.ts +1 -1
- package/build/template/components/GraphQLDocument.d.ts.map +1 -1
- package/build/template/components/GraphQLDocument.js +10 -38
- package/build/template/components/GraphQLDocument.js.map +1 -1
- package/build/template/components/GraphQLInteractive/lib/parser.d.ts +28 -0
- package/build/template/components/GraphQLInteractive/lib/parser.d.ts.map +1 -1
- package/build/template/components/GraphQLInteractive/lib/parser.js +60 -27
- package/build/template/components/GraphQLInteractive/lib/parser.js.map +1 -1
- package/build/template/components/VersionCoveragePicker.d.ts +1 -1
- package/build/template/components/VersionCoveragePicker.d.ts.map +1 -1
- package/build/template/components/VersionCoveragePicker.js +4 -6
- package/build/template/components/VersionCoveragePicker.js.map +1 -1
- package/build/template/components/VersionPicker.d.ts.map +1 -1
- package/build/template/components/VersionPicker.js +5 -2
- package/build/template/components/VersionPicker.js.map +1 -1
- package/build/template/components/home/FeaturesGrid.js +1 -1
- package/build/template/components/home/FeaturesGrid.js.map +1 -1
- package/build/template/components/home/HeroSection.js +1 -1
- package/build/template/components/home/HeroSection.js.map +1 -1
- package/build/template/components/home/QuickStart.d.ts.map +1 -1
- package/build/template/components/home/QuickStart.js +8 -4
- package/build/template/components/home/QuickStart.js.map +1 -1
- package/build/template/components/home/RecentChanges.d.ts.map +1 -1
- package/build/template/components/home/RecentChanges.js +2 -1
- package/build/template/components/home/RecentChanges.js.map +1 -1
- package/build/template/hooks/use-highlighted.d.ts.map +1 -1
- package/build/template/hooks/use-highlighted.js +19 -13
- package/build/template/hooks/use-highlighted.js.map +1 -1
- package/build/template/lib/fetch-text.d.ts +18 -0
- package/build/template/lib/fetch-text.d.ts.map +1 -1
- package/build/template/lib/fetch-text.js +32 -4
- package/build/template/lib/fetch-text.js.map +1 -1
- package/build/template/routes/changelog.d.ts +1 -1
- package/build/template/routes/changelog.d.ts.map +1 -1
- package/build/template/routes/changelog.js +7 -4
- package/build/template/routes/changelog.js.map +1 -1
- package/build/template/routes/examples/_index.js +1 -1
- package/build/template/routes/examples/_index.js.map +1 -1
- package/build/template/routes/examples/name.d.ts.map +1 -1
- package/build/template/routes/examples/name.js +4 -2
- package/build/template/routes/examples/name.js.map +1 -1
- package/build/template/routes/reference.js +6 -6
- package/build/template/routes/reference.js.map +1 -1
- package/build/template/stores/toast.d.ts.map +1 -1
- package/build/template/stores/toast.js +5 -3
- package/build/template/stores/toast.js.map +1 -1
- package/build/vite/plugins/navbar.js +1 -1
- package/build/vite/plugins/navbar.js.map +1 -1
- package/build/vite/plugins/routes-manifest.js +1 -1
- package/build/vite/plugins/routes-manifest.js.map +1 -1
- package/package.json +7 -7
- package/src/api/builder/ssg/generate.ts +10 -5
- package/src/api/builder/ssg/page-generator.worker.ts +18 -3
- package/src/api/config/normalized.ts +12 -3
- package/src/api/config-template/template.ts +2 -2
- package/src/api/content/sidebar.ts +3 -3
- package/src/api/examples/config.test.ts +10 -0
- package/src/api/examples/config.ts +33 -4
- package/src/api/examples/diagnostic/missing-versions.ts +3 -2
- package/src/api/examples/diagnostic/unknown-version.ts +3 -2
- package/src/api/examples/diagnostic/validation-error.ts +9 -3
- package/src/api/examples/diagnostic/validator.test.ts +100 -55
- package/src/api/examples/diagnostic/validator.ts +148 -105
- package/src/api/examples/filter.ts +9 -6
- package/src/api/examples/scanner.ts +144 -120
- package/src/api/examples/type-usage-indexer.test.ts +44 -33
- package/src/api/examples/type-usage-indexer.ts +25 -40
- package/src/api/iso/schema/routing.ts +10 -10
- package/src/api/iso/schema/validation.ts +3 -2
- package/src/api/schema/$.test.ts +2 -2
- package/src/api/schema/input-sources/directory.ts +2 -2
- package/src/api/schema/input-sources/versioned-directory.ts +11 -8
- package/src/api/schema/load.ts +2 -2
- package/src/cli/commands/hero-image.ts +1 -1
- package/src/lib/catalog/catalog.ts +93 -16
- package/src/lib/catalog/versioned.ts +57 -7
- package/src/lib/catalog-statistics/$.test.ts +22 -12
- package/src/lib/catalog-statistics/analyze-catalog.ts +3 -3
- package/src/lib/document/document.ts +135 -2
- package/src/lib/document/versioned.ts +8 -8
- package/src/lib/lifecycles/lifecycles.ts +33 -28
- package/src/lib/version-coverage/$$.ts +1 -0
- package/src/lib/{version-selection/version-selection.ts → version-coverage/version-coverage.ts} +1 -1
- package/src/template/components/Changelog/Changelog.tsx +10 -6
- package/src/template/components/GraphQLDocument.tsx +11 -68
- package/src/template/components/GraphQLInteractive/lib/parser.ts +81 -29
- package/src/template/components/VersionCoveragePicker.tsx +4 -5
- package/src/template/components/VersionPicker.tsx +9 -2
- package/src/template/components/home/FeaturesGrid.tsx +1 -1
- package/src/template/components/home/HeroSection.tsx +1 -1
- package/src/template/components/home/QuickStart.tsx +16 -7
- package/src/template/components/home/RecentChanges.tsx +3 -1
- package/src/template/hooks/use-highlighted.ts +31 -19
- package/src/template/lib/fetch-text.ts +45 -4
- package/src/template/routes/changelog.tsx +10 -4
- package/src/template/routes/examples/_index.tsx +1 -1
- package/src/template/routes/examples/name.tsx +4 -2
- package/src/template/routes/reference.tsx +6 -6
- package/src/template/stores/toast.ts +6 -3
- package/src/vite/plugins/navbar.ts +1 -1
- package/src/vite/plugins/routes-manifest.ts +1 -1
- package/build/lib/graph/$$.d.ts +0 -2
- package/build/lib/graph/$$.d.ts.map +0 -1
- package/build/lib/graph/$$.js +0 -2
- package/build/lib/graph/$$.js.map +0 -1
- package/build/lib/graph/$.d.ts +0 -2
- package/build/lib/graph/$.d.ts.map +0 -1
- package/build/lib/graph/$.js +0 -2
- package/build/lib/graph/$.js.map +0 -1
- package/build/lib/graph/graph.d.ts +0 -127
- package/build/lib/graph/graph.d.ts.map +0 -1
- package/build/lib/graph/graph.js +0 -152
- package/build/lib/graph/graph.js.map +0 -1
- package/build/lib/mask/$$.d.ts +0 -3
- package/build/lib/mask/$$.d.ts.map +0 -1
- package/build/lib/mask/$$.js +0 -3
- package/build/lib/mask/$$.js.map +0 -1
- package/build/lib/mask/$.d.ts +0 -2
- package/build/lib/mask/$.d.ts.map +0 -1
- package/build/lib/mask/$.js +0 -2
- package/build/lib/mask/$.js.map +0 -1
- package/build/lib/mask/apply.d.ts +0 -86
- package/build/lib/mask/apply.d.ts.map +0 -1
- package/build/lib/mask/apply.js +0 -86
- package/build/lib/mask/apply.js.map +0 -1
- package/build/lib/mask/mask.d.ts +0 -124
- package/build/lib/mask/mask.d.ts.map +0 -1
- package/build/lib/mask/mask.js +0 -137
- package/build/lib/mask/mask.js.map +0 -1
- package/build/lib/mask/mask.test-d.d.ts +0 -2
- package/build/lib/mask/mask.test-d.d.ts.map +0 -1
- package/build/lib/mask/mask.test-d.js +0 -102
- package/build/lib/mask/mask.test-d.js.map +0 -1
- package/build/lib/version-selection/$$.d.ts +0 -2
- package/build/lib/version-selection/$$.d.ts.map +0 -1
- package/build/lib/version-selection/$$.js +0 -2
- package/build/lib/version-selection/$$.js.map +0 -1
- package/build/lib/version-selection/$.d.ts.map +0 -1
- package/build/lib/version-selection/$.js.map +0 -1
- package/build/lib/version-selection/version-selection.d.ts.map +0 -1
- package/build/lib/version-selection/version-selection.js.map +0 -1
- package/src/lib/graph/$$.ts +0 -1
- package/src/lib/graph/$.ts +0 -1
- package/src/lib/graph/graph.ts +0 -197
- package/src/lib/mask/$$.ts +0 -2
- package/src/lib/mask/$.test.ts +0 -226
- package/src/lib/mask/$.ts +0 -1
- package/src/lib/mask/apply.ts +0 -134
- package/src/lib/mask/mask.test-d.ts +0 -156
- package/src/lib/mask/mask.ts +0 -244
- package/src/lib/version-selection/$$.ts +0 -1
- /package/build/lib/{version-selection → version-coverage}/$.d.ts +0 -0
- /package/build/lib/{version-selection → version-coverage}/$.js +0 -0
- /package/src/lib/{version-selection → version-coverage}/$.ts +0 -0
@@ -1,18 +1,17 @@
|
|
1
1
|
import { Catalog as SchemaCatalog } from '#lib/catalog/$'
|
2
2
|
import { Document } from '#lib/document/$'
|
3
3
|
import { EffectGlob } from '#lib/effect-glob/$'
|
4
|
-
import { VersionCoverage } from '#lib/version-
|
4
|
+
import { VersionCoverage } from '#lib/version-coverage'
|
5
5
|
import { Version } from '#lib/version/$'
|
6
6
|
import { FileSystem } from '@effect/platform'
|
7
7
|
import { Str } from '@wollybeard/kit'
|
8
|
-
import { Effect, HashMap, HashSet, Match } from 'effect'
|
8
|
+
import { Array, Effect, HashMap, HashSet, Match } from 'effect'
|
9
9
|
import * as Path from 'node:path'
|
10
10
|
import type { Diagnostic } from './diagnostic/diagnostic.js'
|
11
11
|
import {
|
12
12
|
makeDiagnosticDuplicateContent,
|
13
13
|
makeDiagnosticMissingVersions,
|
14
14
|
makeDiagnosticUnknownVersion,
|
15
|
-
makeDiagnosticUnusedDefault,
|
16
15
|
} from './diagnostic/diagnostic.js'
|
17
16
|
import { validateExamples } from './diagnostic/validator.js'
|
18
17
|
import { Catalog } from './schemas/catalog.js'
|
@@ -44,11 +43,26 @@ const VERSIONED_FILE_PATTERN = Str.pattern<{ groups: ['name', 'version'] }>(
|
|
44
43
|
/^(?<name>.+?)\.(?<version>.+)$/,
|
45
44
|
)
|
46
45
|
|
46
|
+
// ============================================================================
|
47
|
+
// File Parsing Types
|
48
|
+
// ============================================================================
|
49
|
+
|
50
|
+
type ParsedExampleFile =
|
51
|
+
| { type: 'unversioned'; name: string; file: string }
|
52
|
+
| { type: 'versioned'; name: string; version: Version.Version; file: string }
|
53
|
+
| { type: 'default'; name: string; file: string }
|
54
|
+
|
55
|
+
type GroupedExampleFiles = Map<string, {
|
56
|
+
unversioned?: string
|
57
|
+
versioned: Map<Version.Version, string>
|
58
|
+
default?: string
|
59
|
+
}>
|
60
|
+
|
47
61
|
// ============================================================================
|
48
62
|
// Helpers
|
49
63
|
// ============================================================================
|
50
64
|
|
51
|
-
const
|
65
|
+
const parseExampleFile = (filename: string): ParsedExampleFile => {
|
52
66
|
const parsed = Path.parse(filename)
|
53
67
|
const base = parsed.name
|
54
68
|
|
@@ -60,41 +74,105 @@ const parseExampleFilename = (filename: string): { name: string; version: string
|
|
60
74
|
|
61
75
|
// Handle special 'default' keyword
|
62
76
|
if (versionStr === 'default') {
|
63
|
-
return {
|
77
|
+
return { type: 'default', name, file: filename }
|
64
78
|
}
|
65
|
-
|
66
|
-
|
67
|
-
return { name, version:
|
79
|
+
|
80
|
+
const version = Version.decodeSync(versionStr)
|
81
|
+
return { type: 'versioned', name, version, file: filename }
|
68
82
|
}
|
69
83
|
|
70
84
|
// No version found - this is an unversioned example
|
71
|
-
return { name: base,
|
85
|
+
return { type: 'unversioned', name: base, file: filename }
|
72
86
|
}
|
73
87
|
|
74
|
-
const groupExampleFiles = (files: string[]):
|
75
|
-
const grouped = new Map
|
88
|
+
const groupExampleFiles = (files: string[]): GroupedExampleFiles => {
|
89
|
+
const grouped: GroupedExampleFiles = new Map()
|
76
90
|
|
77
91
|
for (const file of files) {
|
78
|
-
const
|
92
|
+
const parsed = parseExampleFile(file)
|
79
93
|
|
80
|
-
if (!grouped.has(name)) {
|
81
|
-
grouped.set(name,
|
94
|
+
if (!grouped.has(parsed.name)) {
|
95
|
+
grouped.set(parsed.name, {
|
96
|
+
versioned: new Map(),
|
97
|
+
})
|
98
|
+
}
|
99
|
+
|
100
|
+
const group = grouped.get(parsed.name)!
|
101
|
+
|
102
|
+
switch (parsed.type) {
|
103
|
+
case 'unversioned':
|
104
|
+
group.unversioned = parsed.file
|
105
|
+
break
|
106
|
+
case 'versioned':
|
107
|
+
group.versioned.set(parsed.version, parsed.file)
|
108
|
+
break
|
109
|
+
case 'default':
|
110
|
+
group.default = parsed.file
|
111
|
+
break
|
82
112
|
}
|
83
|
-
grouped.get(name)!.set(version, file)
|
84
113
|
}
|
85
114
|
|
86
115
|
return grouped
|
87
116
|
}
|
88
117
|
|
118
|
+
/**
|
119
|
+
* Resolve .default files into proper version coverage.
|
120
|
+
* This erases the .default convention and converts it to semantic version sets.
|
121
|
+
*/
|
122
|
+
const resolveDefaultFiles = (
|
123
|
+
grouped: GroupedExampleFiles,
|
124
|
+
schemaVersions: Version.Version[],
|
125
|
+
): Map<string, {
|
126
|
+
versionDocuments: HashMap.HashMap<VersionCoverage.VersionCoverage, string>
|
127
|
+
unversioned?: string
|
128
|
+
}> => {
|
129
|
+
const resolved = new Map<string, {
|
130
|
+
versionDocuments: HashMap.HashMap<VersionCoverage.VersionCoverage, string>
|
131
|
+
unversioned?: string
|
132
|
+
}>()
|
133
|
+
|
134
|
+
for (const [name, group] of grouped) {
|
135
|
+
let versionDocuments = HashMap.empty<VersionCoverage.VersionCoverage, string>()
|
136
|
+
|
137
|
+
// Add explicit versions
|
138
|
+
for (const [version, file] of group.versioned) {
|
139
|
+
versionDocuments = HashMap.set(versionDocuments, version, file)
|
140
|
+
}
|
141
|
+
|
142
|
+
// Handle default file if present
|
143
|
+
if (group.default) {
|
144
|
+
// Determine which versions the default covers
|
145
|
+
const explicitVersions = HashSet.fromIterable(group.versioned.keys())
|
146
|
+
const defaultVersions = schemaVersions.filter(v => !HashSet.has(explicitVersions, v))
|
147
|
+
|
148
|
+
if (defaultVersions.length > 0) {
|
149
|
+
// Create version coverage for default
|
150
|
+
const defaultCoverage = defaultVersions.length === 1
|
151
|
+
? defaultVersions[0]! // Single version
|
152
|
+
: HashSet.fromIterable(defaultVersions) // Version set
|
153
|
+
|
154
|
+
versionDocuments = HashMap.set(versionDocuments, defaultCoverage, group.default)
|
155
|
+
}
|
156
|
+
}
|
157
|
+
|
158
|
+
resolved.set(name, {
|
159
|
+
versionDocuments,
|
160
|
+
...(group.unversioned ? { unversioned: group.unversioned } : {}),
|
161
|
+
})
|
162
|
+
}
|
163
|
+
|
164
|
+
return resolved
|
165
|
+
}
|
166
|
+
|
89
167
|
const lintFileLayout = (
|
90
168
|
example: Example.Example,
|
91
169
|
schemaCatalog?: SchemaCatalog.Catalog,
|
92
170
|
): Diagnostic[] => {
|
93
171
|
// Extract schema versions from catalog if provided
|
94
|
-
const schemaVersions:
|
172
|
+
const schemaVersions: Version.Version[] = schemaCatalog
|
95
173
|
? SchemaCatalog.fold(
|
96
|
-
(versioned) =>
|
97
|
-
(unversioned) =>
|
174
|
+
(versioned) => SchemaCatalog.Versioned.getVersions(versioned),
|
175
|
+
(unversioned) => [], // Unversioned doesn't have Version objects, just dates
|
98
176
|
)(schemaCatalog)
|
99
177
|
: []
|
100
178
|
|
@@ -105,20 +183,22 @@ const lintFileLayout = (
|
|
105
183
|
DocumentVersioned: (doc) => {
|
106
184
|
// Get all versions covered by this document
|
107
185
|
const coveredVersions = Document.Versioned.getAllVersions(doc)
|
108
|
-
const
|
109
|
-
|
186
|
+
const missingVersions = Array.filter(
|
187
|
+
schemaVersions,
|
188
|
+
sv => !Array.some(coveredVersions, cv => Version.equivalence(sv, cv)),
|
189
|
+
)
|
110
190
|
|
111
191
|
if (missingVersions.length > 0) {
|
112
192
|
diagnostics.push(makeDiagnosticMissingVersions({
|
113
193
|
message: `Versioned example must provide documents for all schema versions`,
|
114
194
|
example: { name: example.name, path: example.path },
|
115
|
-
providedVersions:
|
195
|
+
providedVersions: coveredVersions,
|
116
196
|
missingVersions,
|
117
197
|
}))
|
118
198
|
}
|
119
199
|
|
120
200
|
// Check for duplicate content between selections
|
121
|
-
const entries =
|
201
|
+
const entries = [...HashMap.entries(doc.versionDocuments)]
|
122
202
|
const duplicates: Array<{ version1: string; version2: string }> = []
|
123
203
|
for (let i = 0; i < entries.length; i++) {
|
124
204
|
for (let j = i + 1; j < entries.length; j++) {
|
@@ -162,32 +242,41 @@ export const scan = (
|
|
162
242
|
const pattern = `**/*.{${extensions.join(',')}}`
|
163
243
|
const files = options.files ?? (yield* EffectGlob.glob(pattern, { cwd: options.dir }))
|
164
244
|
|
245
|
+
// Get schema versions upfront for default file resolution
|
246
|
+
const schemaVersions: Version.Version[] = options.schemaCatalog
|
247
|
+
? SchemaCatalog.fold(
|
248
|
+
(versioned) => SchemaCatalog.Versioned.getVersions(versioned),
|
249
|
+
() => [], // Unversioned schemas don't have version-specific examples
|
250
|
+
)(options.schemaCatalog)
|
251
|
+
: []
|
252
|
+
|
165
253
|
// Group files by example
|
166
254
|
const groupedFiles = groupExampleFiles(files)
|
167
255
|
|
256
|
+
// Resolve .default files into proper version coverage immediately
|
257
|
+
const resolvedFiles = resolveDefaultFiles(groupedFiles, schemaVersions)
|
258
|
+
|
168
259
|
// Process each example group
|
169
260
|
const examples: Example.Example[] = []
|
170
261
|
const diagnostics: Diagnostic[] = []
|
171
262
|
|
172
|
-
for (const [name,
|
173
|
-
// Check if this is a versioned or unversioned example
|
174
|
-
const hasMultipleVersions = versions.size > 1
|
175
|
-
const hasUnversionedFile = versions.has(null)
|
176
|
-
const hasDefaultFile = versions.has('default')
|
177
|
-
const hasOnlyDefaultFile = hasDefaultFile && versions.size === 1
|
178
|
-
|
263
|
+
for (const [name, resolved] of resolvedFiles) {
|
179
264
|
// Determine the base path for this example
|
180
|
-
const
|
181
|
-
|
182
|
-
|
183
|
-
|
265
|
+
const firstFile = resolved.unversioned
|
266
|
+
|| (HashMap.size(resolved.versionDocuments) > 0
|
267
|
+
? HashMap.values(resolved.versionDocuments).next().value
|
268
|
+
: undefined)
|
269
|
+
if (!firstFile) continue // No files for this example
|
270
|
+
|
271
|
+
const basePath = HashMap.size(resolved.versionDocuments) > 1 || resolved.unversioned
|
272
|
+
? Path.dirname(firstFile)
|
273
|
+
: firstFile
|
184
274
|
|
185
|
-
let example: Example.Example
|
275
|
+
let example: Example.Example | undefined
|
186
276
|
|
187
|
-
if (
|
277
|
+
if (resolved.unversioned) {
|
188
278
|
// Unversioned example - single file with no version
|
189
|
-
const
|
190
|
-
const fullPath = Path.join(options.dir, filePath)
|
279
|
+
const fullPath = Path.join(options.dir, resolved.unversioned)
|
191
280
|
const document = yield* fs.readFileString(fullPath)
|
192
281
|
|
193
282
|
example = Example.make({
|
@@ -197,98 +286,36 @@ export const scan = (
|
|
197
286
|
document,
|
198
287
|
}),
|
199
288
|
})
|
200
|
-
} else if (
|
201
|
-
//
|
202
|
-
const filePath = versions.get('default')!
|
203
|
-
const fullPath = Path.join(options.dir, filePath)
|
204
|
-
const documentContent = yield* fs.readFileString(fullPath)
|
205
|
-
|
206
|
-
// Get all schema versions to map to this default document
|
207
|
-
const schemaVersions: Version.Version[] = options.schemaCatalog
|
208
|
-
? SchemaCatalog.fold(
|
209
|
-
(versioned) => versioned.entries.map(entry => entry.version),
|
210
|
-
() => [], // Unversioned schemas don't have version-specific examples
|
211
|
-
)(options.schemaCatalog)
|
212
|
-
: []
|
213
|
-
|
214
|
-
if (schemaVersions.length > 0) {
|
215
|
-
// Create a version set for all schema versions
|
216
|
-
const versionSet = HashSet.fromIterable(schemaVersions)
|
217
|
-
let versionDocuments = HashMap.empty<VersionCoverage.VersionCoverage, string>()
|
218
|
-
versionDocuments = HashMap.set(versionDocuments, versionSet, documentContent)
|
219
|
-
|
220
|
-
example = Example.make({
|
221
|
-
name,
|
222
|
-
path: basePath,
|
223
|
-
document: Document.Versioned.make({
|
224
|
-
versionDocuments,
|
225
|
-
}),
|
226
|
-
})
|
227
|
-
} else {
|
228
|
-
// No schema versions, treat as unversioned
|
229
|
-
example = Example.make({
|
230
|
-
name,
|
231
|
-
path: basePath,
|
232
|
-
document: Document.Unversioned.make({
|
233
|
-
document: documentContent,
|
234
|
-
}),
|
235
|
-
})
|
236
|
-
}
|
237
|
-
} else {
|
238
|
-
// Versioned example - multiple files or versioned files
|
289
|
+
} else if (HashMap.size(resolved.versionDocuments) > 0) {
|
290
|
+
// Versioned example - read all version documents
|
239
291
|
let versionDocuments = HashMap.empty<VersionCoverage.VersionCoverage, string>()
|
240
|
-
|
241
|
-
const
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
(
|
248
|
-
|
249
|
-
)(options.schemaCatalog)
|
250
|
-
: []
|
251
|
-
|
252
|
-
// Read content for each version
|
253
|
-
for (const [version, filePath] of versions) {
|
254
|
-
const fullPath = Path.join(options.dir, filePath)
|
255
|
-
const fileContent = yield* fs.readFileString(fullPath)
|
256
|
-
|
257
|
-
if (version === 'default') {
|
258
|
-
defaultDocument = fileContent
|
259
|
-
} else if (version !== null) {
|
260
|
-
// Check if this version exists in the schema
|
261
|
-
if (options.schemaCatalog && schemaVersions.length > 0 && !schemaVersions.includes(version)) {
|
262
|
-
unknownVersions.push(version)
|
292
|
+
const unknownVersions: Version.Version[] = []
|
293
|
+
const schemaVersionsSet = HashSet.fromIterable(schemaVersions)
|
294
|
+
|
295
|
+
for (const [versionCoverage, filePath] of HashMap.entries(resolved.versionDocuments)) {
|
296
|
+
// Check if version is known (only for single versions, not sets)
|
297
|
+
if (Version.is(versionCoverage)) {
|
298
|
+
const versionExists = HashSet.has(schemaVersionsSet, versionCoverage)
|
299
|
+
if (options.schemaCatalog && schemaVersions.length > 0 && !versionExists) {
|
300
|
+
unknownVersions.push(versionCoverage)
|
263
301
|
// Create diagnostic for unknown version
|
264
302
|
diagnostics.push(makeDiagnosticUnknownVersion({
|
265
|
-
message: `Example "${name}" specifies version "${
|
303
|
+
message: `Example "${name}" specifies version "${
|
304
|
+
Version.encodeSync(versionCoverage)
|
305
|
+
}" which does not exist in the schema`,
|
266
306
|
example: { name, path: basePath },
|
267
|
-
version,
|
307
|
+
version: versionCoverage,
|
268
308
|
availableVersions: schemaVersions,
|
269
309
|
}))
|
270
310
|
// Skip this version - don't include it in the example
|
271
311
|
continue
|
272
312
|
}
|
273
|
-
|
274
|
-
const versionObj = Version.decodeSync(version)
|
275
|
-
versionDocuments = HashMap.set(versionDocuments, versionObj, fileContent)
|
276
|
-
explicitVersions.add(version)
|
277
313
|
}
|
278
|
-
}
|
279
|
-
|
280
|
-
if (defaultDocument) {
|
281
|
-
// If we have a default, determine which versions it applies to
|
282
|
-
const defaultVersions = schemaVersions.filter(v => !explicitVersions.has(v))
|
283
314
|
|
284
|
-
|
285
|
-
|
286
|
-
const defaultVersionSet = defaultVersions.length === 1
|
287
|
-
? Version.decodeSync(defaultVersions[0]!) // Single version
|
288
|
-
: HashSet.fromIterable(defaultVersions.map(_ => Version.decodeSync(_))) // Version set
|
315
|
+
const fullPath = Path.join(options.dir, filePath)
|
316
|
+
const fileContent = yield* fs.readFileString(fullPath)
|
289
317
|
|
290
|
-
|
291
|
-
}
|
318
|
+
versionDocuments = HashMap.set(versionDocuments, versionCoverage, fileContent)
|
292
319
|
}
|
293
320
|
|
294
321
|
if (HashMap.size(versionDocuments) > 0) {
|
@@ -303,9 +330,6 @@ export const scan = (
|
|
303
330
|
} else if (unknownVersions.length > 0) {
|
304
331
|
// All versions were unknown, skip this example entirely
|
305
332
|
continue
|
306
|
-
} else {
|
307
|
-
// No versions at all - shouldn't happen
|
308
|
-
continue
|
309
333
|
}
|
310
334
|
}
|
311
335
|
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Catalog } from '#lib/catalog/$'
|
2
2
|
import { Document } from '#lib/document/$'
|
3
|
-
import { Revision } from '#lib/revision/$'
|
4
3
|
import { Schema } from '#lib/schema/$'
|
5
4
|
import { Version } from '#lib/version/$'
|
6
5
|
import { HashMap, HashSet, Schema as S } from 'effect'
|
@@ -17,23 +16,23 @@ describe('type-usage-indexer', () => {
|
|
17
16
|
users: [User!]!
|
18
17
|
product(id: ID!): Product
|
19
18
|
}
|
20
|
-
|
19
|
+
|
21
20
|
type User {
|
22
21
|
id: ID!
|
23
22
|
name: String!
|
24
23
|
email: String!
|
25
24
|
}
|
26
|
-
|
25
|
+
|
27
26
|
type Product {
|
28
27
|
id: ID!
|
29
28
|
name: String!
|
30
29
|
price: Float!
|
31
30
|
}
|
32
|
-
|
31
|
+
|
33
32
|
interface Node {
|
34
33
|
id: ID!
|
35
34
|
}
|
36
|
-
|
35
|
+
|
37
36
|
union SearchResult = User | Product
|
38
37
|
`
|
39
38
|
|
@@ -91,20 +90,26 @@ describe('type-usage-indexer', () => {
|
|
91
90
|
})
|
92
91
|
|
93
92
|
const catalog = Catalog.Versioned.make({
|
94
|
-
entries:
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
93
|
+
entries: HashMap.make(
|
94
|
+
[
|
95
|
+
version1,
|
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
|
+
),
|
108
113
|
})
|
109
114
|
|
110
115
|
const index = createTypeUsageIndex([example], catalog)
|
@@ -212,20 +217,26 @@ describe('type-usage-indexer', () => {
|
|
212
217
|
})
|
213
218
|
|
214
219
|
const catalog = Catalog.Versioned.make({
|
215
|
-
entries:
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
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
|
+
),
|
229
240
|
})
|
230
241
|
|
231
242
|
const index = createTypeUsageIndex([example], catalog)
|
@@ -1,6 +1,5 @@
|
|
1
1
|
import { Catalog } from '#lib/catalog/$'
|
2
2
|
import { Document } from '#lib/document/$'
|
3
|
-
import { Schema } from '#lib/schema/$'
|
4
3
|
import { Version } from '#lib/version/$'
|
5
4
|
import { HashMap, HashSet, Option } from 'effect'
|
6
5
|
import { Schema as S } from 'effect'
|
@@ -76,19 +75,19 @@ const extractTypesFromQuery = (
|
|
76
75
|
const resolveFieldType = (
|
77
76
|
fieldName: string,
|
78
77
|
parentTypeName: string | null,
|
79
|
-
): string
|
80
|
-
if (!parentTypeName) return
|
78
|
+
): Option.Option<string> => {
|
79
|
+
if (!parentTypeName) return Option.none()
|
81
80
|
|
82
81
|
const parentType = schema.getType(parentTypeName)
|
83
82
|
if (!parentType || !isObjectType(parentType) && !isInterfaceType(parentType)) {
|
84
|
-
return
|
83
|
+
return Option.none()
|
85
84
|
}
|
86
85
|
|
87
86
|
const field = parentType.getFields()[fieldName]
|
88
|
-
if (!field) return
|
87
|
+
if (!field) return Option.none()
|
89
88
|
|
90
89
|
const namedType = getNamedType(field.type)
|
91
|
-
return namedType.name
|
90
|
+
return Option.some(namedType.name)
|
92
91
|
}
|
93
92
|
|
94
93
|
// Track the current type context as we traverse
|
@@ -120,8 +119,9 @@ const extractTypesFromQuery = (
|
|
120
119
|
// Special handling for __typename
|
121
120
|
if (node.name.value === '__typename') return
|
122
121
|
|
123
|
-
const
|
124
|
-
if (
|
122
|
+
const fieldTypeOption = resolveFieldType(node.name.value, currentType)
|
123
|
+
if (Option.isSome(fieldTypeOption)) {
|
124
|
+
const fieldType = fieldTypeOption.value
|
125
125
|
addType(fieldType)
|
126
126
|
// Update context for nested selections
|
127
127
|
if (node.selectionSet) {
|
@@ -160,32 +160,6 @@ const extractTypesFromQuery = (
|
|
160
160
|
return types
|
161
161
|
}
|
162
162
|
|
163
|
-
// ============================================================================
|
164
|
-
// Helper Functions
|
165
|
-
// ============================================================================
|
166
|
-
|
167
|
-
/**
|
168
|
-
* Get a schema by version from the catalog.
|
169
|
-
*/
|
170
|
-
const getSchemaByVersion = (
|
171
|
-
catalog: Catalog.Catalog,
|
172
|
-
version: Version.Version,
|
173
|
-
): Schema.Schema | undefined => {
|
174
|
-
if (Catalog.Versioned.is(catalog)) {
|
175
|
-
// Find the schema with matching version
|
176
|
-
return catalog.entries.find(entry =>
|
177
|
-
Schema.Versioned.is(entry)
|
178
|
-
&& Version.equivalence(entry.version, version)
|
179
|
-
)
|
180
|
-
}
|
181
|
-
// For unversioned catalog, return the single schema if version matches
|
182
|
-
if (Catalog.Unversioned.is(catalog)) {
|
183
|
-
// Unversioned catalogs don't have versions, so we can't match
|
184
|
-
return undefined
|
185
|
-
}
|
186
|
-
return undefined
|
187
|
-
}
|
188
|
-
|
189
163
|
// ============================================================================
|
190
164
|
// Index Creation
|
191
165
|
// ============================================================================
|
@@ -206,12 +180,15 @@ export const createTypeUsageIndex = (
|
|
206
180
|
// Process based on document type
|
207
181
|
if (Document.Unversioned.is(example.document)) {
|
208
182
|
// Unversioned document
|
209
|
-
const schema = Catalog.
|
183
|
+
const schema = Catalog.getLatest(schemasCatalog)
|
210
184
|
const types = extractTypesFromQuery(example.document.document, schema.definition)
|
211
185
|
|
212
186
|
for (const typeName of types) {
|
213
187
|
// For unversioned, use the latest version from the catalog
|
214
|
-
const latestVersion =
|
188
|
+
const latestVersion = Option.getOrElse(
|
189
|
+
Catalog.getLatestVersion(schemasCatalog),
|
190
|
+
() => Version.fromString('1.0.0'),
|
191
|
+
)
|
215
192
|
index = addExampleToIndex(index, UNVERSIONED_KEY, typeName, example, latestVersion)
|
216
193
|
}
|
217
194
|
} else if (Document.Versioned.is(example.document)) {
|
@@ -219,11 +196,19 @@ export const createTypeUsageIndex = (
|
|
219
196
|
const allVersions = Document.Versioned.getAllVersions(example.document)
|
220
197
|
|
221
198
|
for (const version of allVersions) {
|
222
|
-
|
223
|
-
|
199
|
+
// Use centralized resolution to get schema for version
|
200
|
+
const schemaOption = Option.liftThrowable(
|
201
|
+
() => Catalog.resolveCatalogSchema(schemasCatalog, version),
|
202
|
+
)()
|
203
|
+
if (Option.isNone(schemaOption)) {
|
204
|
+
// Skip if version not found in catalog
|
205
|
+
continue
|
206
|
+
}
|
207
|
+
const schema = schemaOption.value
|
224
208
|
|
225
|
-
const
|
226
|
-
if (
|
209
|
+
const documentStringOption = Document.Versioned.getContentForVersion(example.document, version)
|
210
|
+
if (Option.isNone(documentStringOption)) continue
|
211
|
+
const documentString = documentStringOption.value
|
227
212
|
|
228
213
|
const types = extractTypesFromQuery(documentString, schema.definition)
|
229
214
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import { Grafaid } from '#lib/grafaid'
|
2
2
|
import { Schema } from '#lib/schema/$'
|
3
3
|
import { Version } from '#lib/version/$'
|
4
|
+
import { Array, Option, Predicate } from 'effect'
|
4
5
|
|
5
6
|
export interface ReferencePathParts {
|
6
7
|
version?: Version.Version
|
@@ -46,16 +47,15 @@ export const createReferenceVersionPath = (version?: Version.Version): string =>
|
|
46
47
|
export const joinSegmentsAndPaths = (
|
47
48
|
...segmentsOrPaths: (string | undefined | null | (string | null | undefined)[])[]
|
48
49
|
): string => {
|
49
|
-
const
|
50
|
-
.flat()
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
.join('/')
|
50
|
+
const segments = Array.filterMap(
|
51
|
+
segmentsOrPaths.flat(),
|
52
|
+
(segment) => {
|
53
|
+
if (!Predicate.isNotNullable(segment)) return Option.none()
|
54
|
+
const cleaned = segment.replace(/^\//, '').replace(/\/$/, '')
|
55
|
+
return cleaned ? Option.some(cleaned) : Option.none()
|
56
|
+
},
|
57
|
+
)
|
58
|
+
const path = '/' + segments.join('/')
|
59
59
|
|
60
60
|
return path
|
61
61
|
}
|
@@ -1,4 +1,5 @@
|
|
1
1
|
import { Grafaid } from '#lib/grafaid'
|
2
|
+
import { Array, Option } from 'effect'
|
2
3
|
import type { GraphQLFieldMap, GraphQLSchema } from 'graphql'
|
3
4
|
|
4
5
|
export interface PathValidation {
|
@@ -28,8 +29,8 @@ export const doesPathExist = (schema: GraphQLSchema, path: PathValidation): bool
|
|
28
29
|
if (!path.argument) return true
|
29
30
|
|
30
31
|
// Check if argument exists
|
31
|
-
const arg = field.args
|
32
|
-
return
|
32
|
+
const arg = Array.findFirst(field.args, a => a.name === path.argument)
|
33
|
+
return Option.isSome(arg)
|
33
34
|
}
|
34
35
|
|
35
36
|
/**
|