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,12 +1,35 @@
|
|
1
1
|
import { Catalog as SchemaCatalog } from '#lib/catalog/$';
|
2
2
|
import { Document } from '#lib/document/$';
|
3
|
+
import { Schema } from '#lib/schema/$';
|
3
4
|
import { Version } from '#lib/version/$';
|
4
|
-
import { Match } from 'effect';
|
5
|
-
import { HashMap } from 'effect/Schema';
|
5
|
+
import { Array, Either, Match, Schema as S } from 'effect';
|
6
6
|
import { parse, specifiedRules, validate } from 'graphql';
|
7
7
|
import { Example } from '../schemas/example/$.js';
|
8
8
|
import { makeDiagnosticValidationError } from './diagnostic.js';
|
9
9
|
// ============================================================================
|
10
|
+
// Schemas
|
11
|
+
// ============================================================================
|
12
|
+
const GraphQLErrorData = S.Struct({
|
13
|
+
message: S.String,
|
14
|
+
locations: S.optional(S.Array(S.Struct({
|
15
|
+
line: S.Number,
|
16
|
+
column: S.Number,
|
17
|
+
}))),
|
18
|
+
});
|
19
|
+
// ============================================================================
|
20
|
+
// Safe Parsing
|
21
|
+
// ============================================================================
|
22
|
+
/**
|
23
|
+
* Safely parse a GraphQL document without throwing.
|
24
|
+
* Returns an Either with the document on success or error on failure.
|
25
|
+
*/
|
26
|
+
const parseDocumentSafe = (content) => {
|
27
|
+
return Either.try({
|
28
|
+
try: () => parse(content),
|
29
|
+
catch: (error) => error,
|
30
|
+
});
|
31
|
+
};
|
32
|
+
// ============================================================================
|
10
33
|
// Validation
|
11
34
|
// ============================================================================
|
12
35
|
/**
|
@@ -18,42 +41,60 @@ import { makeDiagnosticValidationError } from './diagnostic.js';
|
|
18
41
|
*/
|
19
42
|
export const validateExamples = (examples, catalog) => {
|
20
43
|
const diagnostics = [];
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
Array.forEach(examples, (example) => {
|
45
|
+
if (example.document._tag === 'DocumentVersioned') {
|
46
|
+
// Versioned document: iterate all versions and let utility handle compatibility
|
47
|
+
const documentVersions = Document.Versioned.getAllVersions(example.document);
|
48
|
+
let versionMismatchDetected = false;
|
49
|
+
Array.forEach(documentVersions, (version) => {
|
50
|
+
// Skip remaining versions if we already detected a version mismatch
|
51
|
+
if (versionMismatchDetected)
|
52
|
+
return;
|
53
|
+
const result = Document.resolveDocumentAndSchema(example.document, catalog, version);
|
54
|
+
Either.match(result, {
|
55
|
+
onLeft: (error) => {
|
56
|
+
// Pattern match on error types - all errors are now tagged
|
57
|
+
Match.value(error).pipe(Match.when({ _tag: 'VersionCoverageMismatchError' }, (err) => {
|
58
|
+
diagnostics.push(makeDiagnosticValidationError({
|
59
|
+
message: `Example "${example.name}" has versioned content but catalog is unversioned`,
|
60
|
+
example: { name: example.name, path: example.path },
|
61
|
+
version: undefined,
|
62
|
+
errors: [{ message: err.reason }],
|
63
|
+
}));
|
64
|
+
// Set flag to skip remaining versions - all will have same error
|
65
|
+
versionMismatchDetected = true;
|
66
|
+
}), Match.when({ _tag: 'VersionNotFoundInDocumentError' }, () => {
|
67
|
+
// Skip silently - version not found in document
|
68
|
+
}), Match.when({ _tag: 'VersionNotFoundInCatalogError' }, () => {
|
69
|
+
// Skip silently - version not found in catalog
|
70
|
+
}), Match.when({ _tag: 'EmptyCatalogError' }, () => {
|
71
|
+
// Skip silently - catalog has no entries
|
72
|
+
}), Match.exhaustive);
|
35
73
|
},
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
74
|
+
onRight: ({ content, schema }) => {
|
75
|
+
if (schema) {
|
76
|
+
validateDocument(example, schema, content, diagnostics);
|
77
|
+
}
|
40
78
|
},
|
41
|
-
})
|
42
|
-
}
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
}
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
79
|
+
});
|
80
|
+
});
|
81
|
+
}
|
82
|
+
else {
|
83
|
+
// Unversioned document: call without version coverage
|
84
|
+
const result = Document.resolveDocumentAndSchema(example.document, catalog);
|
85
|
+
Either.match(result, {
|
86
|
+
onLeft: () => {
|
87
|
+
// Resolution failed - skip silently
|
88
|
+
},
|
89
|
+
onRight: ({ content, schema }) => {
|
90
|
+
if (schema) {
|
91
|
+
validateDocument(example, schema, content, diagnostics);
|
92
|
+
}
|
93
|
+
},
|
94
|
+
});
|
95
|
+
}
|
96
|
+
});
|
97
|
+
return diagnostics;
|
57
98
|
};
|
58
99
|
// ============================================================================
|
59
100
|
// Helpers
|
@@ -61,55 +102,61 @@ export const validateExamples = (examples, catalog) => {
|
|
61
102
|
/**
|
62
103
|
* Validate a single document and add diagnostics if needed.
|
63
104
|
*/
|
64
|
-
const validateDocument = (
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
105
|
+
const validateDocument = (example, schema, content, diagnostics) => {
|
106
|
+
// Extract version from schema (undefined for unversioned)
|
107
|
+
const version = Schema.getVersion(schema);
|
108
|
+
// Parse the document safely
|
109
|
+
const parseResult = parseDocumentSafe(content);
|
110
|
+
if (Either.isLeft(parseResult)) {
|
111
|
+
// Handle parse errors
|
112
|
+
diagnostics.push(makeDiagnosticValidationError({
|
113
|
+
message: formatParseError(example.name, version),
|
114
|
+
example: { name: example.name, path: example.path },
|
115
|
+
version,
|
116
|
+
errors: [{ message: parseResult.left.message }],
|
117
|
+
}));
|
118
|
+
return;
|
78
119
|
}
|
79
|
-
|
80
|
-
|
120
|
+
// Validate the parsed document against the schema
|
121
|
+
const errors = validate(schema.definition, parseResult.right, specifiedRules);
|
122
|
+
if (Array.isNonEmptyReadonlyArray(errors)) {
|
81
123
|
diagnostics.push(makeDiagnosticValidationError({
|
82
|
-
message:
|
83
|
-
example: { name:
|
124
|
+
message: formatValidationMessage(example.name, version, errors),
|
125
|
+
example: { name: example.name, path: example.path },
|
84
126
|
version,
|
85
|
-
errors:
|
127
|
+
errors: errors.map(formatGraphQLError),
|
86
128
|
}));
|
87
129
|
}
|
88
130
|
};
|
131
|
+
/**
|
132
|
+
* Format a parse error message for an example.
|
133
|
+
*/
|
134
|
+
const formatParseError = (exampleId, version) => {
|
135
|
+
const versionStr = version ? ` (${Version.encodeSync(version)})` : '';
|
136
|
+
return `Example "${exampleId}"${versionStr} has invalid GraphQL syntax`;
|
137
|
+
};
|
89
138
|
/**
|
90
139
|
* Format a validation message for an example.
|
91
140
|
*/
|
92
141
|
const formatValidationMessage = (exampleId, version, errors) => {
|
93
|
-
const versionStr = version
|
142
|
+
const versionStr = version ? ` (${Version.encodeSync(version)})` : '';
|
94
143
|
const errorCount = errors.length;
|
95
144
|
const errorWord = errorCount === 1 ? 'error' : 'errors';
|
96
|
-
// Include the first error message for context
|
97
|
-
const firstError = errors
|
98
|
-
const preview =
|
145
|
+
// Include the first error message for context - always safe with NonEmptyArray
|
146
|
+
const firstError = Array.headNonEmpty(errors);
|
147
|
+
const preview = `: ${firstError.message}`;
|
99
148
|
return `Example "${exampleId}"${versionStr} has ${errorCount} validation ${errorWord}${preview}`;
|
100
149
|
};
|
101
150
|
/**
|
102
151
|
* Format a GraphQL error for diagnostic reporting.
|
103
152
|
*/
|
104
|
-
const formatGraphQLError = (error) => ({
|
153
|
+
const formatGraphQLError = (error) => GraphQLErrorData.make({
|
105
154
|
message: error.message,
|
106
|
-
...(error.locations
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
}
|
113
|
-
: {}),
|
155
|
+
...(error.locations && {
|
156
|
+
locations: error.locations.map(loc => ({
|
157
|
+
line: loc.line,
|
158
|
+
column: loc.column,
|
159
|
+
})),
|
160
|
+
}),
|
114
161
|
});
|
115
162
|
//# sourceMappingURL=validator.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../../src/api/examples/diagnostic/validator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAC1C,OAAO,EAAE,
|
1
|
+
{"version":3,"file":"validator.js","sourceRoot":"","sources":["../../../../src/api/examples/diagnostic/validator.ts"],"names":[],"mappings":"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"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/api/examples/filter.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"filter.d.ts","sourceRoot":"","sources":["../../../src/api/examples/filter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEhD;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACpC,UAAU,OAAO,CAAC,OAAO,EAAE,EAC3B,WAAW,gBAAgB,GAAG,SAAS,KACtC,OAAO,CAAC,OAAO,EA6BjB,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAC/B,aAAa,WAAW,EACxB,WAAW,gBAAgB,GAAG,SAAS,KACtC,OA6BF,CAAA"}
|
@@ -1,3 +1,4 @@
|
|
1
|
+
import { HashSet } from 'effect';
|
1
2
|
import { Example } from './schemas/example/$.js';
|
2
3
|
/**
|
3
4
|
* Filter examples based on the display configuration.
|
@@ -20,13 +21,13 @@ export const filterExamplesBySelection = (examples, selection) => {
|
|
20
21
|
}
|
21
22
|
// Handle include pattern
|
22
23
|
if ('include' in selection) {
|
23
|
-
const includeSet =
|
24
|
-
return examples.filter(example =>
|
24
|
+
const includeSet = HashSet.fromIterable(selection.include);
|
25
|
+
return examples.filter(example => HashSet.has(includeSet, example.name));
|
25
26
|
}
|
26
27
|
// Handle exclude pattern
|
27
28
|
if ('exclude' in selection) {
|
28
|
-
const excludeSet =
|
29
|
-
return examples.filter(example => !
|
29
|
+
const excludeSet = HashSet.fromIterable(selection.exclude);
|
30
|
+
return examples.filter(example => !HashSet.has(excludeSet, example.name));
|
30
31
|
}
|
31
32
|
// Fallback to all examples if selection pattern is not recognized
|
32
33
|
return examples;
|
@@ -52,11 +53,13 @@ export const shouldDisplayExample = (exampleName, selection) => {
|
|
52
53
|
}
|
53
54
|
// Handle include pattern
|
54
55
|
if ('include' in selection) {
|
55
|
-
|
56
|
+
const includeSet = HashSet.fromIterable(selection.include);
|
57
|
+
return HashSet.has(includeSet, exampleName);
|
56
58
|
}
|
57
59
|
// Handle exclude pattern
|
58
60
|
if ('exclude' in selection) {
|
59
|
-
|
61
|
+
const excludeSet = HashSet.fromIterable(selection.exclude);
|
62
|
+
return !HashSet.has(excludeSet, exampleName);
|
60
63
|
}
|
61
64
|
// Fallback to show if selection pattern is not recognized
|
62
65
|
return true;
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../src/api/examples/filter.ts"],"names":[],"mappings":"
|
1
|
+
{"version":3,"file":"filter.js","sourceRoot":"","sources":["../../../src/api/examples/filter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;AAEhC,OAAO,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAEhD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,CACvC,QAA2B,EAC3B,SAAuC,EACpB,EAAE;IACrB,yCAAyC;IACzC,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,yBAAyB;IACzB,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAA;IACjB,CAAC;IAED,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO,EAAE,CAAA;IACX,CAAC;IAED,yBAAyB;IACzB,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAC1D,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,IAAmB,CAAC,CAAC,CAAA;IACzF,CAAC;IAED,yBAAyB;IACzB,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAC1D,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,IAAmB,CAAC,CAAC,CAAA;IAC1F,CAAC;IAED,kEAAkE;IAClE,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,WAAwB,EACxB,SAAuC,EAC9B,EAAE;IACX,0CAA0C;IAC1C,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,yBAAyB;IACzB,IAAI,SAAS,KAAK,KAAK,EAAE,CAAC;QACxB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,IAAI,SAAS,KAAK,MAAM,EAAE,CAAC;QACzB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,yBAAyB;IACzB,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAC1D,OAAO,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;IAC7C,CAAC;IAED,yBAAyB;IACzB,IAAI,SAAS,IAAI,SAAS,EAAE,CAAC;QAC3B,MAAM,UAAU,GAAG,OAAO,CAAC,YAAY,CAAC,SAAS,CAAC,OAAO,CAAC,CAAA;QAC1D,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,WAAW,CAAC,CAAA;IAC9C,CAAC;IAED,0DAA0D;IAC1D,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../src/api/examples/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAKzD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,
|
1
|
+
{"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../../../src/api/examples/scanner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAKzD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAS,MAAM,EAA2B,MAAM,QAAQ,CAAA;AAE/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAA;AAO5D,OAAO,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAA;AAO9C,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,EAAE,UAAU,EAAE,CAAA;CAC1B;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,UAAU,CAAC,EAAE,MAAM,EAAE,CAAA;IACrB,aAAa,CAAC,EAAE,aAAa,CAAC,OAAO,CAAA;CACtC;AA2MD,eAAO,MAAM,IAAI,GACf,SAAS,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;CAAE,KAC1C,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CA+HrD,CAAA"}
|
@@ -1,13 +1,13 @@
|
|
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
|
-
import { makeDiagnosticDuplicateContent, makeDiagnosticMissingVersions, makeDiagnosticUnknownVersion,
|
10
|
+
import { makeDiagnosticDuplicateContent, makeDiagnosticMissingVersions, makeDiagnosticUnknownVersion, } from './diagnostic/diagnostic.js';
|
11
11
|
import { validateExamples } from './diagnostic/validator.js';
|
12
12
|
import { Catalog } from './schemas/catalog.js';
|
13
13
|
import { Example } from './schemas/example/$.js';
|
@@ -20,7 +20,7 @@ const VERSIONED_FILE_PATTERN = Str.pattern(/^(?<name>.+?)\.(?<version>.+)$/);
|
|
20
20
|
// ============================================================================
|
21
21
|
// Helpers
|
22
22
|
// ============================================================================
|
23
|
-
const
|
23
|
+
const parseExampleFile = (filename) => {
|
24
24
|
const parsed = Path.parse(filename);
|
25
25
|
const base = parsed.name;
|
26
26
|
// Try to match versioned pattern: <name>.<version>
|
@@ -29,26 +29,70 @@ const parseExampleFilename = (filename) => {
|
|
29
29
|
const { name, version: versionStr } = match.groups;
|
30
30
|
// Handle special 'default' keyword
|
31
31
|
if (versionStr === 'default') {
|
32
|
-
return {
|
32
|
+
return { type: 'default', name, file: filename };
|
33
33
|
}
|
34
|
-
const
|
35
|
-
|
36
|
-
return { name, version: Version.encodeSync(decoded) };
|
34
|
+
const version = Version.decodeSync(versionStr);
|
35
|
+
return { type: 'versioned', name, version, file: filename };
|
37
36
|
}
|
38
37
|
// No version found - this is an unversioned example
|
39
|
-
return { name: base,
|
38
|
+
return { type: 'unversioned', name: base, file: filename };
|
40
39
|
};
|
41
40
|
const groupExampleFiles = (files) => {
|
42
41
|
const grouped = new Map();
|
43
42
|
for (const file of files) {
|
44
|
-
const
|
45
|
-
if (!grouped.has(name)) {
|
46
|
-
grouped.set(name,
|
43
|
+
const parsed = parseExampleFile(file);
|
44
|
+
if (!grouped.has(parsed.name)) {
|
45
|
+
grouped.set(parsed.name, {
|
46
|
+
versioned: new Map(),
|
47
|
+
});
|
48
|
+
}
|
49
|
+
const group = grouped.get(parsed.name);
|
50
|
+
switch (parsed.type) {
|
51
|
+
case 'unversioned':
|
52
|
+
group.unversioned = parsed.file;
|
53
|
+
break;
|
54
|
+
case 'versioned':
|
55
|
+
group.versioned.set(parsed.version, parsed.file);
|
56
|
+
break;
|
57
|
+
case 'default':
|
58
|
+
group.default = parsed.file;
|
59
|
+
break;
|
47
60
|
}
|
48
|
-
grouped.get(name).set(version, file);
|
49
61
|
}
|
50
62
|
return grouped;
|
51
63
|
};
|
64
|
+
/**
|
65
|
+
* Resolve .default files into proper version coverage.
|
66
|
+
* This erases the .default convention and converts it to semantic version sets.
|
67
|
+
*/
|
68
|
+
const resolveDefaultFiles = (grouped, schemaVersions) => {
|
69
|
+
const resolved = new Map();
|
70
|
+
for (const [name, group] of grouped) {
|
71
|
+
let versionDocuments = HashMap.empty();
|
72
|
+
// Add explicit versions
|
73
|
+
for (const [version, file] of group.versioned) {
|
74
|
+
versionDocuments = HashMap.set(versionDocuments, version, file);
|
75
|
+
}
|
76
|
+
// Handle default file if present
|
77
|
+
if (group.default) {
|
78
|
+
// Determine which versions the default covers
|
79
|
+
const explicitVersions = HashSet.fromIterable(group.versioned.keys());
|
80
|
+
const defaultVersions = schemaVersions.filter(v => !HashSet.has(explicitVersions, v));
|
81
|
+
if (defaultVersions.length > 0) {
|
82
|
+
// Create version coverage for default
|
83
|
+
const defaultCoverage = defaultVersions.length === 1
|
84
|
+
? defaultVersions[0] // Single version
|
85
|
+
: HashSet.fromIterable(defaultVersions); // Version set
|
86
|
+
versionDocuments = HashMap.set(versionDocuments, defaultCoverage, group.default);
|
87
|
+
}
|
88
|
+
}
|
89
|
+
resolved.set(name, {
|
90
|
+
versionDocuments,
|
91
|
+
...(group.unversioned ? { unversioned: group.unversioned } : {}),
|
92
|
+
});
|
93
|
+
}
|
94
|
+
return resolved;
|
95
|
+
};
|
52
96
|
const lintFileLayout = (example, schemaCatalog) => {
|
53
97
|
// Extract schema versions from catalog if provided
|
54
98
|
const schemaVersions = schemaCatalog
|
@@ -59,7 +103,7 @@ const lintFileLayout = (example, schemaCatalog) => {
|
|
59
103
|
DocumentVersioned: (doc) => {
|
60
104
|
// Get all versions covered by this document
|
61
105
|
const coveredVersions = Document.Versioned.getAllVersions(doc);
|
62
|
-
const missingVersions =
|
106
|
+
const missingVersions = Array.filter(schemaVersions, sv => !Array.some(coveredVersions, cv => Version.equivalence(sv, cv)));
|
63
107
|
if (missingVersions.length > 0) {
|
64
108
|
diagnostics.push(makeDiagnosticMissingVersions({
|
65
109
|
message: `Versioned example must provide documents for all schema versions`,
|
@@ -69,7 +113,7 @@ const lintFileLayout = (example, schemaCatalog) => {
|
|
69
113
|
}));
|
70
114
|
}
|
71
115
|
// Check for duplicate content between selections
|
72
|
-
const entries =
|
116
|
+
const entries = [...HashMap.entries(doc.versionDocuments)];
|
73
117
|
const duplicates = [];
|
74
118
|
for (let i = 0; i < entries.length; i++) {
|
75
119
|
for (let j = i + 1; j < entries.length; j++) {
|
@@ -105,27 +149,32 @@ export const scan = (options) => Effect.gen(function* () {
|
|
105
149
|
const extensions = options.extensions ?? DEFAULT_EXTENSIONS;
|
106
150
|
const pattern = `**/*.{${extensions.join(',')}}`;
|
107
151
|
const files = options.files ?? (yield* EffectGlob.glob(pattern, { cwd: options.dir }));
|
152
|
+
// Get schema versions upfront for default file resolution
|
153
|
+
const schemaVersions = options.schemaCatalog
|
154
|
+
? SchemaCatalog.fold((versioned) => SchemaCatalog.Versioned.getVersions(versioned), () => [])(options.schemaCatalog)
|
155
|
+
: [];
|
108
156
|
// Group files by example
|
109
157
|
const groupedFiles = groupExampleFiles(files);
|
158
|
+
// Resolve .default files into proper version coverage immediately
|
159
|
+
const resolvedFiles = resolveDefaultFiles(groupedFiles, schemaVersions);
|
110
160
|
// Process each example group
|
111
161
|
const examples = [];
|
112
162
|
const diagnostics = [];
|
113
|
-
for (const [name,
|
114
|
-
// Check if this is a versioned or unversioned example
|
115
|
-
const hasMultipleVersions = versions.size > 1;
|
116
|
-
const hasUnversionedFile = versions.has(null);
|
117
|
-
const hasDefaultFile = versions.has('default');
|
118
|
-
const hasOnlyDefaultFile = hasDefaultFile && versions.size === 1;
|
163
|
+
for (const [name, resolved] of resolvedFiles) {
|
119
164
|
// Determine the base path for this example
|
120
|
-
const
|
121
|
-
|
122
|
-
|
123
|
-
|
165
|
+
const firstFile = resolved.unversioned
|
166
|
+
|| (HashMap.size(resolved.versionDocuments) > 0
|
167
|
+
? HashMap.values(resolved.versionDocuments).next().value
|
168
|
+
: undefined);
|
169
|
+
if (!firstFile)
|
170
|
+
continue; // No files for this example
|
171
|
+
const basePath = HashMap.size(resolved.versionDocuments) > 1 || resolved.unversioned
|
172
|
+
? Path.dirname(firstFile)
|
173
|
+
: firstFile;
|
124
174
|
let example;
|
125
|
-
if (
|
175
|
+
if (resolved.unversioned) {
|
126
176
|
// Unversioned example - single file with no version
|
127
|
-
const
|
128
|
-
const fullPath = Path.join(options.dir, filePath);
|
177
|
+
const fullPath = Path.join(options.dir, resolved.unversioned);
|
129
178
|
const document = yield* fs.readFileString(fullPath);
|
130
179
|
example = Example.make({
|
131
180
|
name,
|
@@ -135,90 +184,31 @@ export const scan = (options) => Effect.gen(function* () {
|
|
135
184
|
}),
|
136
185
|
});
|
137
186
|
}
|
138
|
-
else if (
|
139
|
-
//
|
140
|
-
const filePath = versions.get('default');
|
141
|
-
const fullPath = Path.join(options.dir, filePath);
|
142
|
-
const documentContent = yield* fs.readFileString(fullPath);
|
143
|
-
// Get all schema versions to map to this default document
|
144
|
-
const schemaVersions = options.schemaCatalog
|
145
|
-
? SchemaCatalog.fold((versioned) => SchemaCatalog.Versioned.getVersions(versioned), () => [])(options.schemaCatalog)
|
146
|
-
: [];
|
147
|
-
if (schemaVersions.length > 0) {
|
148
|
-
// Create a version set for all schema versions
|
149
|
-
const versionSet = HashSet.fromIterable(schemaVersions);
|
150
|
-
let versionDocuments = HashMap.empty();
|
151
|
-
versionDocuments = HashMap.set(versionDocuments, versionSet, documentContent);
|
152
|
-
example = Example.make({
|
153
|
-
name,
|
154
|
-
path: basePath,
|
155
|
-
document: Document.Versioned.make({
|
156
|
-
versionDocuments,
|
157
|
-
}),
|
158
|
-
});
|
159
|
-
}
|
160
|
-
else {
|
161
|
-
// No schema versions, treat as unversioned
|
162
|
-
example = Example.make({
|
163
|
-
name,
|
164
|
-
path: basePath,
|
165
|
-
document: Document.Unversioned.make({
|
166
|
-
document: documentContent,
|
167
|
-
}),
|
168
|
-
});
|
169
|
-
}
|
170
|
-
}
|
171
|
-
else {
|
172
|
-
// Versioned example - multiple files or versioned files
|
187
|
+
else if (HashMap.size(resolved.versionDocuments) > 0) {
|
188
|
+
// Versioned example - read all version documents
|
173
189
|
let versionDocuments = HashMap.empty();
|
174
|
-
let defaultDocument;
|
175
|
-
let explicitVersions = HashSet.empty(); // Track which versions have explicit files
|
176
190
|
const unknownVersions = [];
|
177
|
-
// Get available schema versions if catalog is provided
|
178
|
-
const schemaVersions = options.schemaCatalog
|
179
|
-
? SchemaCatalog.fold((versioned) => SchemaCatalog.Versioned.getVersions(versioned), () => [])(options.schemaCatalog)
|
180
|
-
: [];
|
181
|
-
// Create HashSet for O(1) lookups
|
182
191
|
const schemaVersionsSet = HashSet.fromIterable(schemaVersions);
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
if (version === 'default') {
|
188
|
-
defaultDocument = fileContent;
|
189
|
-
}
|
190
|
-
else if (version !== null) {
|
191
|
-
// Parse the version string
|
192
|
-
const parsedVersion = Version.decodeSync(version);
|
193
|
-
// Check if this version exists in the schema
|
194
|
-
const versionExists = HashSet.has(schemaVersionsSet, parsedVersion);
|
192
|
+
for (const [versionCoverage, filePath] of HashMap.entries(resolved.versionDocuments)) {
|
193
|
+
// Check if version is known (only for single versions, not sets)
|
194
|
+
if (Version.is(versionCoverage)) {
|
195
|
+
const versionExists = HashSet.has(schemaVersionsSet, versionCoverage);
|
195
196
|
if (options.schemaCatalog && schemaVersions.length > 0 && !versionExists) {
|
196
|
-
unknownVersions.push(
|
197
|
+
unknownVersions.push(versionCoverage);
|
197
198
|
// Create diagnostic for unknown version
|
198
199
|
diagnostics.push(makeDiagnosticUnknownVersion({
|
199
|
-
message: `Example "${name}" specifies version "${
|
200
|
+
message: `Example "${name}" specifies version "${Version.encodeSync(versionCoverage)}" which does not exist in the schema`,
|
200
201
|
example: { name, path: basePath },
|
201
|
-
version:
|
202
|
+
version: versionCoverage,
|
202
203
|
availableVersions: schemaVersions,
|
203
204
|
}));
|
204
205
|
// Skip this version - don't include it in the example
|
205
206
|
continue;
|
206
207
|
}
|
207
|
-
// We already have parsedVersion from above
|
208
|
-
versionDocuments = HashMap.set(versionDocuments, parsedVersion, fileContent);
|
209
|
-
explicitVersions = HashSet.add(explicitVersions, parsedVersion);
|
210
|
-
}
|
211
|
-
}
|
212
|
-
if (defaultDocument) {
|
213
|
-
// If we have a default, determine which versions it applies to
|
214
|
-
const defaultVersions = schemaVersions.filter(v => !HashSet.has(explicitVersions, v));
|
215
|
-
if (defaultVersions.length > 0) {
|
216
|
-
// Create a version set for the default document
|
217
|
-
const defaultVersionSet = defaultVersions.length === 1
|
218
|
-
? defaultVersions[0] // Single version
|
219
|
-
: HashSet.fromIterable(defaultVersions); // Version set
|
220
|
-
versionDocuments = HashMap.set(versionDocuments, defaultVersionSet, defaultDocument);
|
221
208
|
}
|
209
|
+
const fullPath = Path.join(options.dir, filePath);
|
210
|
+
const fileContent = yield* fs.readFileString(fullPath);
|
211
|
+
versionDocuments = HashMap.set(versionDocuments, versionCoverage, fileContent);
|
222
212
|
}
|
223
213
|
if (HashMap.size(versionDocuments) > 0) {
|
224
214
|
// Create versioned document
|
@@ -234,10 +224,6 @@ export const scan = (options) => Effect.gen(function* () {
|
|
234
224
|
// All versions were unknown, skip this example entirely
|
235
225
|
continue;
|
236
226
|
}
|
237
|
-
else {
|
238
|
-
// No versions at all - shouldn't happen
|
239
|
-
continue;
|
240
|
-
}
|
241
227
|
}
|
242
228
|
if (example) {
|
243
229
|
examples.push(example);
|