polen 0.11.0-next.17 → 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 +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 -68
- 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 +89 -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 +17 -30
- 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.map +1 -1
- 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/api/schema/load.d.ts.map +1 -1
- package/build/api/schema/load.js +1 -1
- package/build/api/schema/load.js.map +1 -1
- package/build/lib/catalog/catalog.d.ts +43 -3
- package/build/lib/catalog/catalog.d.ts.map +1 -1
- package/build/lib/catalog/catalog.js +67 -5
- package/build/lib/catalog/catalog.js.map +1 -1
- package/build/lib/catalog/versioned.d.ts +11 -1
- package/build/lib/catalog/versioned.d.ts.map +1 -1
- package/build/lib/catalog/versioned.js +23 -5
- package/build/lib/catalog/versioned.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 +14 -12
- 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/GraphQLDocument.d.ts +1 -1
- package/build/template/components/GraphQLDocument.d.ts.map +1 -1
- package/build/template/components/GraphQLDocument.js +10 -39
- 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/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/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/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/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/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/validation-error.ts +9 -3
- package/src/api/examples/diagnostic/validator.test.ts +30 -0
- package/src/api/examples/diagnostic/validator.ts +148 -103
- package/src/api/examples/filter.ts +9 -6
- package/src/api/examples/scanner.ts +136 -117
- package/src/api/examples/type-usage-indexer.ts +24 -36
- package/src/api/iso/schema/routing.ts +10 -10
- package/src/api/iso/schema/validation.ts +3 -2
- package/src/api/schema/input-sources/directory.ts +2 -2
- package/src/api/schema/input-sources/versioned-directory.ts +5 -7
- package/src/api/schema/load.ts +1 -1
- package/src/lib/catalog/catalog.ts +89 -6
- package/src/lib/catalog/versioned.ts +26 -5
- package/src/lib/document/document.ts +135 -2
- package/src/lib/document/versioned.ts +8 -8
- package/src/lib/lifecycles/lifecycles.ts +32 -27
- 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/GraphQLDocument.tsx +11 -69
- package/src/template/components/GraphQLInteractive/lib/parser.ts +81 -29
- package/src/template/components/VersionCoveragePicker.tsx +4 -5
- package/src/template/components/home/QuickStart.tsx +16 -7
- package/src/template/hooks/use-highlighted.ts +31 -19
- package/src/template/lib/fetch-text.ts +45 -4
- package/src/template/routes/examples/name.tsx +4 -2
- package/src/template/stores/toast.ts +6 -3
- 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,13 +1,33 @@
|
|
1
1
|
import { S } from '#lib/kit-temp/effect'
|
2
2
|
import { Schema } from '#lib/schema/$'
|
3
|
+
import { VersionCoverage } from '#lib/version-coverage'
|
3
4
|
import { Version } from '#lib/version/$'
|
4
|
-
import { HashMap, Match } from 'effect'
|
5
|
+
import { Data, Either, HashMap, Match, Option } from 'effect'
|
5
6
|
import * as Unversioned from './unversioned.js'
|
6
7
|
import * as Versioned from './versioned.js'
|
7
8
|
|
8
9
|
export * as Unversioned from './unversioned.js'
|
9
10
|
export * as Versioned from './versioned.js'
|
10
11
|
|
12
|
+
// ============================================================================
|
13
|
+
// Error Types
|
14
|
+
// ============================================================================
|
15
|
+
|
16
|
+
/**
|
17
|
+
* Error thrown when a version is not found in the catalog
|
18
|
+
*/
|
19
|
+
export class VersionNotFoundInCatalogError extends Data.TaggedError('VersionNotFoundInCatalogError')<{
|
20
|
+
readonly version: string
|
21
|
+
readonly reason: string
|
22
|
+
}> {}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Error thrown when a catalog has no entries
|
26
|
+
*/
|
27
|
+
export class EmptyCatalogError extends Data.TaggedError('EmptyCatalogError')<{
|
28
|
+
readonly reason: string
|
29
|
+
}> {}
|
30
|
+
|
11
31
|
// ============================================================================
|
12
32
|
// Schema
|
13
33
|
// ============================================================================
|
@@ -87,14 +107,77 @@ export const getLatest = (catalog: Catalog): Schema.Schema =>
|
|
87
107
|
|
88
108
|
/**
|
89
109
|
* Get the latest version identifier from a catalog.
|
90
|
-
* Returns the version for versioned catalogs, or
|
110
|
+
* Returns the version for versioned catalogs, or none for unversioned catalogs.
|
91
111
|
*/
|
92
|
-
export const getLatestVersion = (catalog?: Catalog): Version.Version
|
93
|
-
if (!catalog) return
|
112
|
+
export const getLatestVersion = (catalog?: Catalog): Option.Option<Version.Version> => {
|
113
|
+
if (!catalog) return Option.none()
|
94
114
|
return Match.value(catalog).pipe(
|
95
115
|
Match.tagsExhaustive({
|
96
|
-
CatalogUnversioned: () =>
|
97
|
-
CatalogVersioned: (cat) =>
|
116
|
+
CatalogUnversioned: () => Option.none(),
|
117
|
+
CatalogVersioned: (cat) => {
|
118
|
+
const versions = Versioned.getVersions(cat)
|
119
|
+
return versions[0] ? Option.some(versions[0]) : Option.none()
|
120
|
+
},
|
98
121
|
}),
|
99
122
|
)
|
100
123
|
}
|
124
|
+
|
125
|
+
// ============================================================================
|
126
|
+
// Resolution Functions
|
127
|
+
// ============================================================================
|
128
|
+
|
129
|
+
/**
|
130
|
+
* Resolve schema from catalog for a given version coverage.
|
131
|
+
*
|
132
|
+
* @param catalog - The schema catalog
|
133
|
+
* @param versionCoverage - The version coverage to use (optional, defaults to latest)
|
134
|
+
* @returns Either with the resolved schema or error
|
135
|
+
*/
|
136
|
+
export const resolveCatalogSchemaEither = (
|
137
|
+
catalog: Catalog,
|
138
|
+
versionCoverage?: VersionCoverage.VersionCoverage | null,
|
139
|
+
): Either.Either<Schema.Schema, VersionNotFoundInCatalogError | EmptyCatalogError> => {
|
140
|
+
if (Unversioned.is(catalog)) {
|
141
|
+
return Either.right(catalog.schema)
|
142
|
+
}
|
143
|
+
|
144
|
+
// If no version coverage specified, use latest
|
145
|
+
if (!versionCoverage) {
|
146
|
+
return Versioned.getLatest(catalog)
|
147
|
+
}
|
148
|
+
|
149
|
+
// Get the latest version from the coverage
|
150
|
+
const version = VersionCoverage.getLatest(versionCoverage)
|
151
|
+
|
152
|
+
const schemaOption = HashMap.get(catalog.entries, version)
|
153
|
+
if (Option.isNone(schemaOption)) {
|
154
|
+
return Either.left(
|
155
|
+
new VersionNotFoundInCatalogError({
|
156
|
+
version: Version.encodeSync(version),
|
157
|
+
reason: `Version ${Version.encodeSync(version)} not found in catalog`,
|
158
|
+
}),
|
159
|
+
)
|
160
|
+
}
|
161
|
+
|
162
|
+
return Either.right(Option.getOrThrow(schemaOption))
|
163
|
+
}
|
164
|
+
|
165
|
+
/**
|
166
|
+
* Resolve schema from catalog for a given version coverage.
|
167
|
+
*
|
168
|
+
* @param catalog - The schema catalog
|
169
|
+
* @param versionCoverage - The version coverage to use (optional, defaults to latest)
|
170
|
+
* @returns The resolved schema
|
171
|
+
* @throws {Error} If catalog is versioned but version is not found
|
172
|
+
* @deprecated Use resolveCatalogSchemaEither which returns Either
|
173
|
+
*/
|
174
|
+
export const resolveCatalogSchema = (
|
175
|
+
catalog: Catalog,
|
176
|
+
versionCoverage?: VersionCoverage.VersionCoverage | null,
|
177
|
+
): Schema.Schema => {
|
178
|
+
const result = resolveCatalogSchemaEither(catalog, versionCoverage)
|
179
|
+
if (Either.isLeft(result)) {
|
180
|
+
throw new Error(result.left.reason)
|
181
|
+
}
|
182
|
+
return result.right
|
183
|
+
}
|
@@ -1,7 +1,8 @@
|
|
1
1
|
import { S } from '#lib/kit-temp/effect'
|
2
|
-
import { Array, HashMap, Iterable, Order, pipe } from 'effect'
|
2
|
+
import { Array, Either, HashMap, Iterable, Order, pipe } from 'effect'
|
3
3
|
import { Schema } from '../schema/$.js'
|
4
4
|
import { Version } from '../version/$.js'
|
5
|
+
import { EmptyCatalogError } from './catalog.js'
|
5
6
|
|
6
7
|
// ============================================================================
|
7
8
|
// Schema
|
@@ -50,6 +51,25 @@ export const equivalence = S.equivalence(Versioned)
|
|
50
51
|
// Domain Logic
|
51
52
|
// ============================================================================
|
52
53
|
|
54
|
+
/**
|
55
|
+
* Get the latest schema from a versioned catalog.
|
56
|
+
* The latest version is determined by Version.max comparison.
|
57
|
+
*
|
58
|
+
* @param catalog - The versioned catalog
|
59
|
+
* @returns Either with the latest schema or EmptyCatalogError
|
60
|
+
*/
|
61
|
+
export const getLatest = (catalog: Versioned): Either.Either<Schema.Versioned.Versioned, EmptyCatalogError> => {
|
62
|
+
const schema = getAll(catalog)[0]
|
63
|
+
if (!schema) {
|
64
|
+
return Either.left(
|
65
|
+
new EmptyCatalogError({
|
66
|
+
reason: 'Versioned catalog has no entries - cannot get latest schema',
|
67
|
+
}),
|
68
|
+
)
|
69
|
+
}
|
70
|
+
return Either.right(schema)
|
71
|
+
}
|
72
|
+
|
53
73
|
/**
|
54
74
|
* Get the latest schema definition from a versioned catalog.
|
55
75
|
* The latest version is determined by Version.max comparison.
|
@@ -57,13 +77,14 @@ export const equivalence = S.equivalence(Versioned)
|
|
57
77
|
* @param catalog - The versioned catalog
|
58
78
|
* @returns The GraphQL schema definition of the latest version
|
59
79
|
* @throws {Error} If the catalog has no entries
|
80
|
+
* @deprecated Use getLatest which returns Either
|
60
81
|
*/
|
61
82
|
export const getLatestOrThrow = (catalog: Versioned): Schema.Versioned.Versioned => {
|
62
|
-
const
|
63
|
-
if (
|
64
|
-
throw new Error(
|
83
|
+
const result = getLatest(catalog)
|
84
|
+
if (Either.isLeft(result)) {
|
85
|
+
throw new Error(result.left.reason)
|
65
86
|
}
|
66
|
-
return
|
87
|
+
return result.right
|
67
88
|
}
|
68
89
|
|
69
90
|
/**
|
@@ -1,6 +1,30 @@
|
|
1
|
+
import { Catalog } from '#lib/catalog/$'
|
1
2
|
import { S } from '#lib/kit-temp/effect'
|
3
|
+
import { Schema } from '#lib/schema/$'
|
4
|
+
import { VersionCoverage } from '#lib/version-coverage'
|
5
|
+
import { Version } from '#lib/version/$'
|
6
|
+
import { Data, Either, Option } from 'effect'
|
2
7
|
import { DocumentUnversioned } from './unversioned.js'
|
3
|
-
import
|
8
|
+
import * as DocumentVersioned from './versioned.js'
|
9
|
+
|
10
|
+
// ============================================================================
|
11
|
+
// Error Types
|
12
|
+
// ============================================================================
|
13
|
+
|
14
|
+
/**
|
15
|
+
* Error thrown when trying to use version coverage with an unversioned catalog
|
16
|
+
*/
|
17
|
+
export class VersionCoverageMismatchError extends Data.TaggedError('VersionCoverageMismatchError')<{
|
18
|
+
readonly reason: string
|
19
|
+
}> {}
|
20
|
+
|
21
|
+
/**
|
22
|
+
* Error thrown when a version is not found in the document
|
23
|
+
*/
|
24
|
+
export class VersionNotFoundInDocumentError extends Data.TaggedError('VersionNotFoundInDocumentError')<{
|
25
|
+
readonly version: string
|
26
|
+
readonly reason: string
|
27
|
+
}> {}
|
4
28
|
|
5
29
|
// ============================================================================
|
6
30
|
// Schema
|
@@ -13,7 +37,7 @@ import { DocumentVersioned } from './versioned.js'
|
|
13
37
|
*/
|
14
38
|
export const Document = S.Union(
|
15
39
|
DocumentUnversioned,
|
16
|
-
DocumentVersioned,
|
40
|
+
DocumentVersioned.DocumentVersioned,
|
17
41
|
)
|
18
42
|
|
19
43
|
// ============================================================================
|
@@ -35,3 +59,112 @@ export const is = S.is(Document)
|
|
35
59
|
export const decode = S.decode(Document)
|
36
60
|
export const decodeSync = S.decodeSync(Document)
|
37
61
|
export const encode = S.encode(Document)
|
62
|
+
|
63
|
+
// ============================================================================
|
64
|
+
// Domain Logic - Resolution Functions
|
65
|
+
// ============================================================================
|
66
|
+
|
67
|
+
/**
|
68
|
+
* Resolve document content for a given version coverage.
|
69
|
+
*
|
70
|
+
* @param document - The document to resolve content from
|
71
|
+
* @param versionCoverage - The version coverage to use (optional, defaults to latest)
|
72
|
+
* @returns The resolved document content
|
73
|
+
* @throws {Error} If version is not found in document
|
74
|
+
*/
|
75
|
+
export const resolveDocumentContent = (
|
76
|
+
document: Document,
|
77
|
+
versionCoverage?: VersionCoverage.VersionCoverage | null,
|
78
|
+
): string => {
|
79
|
+
if (document._tag === 'DocumentUnversioned') {
|
80
|
+
return document.document
|
81
|
+
}
|
82
|
+
|
83
|
+
// If no version coverage specified, use latest
|
84
|
+
if (!versionCoverage) {
|
85
|
+
return DocumentVersioned.getContentForLatestVersionOrThrow(document)
|
86
|
+
}
|
87
|
+
|
88
|
+
// Get the latest version from the coverage
|
89
|
+
const version = VersionCoverage.getLatest(versionCoverage)
|
90
|
+
const contentOption = DocumentVersioned.getContentForVersion(document, version)
|
91
|
+
|
92
|
+
if (Option.isNone(contentOption)) {
|
93
|
+
throw new VersionNotFoundInDocumentError({
|
94
|
+
version: Version.encodeSync(version),
|
95
|
+
reason: `Version ${Version.encodeSync(version)} not covered by document`,
|
96
|
+
})
|
97
|
+
}
|
98
|
+
|
99
|
+
return contentOption.value
|
100
|
+
}
|
101
|
+
|
102
|
+
/**
|
103
|
+
* Resolve both document content and schema for a given version coverage.
|
104
|
+
* This is the primary resolution function that handles all combinations
|
105
|
+
* of versioned/unversioned documents and catalogs.
|
106
|
+
*
|
107
|
+
* @param document - The document to resolve content from
|
108
|
+
* @param catalog - The schema catalog (optional)
|
109
|
+
* @param versionCoverage - The version coverage to use (optional, defaults to latest)
|
110
|
+
* @returns Either with resolved content and optional schema, or error
|
111
|
+
*/
|
112
|
+
export const resolveDocumentAndSchema = (
|
113
|
+
document: Document,
|
114
|
+
catalog?: Catalog.Catalog,
|
115
|
+
versionCoverage?: VersionCoverage.VersionCoverage | null,
|
116
|
+
): Either.Either<
|
117
|
+
{ content: string; schema?: Schema.Schema },
|
118
|
+
| VersionCoverageMismatchError
|
119
|
+
| VersionNotFoundInDocumentError
|
120
|
+
| Catalog.VersionNotFoundInCatalogError
|
121
|
+
| Catalog.EmptyCatalogError
|
122
|
+
> => {
|
123
|
+
// Handle unversioned document
|
124
|
+
if (document._tag === 'DocumentUnversioned') {
|
125
|
+
const content = document.document
|
126
|
+
|
127
|
+
if (!catalog) {
|
128
|
+
return Either.right({ content })
|
129
|
+
}
|
130
|
+
|
131
|
+
return Catalog.resolveCatalogSchemaEither(catalog, null).pipe(
|
132
|
+
Either.map(schema => ({ content, schema })),
|
133
|
+
)
|
134
|
+
}
|
135
|
+
|
136
|
+
// Handle versioned document
|
137
|
+
let content: string
|
138
|
+
try {
|
139
|
+
content = resolveDocumentContent(document, versionCoverage)
|
140
|
+
} catch (error) {
|
141
|
+
// resolveDocumentContent throws our tagged error
|
142
|
+
if (error instanceof VersionNotFoundInDocumentError) {
|
143
|
+
return Either.left(error)
|
144
|
+
}
|
145
|
+
// This shouldn't happen but handle gracefully
|
146
|
+
return Either.left(
|
147
|
+
new VersionNotFoundInDocumentError({
|
148
|
+
version: String(versionCoverage),
|
149
|
+
reason: error instanceof Error ? error.message : String(error),
|
150
|
+
}),
|
151
|
+
)
|
152
|
+
}
|
153
|
+
|
154
|
+
if (!catalog) {
|
155
|
+
return Either.right({ content })
|
156
|
+
}
|
157
|
+
|
158
|
+
// Cannot use version coverage with unversioned catalog
|
159
|
+
if (versionCoverage && Catalog.Unversioned.is(catalog)) {
|
160
|
+
return Either.left(
|
161
|
+
new VersionCoverageMismatchError({
|
162
|
+
reason: 'Cannot use a version coverage with an unversioned catalog',
|
163
|
+
}),
|
164
|
+
)
|
165
|
+
}
|
166
|
+
|
167
|
+
return Catalog.resolveCatalogSchemaEither(catalog, versionCoverage).pipe(
|
168
|
+
Either.map(schema => ({ content, schema })),
|
169
|
+
)
|
170
|
+
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import { S } from '#lib/kit-temp/effect'
|
2
|
-
import { VersionCoverage } from '#lib/version-
|
2
|
+
import { VersionCoverage } from '#lib/version-coverage'
|
3
3
|
import { Version } from '#lib/version/$'
|
4
4
|
import { HashMap, Option } from 'effect'
|
5
5
|
|
@@ -56,21 +56,21 @@ export const encode = S.encode(DocumentVersioned)
|
|
56
56
|
export const getContentForVersion = (
|
57
57
|
doc: DocumentVersioned,
|
58
58
|
version: Version.Version,
|
59
|
-
): string
|
59
|
+
): Option.Option<string> => {
|
60
60
|
// Try exact match first (single version key)
|
61
61
|
const exactMatch = HashMap.get(doc.versionDocuments, version)
|
62
62
|
if (Option.isSome(exactMatch)) {
|
63
|
-
return exactMatch.value
|
63
|
+
return Option.some(exactMatch.value)
|
64
64
|
}
|
65
65
|
|
66
66
|
// Check version sets
|
67
67
|
for (const [selection, content] of HashMap.entries(doc.versionDocuments)) {
|
68
68
|
if (VersionCoverage.isSet(selection) && VersionCoverage.contains(selection, version)) {
|
69
|
-
return content
|
69
|
+
return Option.some(content)
|
70
70
|
}
|
71
71
|
}
|
72
72
|
|
73
|
-
return
|
73
|
+
return Option.none()
|
74
74
|
}
|
75
75
|
|
76
76
|
/**
|
@@ -98,9 +98,9 @@ export const getContentForLatestVersionOrThrow = (doc: DocumentVersioned): strin
|
|
98
98
|
// Use Version.max with reduce to find the latest version
|
99
99
|
const latestVersion = versions.reduce(Version.max)
|
100
100
|
|
101
|
-
const
|
102
|
-
if (
|
101
|
+
const contentOption = getContentForVersion(doc, latestVersion)
|
102
|
+
if (Option.isNone(contentOption)) {
|
103
103
|
throw new Error('Latest version not found in document')
|
104
104
|
}
|
105
|
-
return
|
105
|
+
return contentOption.value
|
106
106
|
}
|
@@ -3,7 +3,7 @@ import { Change } from '#lib/change/$'
|
|
3
3
|
import { Revision } from '#lib/revision/$'
|
4
4
|
import { Schema } from '#lib/schema/$'
|
5
5
|
import { Version } from '#lib/version/$'
|
6
|
-
import { Match } from 'effect'
|
6
|
+
import { Match, Option } from 'effect'
|
7
7
|
|
8
8
|
// ============================================================================
|
9
9
|
// Lifecycles Type - Simple Index
|
@@ -44,21 +44,21 @@ export type Since =
|
|
44
44
|
/**
|
45
45
|
* Extract the type name from a change
|
46
46
|
*/
|
47
|
-
const extractTypeNameFromChange = (change: Change.Change): string
|
47
|
+
const extractTypeNameFromChange = (change: Change.Change): Option.Option<string> => {
|
48
48
|
return Match.value(change).pipe(
|
49
|
-
Match.tag('TYPE_ADDED', (c) => c.name),
|
50
|
-
Match.tag('TYPE_REMOVED', (c) => c.name),
|
51
|
-
Match.tag('FIELD_ADDED', (c) => c.typeName),
|
52
|
-
Match.tag('FIELD_REMOVED', (c) => c.typeName),
|
53
|
-
Match.tag('INPUT_FIELD_ADDED', (c) => c.inputName),
|
54
|
-
Match.tag('INPUT_FIELD_REMOVED', (c) => c.inputName),
|
55
|
-
Match.tag('ENUM_VALUE_ADDED', (c) => c.enumName),
|
56
|
-
Match.tag('ENUM_VALUE_REMOVED', (c) => c.enumName),
|
57
|
-
Match.tag('UNION_MEMBER_ADDED', (c) => c.unionName),
|
58
|
-
Match.tag('UNION_MEMBER_REMOVED', (c) => c.unionName),
|
59
|
-
Match.tag('OBJECT_TYPE_INTERFACE_ADDED', (c) => c.objectName),
|
60
|
-
Match.tag('OBJECT_TYPE_INTERFACE_REMOVED', (c) => c.objectName),
|
61
|
-
Match.orElse(() =>
|
49
|
+
Match.tag('TYPE_ADDED', (c) => Option.some(c.name)),
|
50
|
+
Match.tag('TYPE_REMOVED', (c) => Option.some(c.name)),
|
51
|
+
Match.tag('FIELD_ADDED', (c) => Option.some(c.typeName)),
|
52
|
+
Match.tag('FIELD_REMOVED', (c) => Option.some(c.typeName)),
|
53
|
+
Match.tag('INPUT_FIELD_ADDED', (c) => Option.some(c.inputName)),
|
54
|
+
Match.tag('INPUT_FIELD_REMOVED', (c) => Option.some(c.inputName)),
|
55
|
+
Match.tag('ENUM_VALUE_ADDED', (c) => Option.some(c.enumName)),
|
56
|
+
Match.tag('ENUM_VALUE_REMOVED', (c) => Option.some(c.enumName)),
|
57
|
+
Match.tag('UNION_MEMBER_ADDED', (c) => Option.some(c.unionName)),
|
58
|
+
Match.tag('UNION_MEMBER_REMOVED', (c) => Option.some(c.unionName)),
|
59
|
+
Match.tag('OBJECT_TYPE_INTERFACE_ADDED', (c) => Option.some(c.objectName)),
|
60
|
+
Match.tag('OBJECT_TYPE_INTERFACE_REMOVED', (c) => Option.some(c.objectName)),
|
61
|
+
Match.orElse(() => Option.none()),
|
62
62
|
)
|
63
63
|
}
|
64
64
|
|
@@ -72,8 +72,9 @@ export const createFromSchema = (schema: Schema.Schema): Lifecycles => {
|
|
72
72
|
for (const revision of schema.revisions) {
|
73
73
|
// Process all changes in this revision
|
74
74
|
for (const change of revision.changes) {
|
75
|
-
const
|
76
|
-
if (
|
75
|
+
const typeNameOption = extractTypeNameFromChange(change)
|
76
|
+
if (Option.isSome(typeNameOption)) {
|
77
|
+
const typeName = typeNameOption.value
|
77
78
|
if (!lifecycles[typeName]) {
|
78
79
|
lifecycles[typeName] = []
|
79
80
|
}
|
@@ -100,8 +101,9 @@ export const create = (catalog: Catalog.Catalog): Lifecycles => {
|
|
100
101
|
for (const revision of schema.revisions) {
|
101
102
|
// Process all changes in this revision
|
102
103
|
for (const change of revision.changes) {
|
103
|
-
const
|
104
|
-
if (
|
104
|
+
const typeNameOption = extractTypeNameFromChange(change)
|
105
|
+
if (Option.isSome(typeNameOption)) {
|
106
|
+
const typeName = typeNameOption.value
|
105
107
|
if (!lifecycles[typeName]) {
|
106
108
|
lifecycles[typeName] = []
|
107
109
|
}
|
@@ -477,9 +479,9 @@ export const getFieldLifecycle = (
|
|
477
479
|
lifecycles: Lifecycles,
|
478
480
|
typeName: string,
|
479
481
|
fieldName: string,
|
480
|
-
): { events: ChangeEntry[] }
|
482
|
+
): Option.Option<{ events: ChangeEntry[] }> => {
|
481
483
|
const entries = lifecycles[typeName]
|
482
|
-
if (!entries) return
|
484
|
+
if (!entries) return Option.none()
|
483
485
|
|
484
486
|
// Filter entries related to this specific field
|
485
487
|
const fieldEntries = entries.filter(entry => {
|
@@ -497,25 +499,28 @@ export const getFieldLifecycle = (
|
|
497
499
|
&& entry.change.fieldName === fieldName)
|
498
500
|
})
|
499
501
|
|
500
|
-
if (fieldEntries.length === 0) return
|
502
|
+
if (fieldEntries.length === 0) return Option.none()
|
501
503
|
|
502
504
|
// Return in a format compatible with existing code that expects an object with events
|
503
|
-
return { events: fieldEntries }
|
505
|
+
return Option.some({ events: fieldEntries })
|
504
506
|
}
|
505
507
|
|
506
508
|
/**
|
507
509
|
* Get type lifecycle info (for compatibility with existing UI code)
|
508
510
|
*/
|
509
|
-
export const getTypeLifecycle = (
|
511
|
+
export const getTypeLifecycle = (
|
512
|
+
lifecycles: Lifecycles,
|
513
|
+
typeName: string,
|
514
|
+
): Option.Option<{ events: ChangeEntry[] }> => {
|
510
515
|
const entries = lifecycles[typeName]
|
511
|
-
if (!entries) return
|
516
|
+
if (!entries) return Option.none()
|
512
517
|
|
513
518
|
// Filter entries related to type-level changes
|
514
519
|
const typeEntries = entries.filter(entry => {
|
515
520
|
return entry.change._tag === 'TYPE_ADDED' || entry.change._tag === 'TYPE_REMOVED'
|
516
521
|
})
|
517
522
|
|
518
|
-
if (typeEntries.length === 0) return
|
523
|
+
if (typeEntries.length === 0) return Option.none()
|
519
524
|
|
520
|
-
return { events: typeEntries }
|
525
|
+
return Option.some({ events: typeEntries })
|
521
526
|
}
|
@@ -0,0 +1 @@
|
|
1
|
+
export * from './version-coverage.js'
|
package/src/lib/{version-selection/version-selection.ts → version-coverage/version-coverage.ts}
RENAMED
@@ -58,7 +58,7 @@ export const encodeSync = S.encodeSync(VersionCoverage)
|
|
58
58
|
export const equivalence = S.equivalence(VersionCoverage)
|
59
59
|
|
60
60
|
// ============================================================================
|
61
|
-
// Domain Logic
|
61
|
+
// Domain Logic - Basic Operations
|
62
62
|
// ============================================================================
|
63
63
|
|
64
64
|
/**
|
@@ -1,12 +1,7 @@
|
|
1
1
|
import { Catalog } from '#lib/catalog/$'
|
2
2
|
import { Document } from '#lib/document/$'
|
3
|
-
import {
|
4
|
-
import
|
5
|
-
import { VersionCoverage } from '#lib/version-selection/$'
|
6
|
-
import { VersionCoverageSet } from '#lib/version-selection/version-selection'
|
7
|
-
import { Version } from '#lib/version/$'
|
8
|
-
import { Array, HashMap, Match, Option } from 'effect'
|
9
|
-
import type { GraphQLSchema } from 'graphql'
|
3
|
+
import { VersionCoverage } from '#lib/version-coverage'
|
4
|
+
import { Either, Option } from 'effect'
|
10
5
|
import * as React from 'react'
|
11
6
|
import { useHighlighted } from '../hooks/use-highlighted.js'
|
12
7
|
import { GraphQLInteractive } from './GraphQLInteractive/GraphQLInteractive.js'
|
@@ -47,7 +42,7 @@ export const GraphQLDocument: React.FC<GraphQLDocumentProps> = ({
|
|
47
42
|
/// ━ VERSION MANAGEMENT
|
48
43
|
const isControlled = controlledVersionCoverage !== undefined
|
49
44
|
const [internalVersionCoverage, setInternalVersionCoverage] = React.useState<VersionCoverage.VersionCoverage | null>(
|
50
|
-
Catalog.getLatestVersion(schemaCatalog),
|
45
|
+
Option.getOrNull(Catalog.getLatestVersion(schemaCatalog)),
|
51
46
|
)
|
52
47
|
const selectedVersionCoverage = isControlled ? controlledVersionCoverage : internalVersionCoverage
|
53
48
|
const internalOnVersionChange = (version: VersionCoverage.VersionCoverage) => {
|
@@ -58,11 +53,15 @@ export const GraphQLDocument: React.FC<GraphQLDocumentProps> = ({
|
|
58
53
|
}
|
59
54
|
|
60
55
|
/// ━ DATA RESOLUTION
|
61
|
-
const
|
62
|
-
schema,
|
63
|
-
content,
|
64
|
-
} = resolveSelectedVerCov(document, selectedVersionCoverage, schemaCatalog)
|
56
|
+
const result = Document.resolveDocumentAndSchema(document, schemaCatalog, selectedVersionCoverage)
|
65
57
|
|
58
|
+
// Handle resolution errors gracefully
|
59
|
+
if (Either.isLeft(result)) {
|
60
|
+
console.error('Failed to resolve document and schema:', result.left.message)
|
61
|
+
return null
|
62
|
+
}
|
63
|
+
|
64
|
+
const { schema, content } = result.right
|
66
65
|
const highlightedCode = useHighlighted(content, { interactive: true })
|
67
66
|
|
68
67
|
if (!highlightedCode) {
|
@@ -87,60 +86,3 @@ export const GraphQLDocument: React.FC<GraphQLDocumentProps> = ({
|
|
87
86
|
/>
|
88
87
|
)
|
89
88
|
}
|
90
|
-
|
91
|
-
/**
|
92
|
-
* Matches a document with an optional schema catalog, returning the document content,
|
93
|
-
* corresponding schema, and available versions for the selected version.
|
94
|
-
*
|
95
|
-
* @param document - The document to retrieve content from (required)
|
96
|
-
* @param selectedVersionCoverage - The version to select (optional, defaults to latest)
|
97
|
-
* @param schemaCatalog - The schema catalog to match against (optional)
|
98
|
-
* @returns Object with document content, optional schema, and available versions
|
99
|
-
* @throws {Error} If versions in catalog don't match versions in document
|
100
|
-
*/
|
101
|
-
type Result = { content: string; schema?: Schema.Schema }
|
102
|
-
const resolveSelectedVerCov = (
|
103
|
-
document: Document.Document,
|
104
|
-
selectedVersionCoverage?: VersionCoverage.VersionCoverage | null,
|
105
|
-
schemaCatalog?: Catalog.Catalog,
|
106
|
-
): Result => {
|
107
|
-
if (Document.Unversioned.is(document)) {
|
108
|
-
return {
|
109
|
-
content: document.document,
|
110
|
-
schema: Match.value(schemaCatalog).pipe(
|
111
|
-
Match.tagsExhaustive({
|
112
|
-
CatalogUnversioned: (catalog) => catalog.schema,
|
113
|
-
CatalogVersioned: (catalog) => Catalog.Versioned.getLatestOrThrow(catalog),
|
114
|
-
}),
|
115
|
-
),
|
116
|
-
}
|
117
|
-
}
|
118
|
-
|
119
|
-
return Match.value(selectedVersionCoverage).pipe(
|
120
|
-
Match.whenOr(null, undefined, _ => {
|
121
|
-
const content = Document.Versioned.getContentForLatestVersionOrThrow(document)
|
122
|
-
return { content }
|
123
|
-
}),
|
124
|
-
Match.orElse(_ => {
|
125
|
-
const version = VersionCoverage.getLatest(_)
|
126
|
-
|
127
|
-
const content = Document.Versioned.getContentForVersion(document, version)
|
128
|
-
if (!content) {
|
129
|
-
throw new Error(`Version ${Version.encodeSync(version)} not covered by document`)
|
130
|
-
}
|
131
|
-
|
132
|
-
if (!schemaCatalog) return { version, content }
|
133
|
-
|
134
|
-
if (Catalog.Unversioned.is(schemaCatalog)) {
|
135
|
-
throw new Error('Cannot use a set of versions with an unversioned catalog')
|
136
|
-
}
|
137
|
-
const schemaOption = HashMap.get(schemaCatalog.entries, version)
|
138
|
-
if (Option.isNone(schemaOption)) {
|
139
|
-
throw new Error(`Version ${Version.encodeSync(version)} not found in catalog`)
|
140
|
-
}
|
141
|
-
const schema = Option.getOrThrow(schemaOption)
|
142
|
-
|
143
|
-
return { content, schema: schema }
|
144
|
-
}),
|
145
|
-
)
|
146
|
-
}
|