polen 0.11.0-next.23 → 0.11.0-next.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (192) hide show
  1. package/build/api/config/input.d.ts +76 -77
  2. package/build/api/config/input.d.ts.map +1 -1
  3. package/build/api/config/normalized.d.ts +136 -143
  4. package/build/api/config/normalized.d.ts.map +1 -1
  5. package/build/api/config-template/template.d.ts +110 -121
  6. package/build/api/config-template/template.d.ts.map +1 -1
  7. package/build/api/examples/diagnostic/diagnostic.d.ts +0 -23
  8. package/build/api/examples/diagnostic/diagnostic.d.ts.map +1 -1
  9. package/build/api/examples/diagnostic/diagnostic.js +1 -3
  10. package/build/api/examples/diagnostic/diagnostic.js.map +1 -1
  11. package/build/api/examples/scanner.d.ts +27 -1
  12. package/build/api/examples/scanner.d.ts.map +1 -1
  13. package/build/api/examples/scanner.js +19 -17
  14. package/build/api/examples/scanner.js.map +1 -1
  15. package/build/api/examples/schemas/catalog.d.ts +20 -12
  16. package/build/api/examples/schemas/catalog.d.ts.map +1 -1
  17. package/build/api/examples/schemas/example/example.d.ts +17 -11
  18. package/build/api/examples/schemas/example/example.d.ts.map +1 -1
  19. package/build/api/schema/augmentations/$$.d.ts +7 -0
  20. package/build/api/schema/augmentations/$$.d.ts.map +1 -0
  21. package/build/api/schema/augmentations/$$.js +7 -0
  22. package/build/api/schema/augmentations/$$.js.map +1 -0
  23. package/build/api/schema/augmentations/$.d.ts +1 -1
  24. package/build/api/schema/augmentations/$.d.ts.map +1 -1
  25. package/build/api/schema/augmentations/$.js +1 -1
  26. package/build/api/schema/augmentations/$.js.map +1 -1
  27. package/build/api/schema/augmentations/apply.d.ts +29 -0
  28. package/build/api/schema/augmentations/apply.d.ts.map +1 -0
  29. package/build/api/schema/augmentations/apply.js +181 -0
  30. package/build/api/schema/augmentations/apply.js.map +1 -0
  31. package/build/api/schema/augmentations/augmentation.d.ts +31 -0
  32. package/build/api/schema/augmentations/augmentation.d.ts.map +1 -0
  33. package/build/api/schema/augmentations/augmentation.js +22 -0
  34. package/build/api/schema/augmentations/augmentation.js.map +1 -0
  35. package/build/api/schema/augmentations/config.d.ts +24 -0
  36. package/build/api/schema/augmentations/config.d.ts.map +1 -0
  37. package/build/api/schema/augmentations/config.js +9 -0
  38. package/build/api/schema/augmentations/config.js.map +1 -0
  39. package/build/api/schema/augmentations/diagnostics/diagnostic.d.ts +67 -0
  40. package/build/api/schema/augmentations/diagnostics/diagnostic.d.ts.map +1 -0
  41. package/build/api/schema/augmentations/diagnostics/diagnostic.js +13 -0
  42. package/build/api/schema/augmentations/diagnostics/diagnostic.js.map +1 -0
  43. package/build/api/schema/augmentations/diagnostics/duplicate-version.d.ts +45 -0
  44. package/build/api/schema/augmentations/diagnostics/duplicate-version.d.ts.map +1 -0
  45. package/build/api/schema/augmentations/diagnostics/duplicate-version.js +17 -0
  46. package/build/api/schema/augmentations/diagnostics/duplicate-version.js.map +1 -0
  47. package/build/api/schema/augmentations/diagnostics/invalid-path.d.ts +46 -0
  48. package/build/api/schema/augmentations/diagnostics/invalid-path.d.ts.map +1 -0
  49. package/build/api/schema/augmentations/diagnostics/invalid-path.js +18 -0
  50. package/build/api/schema/augmentations/diagnostics/invalid-path.js.map +1 -0
  51. package/build/api/schema/augmentations/diagnostics/version-mismatch.d.ts +46 -0
  52. package/build/api/schema/augmentations/diagnostics/version-mismatch.d.ts.map +1 -0
  53. package/build/api/schema/augmentations/diagnostics/version-mismatch.js +18 -0
  54. package/build/api/schema/augmentations/diagnostics/version-mismatch.js.map +1 -0
  55. package/build/api/schema/augmentations/input.d.ts +145 -0
  56. package/build/api/schema/augmentations/input.d.ts.map +1 -0
  57. package/build/api/schema/augmentations/input.js +191 -0
  58. package/build/api/schema/augmentations/input.js.map +1 -0
  59. package/build/api/schema/augmentations/placement.d.ts +8 -0
  60. package/build/api/schema/augmentations/placement.d.ts.map +1 -0
  61. package/build/api/schema/augmentations/placement.js +7 -0
  62. package/build/api/schema/augmentations/placement.js.map +1 -0
  63. package/build/api/schema/config-schema.d.ts +66 -66
  64. package/build/api/schema/config-schema.d.ts.map +1 -1
  65. package/build/api/schema/config-schema.js +2 -2
  66. package/build/api/schema/config-schema.js.map +1 -1
  67. package/build/api/schema/input-source/load.d.ts +2 -0
  68. package/build/api/schema/input-source/load.d.ts.map +1 -1
  69. package/build/api/schema/input-source/load.js.map +1 -1
  70. package/build/api/schema/input-sources/directory.d.ts +39 -39
  71. package/build/api/schema/input-sources/file.d.ts +39 -39
  72. package/build/api/schema/input-sources/introspection-file.d.ts +39 -39
  73. package/build/api/schema/input-sources/introspection.d.ts +39 -39
  74. package/build/api/schema/input-sources/memory.d.ts +39 -39
  75. package/build/api/schema/input-sources/versioned-directory.d.ts +79 -79
  76. package/build/api/schema/load.d.ts.map +1 -1
  77. package/build/api/schema/load.js +9 -2
  78. package/build/api/schema/load.js.map +1 -1
  79. package/build/lib/catalog/catalog.d.ts +1181 -1181
  80. package/build/lib/catalog/unversioned.d.ts +312 -312
  81. package/build/lib/catalog/versioned.d.ts +634 -634
  82. package/build/lib/change/change.d.ts +238 -238
  83. package/build/lib/document/document.d.ts +14 -8
  84. package/build/lib/document/document.d.ts.map +1 -1
  85. package/build/lib/document/versioned.d.ts +17 -10
  86. package/build/lib/document/versioned.d.ts.map +1 -1
  87. package/build/lib/grafaid/schema/KindMap/_.d.ts +1 -1
  88. package/build/lib/graphql-path/$$.d.ts +7 -13
  89. package/build/lib/graphql-path/$$.d.ts.map +1 -1
  90. package/build/lib/graphql-path/$$.js +7 -13
  91. package/build/lib/graphql-path/$$.js.map +1 -1
  92. package/build/lib/graphql-path/definition.d.ts +104 -94
  93. package/build/lib/graphql-path/definition.d.ts.map +1 -1
  94. package/build/lib/graphql-path/definition.js +126 -125
  95. package/build/lib/graphql-path/definition.js.map +1 -1
  96. package/build/lib/graphql-path/query.d.ts +25 -57
  97. package/build/lib/graphql-path/query.d.ts.map +1 -1
  98. package/build/lib/graphql-path/query.js +15 -93
  99. package/build/lib/graphql-path/query.js.map +1 -1
  100. package/build/lib/graphql-path/schema.d.ts +49 -0
  101. package/build/lib/graphql-path/schema.d.ts.map +1 -0
  102. package/build/lib/graphql-path/schema.js +89 -0
  103. package/build/lib/graphql-path/schema.js.map +1 -0
  104. package/build/lib/graphql-path/types.d.ts +76 -28
  105. package/build/lib/graphql-path/types.d.ts.map +1 -1
  106. package/build/lib/graphql-path/types.js +101 -2
  107. package/build/lib/graphql-path/types.js.map +1 -1
  108. package/build/lib/revision/revision.d.ts +1170 -1170
  109. package/build/lib/schema/schema.d.ts +708 -708
  110. package/build/lib/schema/unversioned.d.ts +1092 -1092
  111. package/build/lib/schema/versioned.d.ts +634 -634
  112. package/build/lib/semver/official-release.d.ts +10 -10
  113. package/build/lib/semver/pre-release.d.ts +10 -10
  114. package/build/lib/semver/semver.d.ts +50 -50
  115. package/build/lib/version-coverage/version-coverage.d.ts +43 -11
  116. package/build/lib/version-coverage/version-coverage.d.ts.map +1 -1
  117. package/build/lib/version-coverage/version-coverage.js +40 -6
  118. package/build/lib/version-coverage/version-coverage.js.map +1 -1
  119. package/build/template/hooks/use-examples.d.ts +1 -1
  120. package/build/template/routes/changelog/ChangelogSidebar.d.ts +2 -2
  121. package/build/template/routes/changelog/ChangelogSidebar.d.ts.map +1 -1
  122. package/build/template/routes/changelog/ChangelogSidebar.js +4 -4
  123. package/build/template/routes/changelog/ChangelogSidebar.js.map +1 -1
  124. package/build/template/routes/examples/_.d.ts +3 -3
  125. package/build/template/routes/examples/_index.d.ts +2 -2
  126. package/build/template/routes/examples/name.d.ts +3 -3
  127. package/build/template/routes/pages.d.ts.map +1 -1
  128. package/build/template/routes/pages.js +5 -1
  129. package/build/template/routes/pages.js.map +1 -1
  130. package/build/template/stores/changelog.d.ts +39 -39
  131. package/build/vite/plugins/examples.d.ts.map +1 -1
  132. package/build/vite/plugins/examples.js +0 -2
  133. package/build/vite/plugins/examples.js.map +1 -1
  134. package/build/vite/plugins/schemas.d.ts.map +1 -1
  135. package/build/vite/plugins/schemas.js +38 -2
  136. package/build/vite/plugins/schemas.js.map +1 -1
  137. package/package.json +1 -1
  138. package/src/api/examples/diagnostic/diagnostic.ts +0 -3
  139. package/src/api/examples/scanner.test.ts +83 -0
  140. package/src/api/examples/scanner.ts +17 -21
  141. package/src/api/schema/augmentations/$$.ts +6 -0
  142. package/src/api/schema/augmentations/$.ts +1 -1
  143. package/src/api/schema/augmentations/apply.test.ts +89 -0
  144. package/src/api/schema/augmentations/apply.ts +277 -0
  145. package/src/api/schema/augmentations/augmentation.ts +24 -0
  146. package/src/api/schema/augmentations/config.ts +11 -0
  147. package/src/api/schema/augmentations/diagnostics/diagnostic.ts +20 -0
  148. package/src/api/schema/augmentations/diagnostics/duplicate-version.ts +20 -0
  149. package/src/api/schema/augmentations/diagnostics/invalid-path.ts +21 -0
  150. package/src/api/schema/augmentations/diagnostics/version-mismatch.ts +21 -0
  151. package/src/api/schema/augmentations/input.test.ts +144 -0
  152. package/src/api/schema/augmentations/input.ts +215 -0
  153. package/src/api/schema/augmentations/placement.ts +11 -0
  154. package/src/api/schema/config-schema.ts +2 -2
  155. package/src/api/schema/input-source/load.ts +2 -0
  156. package/src/api/schema/load.ts +19 -2
  157. package/src/lib/graphql-path/$$.ts +7 -13
  158. package/src/lib/graphql-path/$.test.ts +175 -0
  159. package/src/lib/graphql-path/definition.ts +162 -162
  160. package/src/lib/graphql-path/query.ts +15 -98
  161. package/src/lib/graphql-path/schema.ts +136 -0
  162. package/src/lib/graphql-path/types.ts +108 -28
  163. package/src/lib/version-coverage/version-coverage.ts +48 -6
  164. package/src/template/routes/changelog/ChangelogSidebar.tsx +4 -4
  165. package/src/template/routes/pages.tsx +6 -1
  166. package/src/vite/plugins/examples.ts +0 -2
  167. package/src/vite/plugins/schemas.ts +51 -2
  168. package/build/api/examples/diagnostic/unused-default.d.ts +0 -49
  169. package/build/api/examples/diagnostic/unused-default.d.ts.map +0 -1
  170. package/build/api/examples/diagnostic/unused-default.js +0 -19
  171. package/build/api/examples/diagnostic/unused-default.js.map +0 -1
  172. package/build/api/schema/augmentations/augmentations/description.d.ts +0 -26
  173. package/build/api/schema/augmentations/augmentations/description.d.ts.map +0 -1
  174. package/build/api/schema/augmentations/augmentations/description.js +0 -55
  175. package/build/api/schema/augmentations/augmentations/description.js.map +0 -1
  176. package/build/api/schema/augmentations/schema-augmentation.d.ts +0 -20
  177. package/build/api/schema/augmentations/schema-augmentation.d.ts.map +0 -1
  178. package/build/api/schema/augmentations/schema-augmentation.js +0 -22
  179. package/build/api/schema/augmentations/schema-augmentation.js.map +0 -1
  180. package/build/api/schema/augmentations/target.d.ts +0 -25
  181. package/build/api/schema/augmentations/target.d.ts.map +0 -1
  182. package/build/api/schema/augmentations/target.js +0 -39
  183. package/build/api/schema/augmentations/target.js.map +0 -1
  184. package/build/lib/graphql-path/constructors.d.ts +0 -57
  185. package/build/lib/graphql-path/constructors.d.ts.map +0 -1
  186. package/build/lib/graphql-path/constructors.js +0 -73
  187. package/build/lib/graphql-path/constructors.js.map +0 -1
  188. package/src/api/examples/diagnostic/unused-default.ts +0 -22
  189. package/src/api/schema/augmentations/augmentations/description.ts +0 -69
  190. package/src/api/schema/augmentations/schema-augmentation.ts +0 -32
  191. package/src/api/schema/augmentations/target.ts +0 -61
  192. package/src/lib/graphql-path/constructors.ts +0 -81
@@ -1,73 +1,153 @@
1
1
  /**
2
- * Definition path operations
3
- */
4
-
5
- import { createArgumentSegment, createFieldSegment, createTypeSegment } from './constructors.js'
6
-
7
- import type { ArgumentSegment, FieldSegment, TypeSegment } from '#lib/graphql-path/types'
8
-
9
- /**
10
- * Encode a definition path to a human-readable expression string
11
- *
12
- * @param path - The definition path to encode
13
- * @returns A string expression representation
14
- * @example
15
- * encode(field('User', 'name')) // 'User.name'
16
- * encode(argument('User', 'posts', 'limit')) // 'User.posts(limit)'
17
- */
18
- export const encode = (path: DefinitionPath): string => {
19
- if (isTypeDefinitionPath(path)) {
20
- return path[0].type
21
- } else if (isFieldDefinitionPath(path)) {
22
- return `${path[0].type}.${path[1].field}`
23
- } else if (isArgumentDefinitionPath(path)) {
24
- return `${path[0].type}.${path[1].field}(${path[2].argument})`
25
- }
26
- return ''
27
- }
2
+ * Definition path operations using Effect Schema transforms
3
+ */
4
+
5
+ import { S } from '#lib/kit-temp/effect'
6
+ import { ParseResult } from 'effect'
7
+ import { ArgumentSegment, FieldSegment, TypeSegment } from './types.js'
8
+
9
+ // ============================================================================
10
+ // Internal Path Schemas (Decoded Forms)
11
+ // ============================================================================
12
+
13
+ const TypeDefinitionPathDecoded = S.Tuple(TypeSegment)
14
+ const FieldDefinitionPathDecoded = S.Tuple(TypeSegment, FieldSegment)
15
+ const ArgumentDefinitionPathDecoded = S.Tuple(TypeSegment, FieldSegment, ArgumentSegment)
16
+
17
+ // ============================================================================
18
+ // Transform Codecs (String <-> Struct)
19
+ // ============================================================================
20
+
21
+ /**
22
+ * Type definition path codec
23
+ * Encoded: "User"
24
+ * Decoded: [{ _tag: 'TypeSegment', type: 'User' }]
25
+ */
26
+ export const TypeDefinitionPath = S.transformOrFail(
27
+ S.String,
28
+ TypeDefinitionPathDecoded,
29
+ {
30
+ decode: (str, _options, ast) => {
31
+ if (!str || str.includes('.') || str.includes('(')) {
32
+ return ParseResult.fail(new ParseResult.Type(ast, str))
33
+ }
34
+ return ParseResult.succeed([TypeSegment.make({ type: str })])
35
+ },
36
+ encode: (path) => ParseResult.succeed(path[0].type),
37
+ },
38
+ ).annotations({
39
+ identifier: 'TypeDefinitionPath',
40
+ description: 'Path to a type definition',
41
+ })
42
+
43
+ /**
44
+ * Field definition path codec
45
+ * Encoded: "User.name"
46
+ * Decoded: [{ _tag: 'TypeSegment', type: 'User' }, { _tag: 'FieldSegment', field: 'name' }]
47
+ */
48
+ export const FieldDefinitionPath = S.transformOrFail(
49
+ S.String,
50
+ FieldDefinitionPathDecoded,
51
+ {
52
+ decode: (str, _options, ast) => {
53
+ const parts = str.split('.')
54
+ if (parts.length !== 2 || !parts[0] || !parts[1] || str.includes('(')) {
55
+ return ParseResult.fail(new ParseResult.Type(ast, str))
56
+ }
57
+ return ParseResult.succeed([
58
+ TypeSegment.make({ type: parts[0] }),
59
+ FieldSegment.make({ field: parts[1] }),
60
+ ])
61
+ },
62
+ encode: (path) => ParseResult.succeed(`${path[0].type}.${path[1].field}`),
63
+ },
64
+ ).annotations({
65
+ identifier: 'FieldDefinitionPath',
66
+ description: 'Path to a field definition',
67
+ })
68
+
69
+ /**
70
+ * Argument definition path codec
71
+ * Encoded: "User.posts(limit)"
72
+ * Decoded: [{ _tag: 'TypeSegment', type: 'User' }, { _tag: 'FieldSegment', field: 'posts' }, { _tag: 'ArgumentSegment', argument: 'limit' }]
73
+ */
74
+ export const ArgumentDefinitionPath = S.transformOrFail(
75
+ S.String,
76
+ ArgumentDefinitionPathDecoded,
77
+ {
78
+ decode: (str, _options, ast) => {
79
+ const match = str.match(/^([^.]+)\.([^.(]+)\(([^)]+)\)$/)
80
+ if (!match || !match[1] || !match[2] || !match[3]) {
81
+ return ParseResult.fail(new ParseResult.Type(ast, str))
82
+ }
83
+ return ParseResult.succeed([
84
+ TypeSegment.make({ type: match[1] }),
85
+ FieldSegment.make({ field: match[2] }),
86
+ ArgumentSegment.make({ argument: match[3] }),
87
+ ])
88
+ },
89
+ encode: (path) => ParseResult.succeed(`${path[0].type}.${path[1].field}(${path[2].argument})`),
90
+ },
91
+ ).annotations({
92
+ identifier: 'ArgumentDefinitionPath',
93
+ description: 'Path to an argument definition',
94
+ })
95
+
96
+ /**
97
+ * Union of all definition paths
98
+ * Automatically determines the correct path type from the string format
99
+ */
100
+ export const DefinitionPath = S.Union(
101
+ ArgumentDefinitionPath, // Check argument first (most specific)
102
+ FieldDefinitionPath, // Then field
103
+ TypeDefinitionPath, // Then type (least specific)
104
+ ).annotations({
105
+ identifier: 'DefinitionPath',
106
+ description: 'Union of all definition path types',
107
+ })
108
+
109
+ // ============================================================================
110
+ // Type Exports
111
+ // ============================================================================
112
+
113
+ export type TypeDefinitionPath = S.Schema.Type<typeof TypeDefinitionPath>
114
+ export type FieldDefinitionPath = S.Schema.Type<typeof FieldDefinitionPath>
115
+ export type ArgumentDefinitionPath = S.Schema.Type<typeof ArgumentDefinitionPath>
116
+ export type DefinitionPath = S.Schema.Type<typeof DefinitionPath>
117
+
118
+ // ============================================================================
119
+ // Codec Functions
120
+ // ============================================================================
28
121
 
29
122
  /**
30
123
  * Decode a string expression into a definition path
31
- *
32
124
  * @param expression - The string expression to decode
33
- * @returns The decoded definition path or null if invalid
125
+ * @returns The decoded definition path
34
126
  * @example
35
127
  * decode('User') // type definition path
36
128
  * decode('User.name') // field definition path
37
129
  * decode('User.posts(limit)') // argument definition path
38
130
  */
39
- export const decode = (expression: string): DefinitionPath | null => {
40
- // Handle argument path: Type.field(argument)
41
- const argMatch = expression.match(/^([^.]+)\.([^.(]+)\(([^)]+)\)$/)
42
- if (argMatch) {
43
- const [, typeName, fieldName, argName] = argMatch
44
- if (!typeName || !fieldName || !argName) return null
45
- return createArgumentDefinitionPath(typeName, fieldName, argName)
46
- }
47
-
48
- // Handle field path: Type.field
49
- const fieldMatch = expression.match(/^([^.]+)\.([^.]+)$/)
50
- if (fieldMatch) {
51
- const [, typeName, fieldName] = fieldMatch
52
- if (!typeName || !fieldName) return null
53
- return createFieldDefinitionPath(typeName, fieldName)
54
- }
55
-
56
- // Handle type path: Type
57
- const typeMatch = expression.match(/^[^.]+$/)
58
- if (typeMatch) {
59
- return createTypeDefinitionPath(expression)
60
- }
61
-
62
- return null
63
- }
131
+ export const decodeSync = S.decodeUnknownSync(DefinitionPath)
132
+
133
+ /**
134
+ * Encode a definition path to a string expression
135
+ * @param path - The definition path to encode
136
+ * @returns A string expression representation
137
+ * @example
138
+ * encode([{ _tag: 'TypeSegment', type: 'User' }]) // 'User'
139
+ * encode([{ _tag: 'TypeSegment', type: 'User' }, { _tag: 'FieldSegment', field: 'name' }]) // 'User.name'
140
+ */
141
+ export const encodeSync = S.encodeSync(DefinitionPath)
142
+
143
+ // ============================================================================
144
+ // Helper Functions
145
+ // ============================================================================
64
146
 
65
147
  /**
66
148
  * Extract the type name from any definition path
67
- *
68
149
  * @param path - The definition path
69
150
  * @returns The type name
70
- * @example getType([{ kind: 'type', type: 'User' }]) // 'User'
71
151
  */
72
152
  export const getType = (path: DefinitionPath): string => {
73
153
  return path[0].type
@@ -75,10 +155,8 @@ export const getType = (path: DefinitionPath): string => {
75
155
 
76
156
  /**
77
157
  * Extract the field name from a field or argument definition path
78
- *
79
158
  * @param path - The field or argument definition path
80
159
  * @returns The field name
81
- * @example getField([{ kind: 'type', type: 'User' }, { kind: 'field', field: 'name' }]) // 'name'
82
160
  */
83
161
  export const getField = (path: FieldDefinitionPath | ArgumentDefinitionPath): string => {
84
162
  return path[1].field
@@ -86,155 +164,77 @@ export const getField = (path: FieldDefinitionPath | ArgumentDefinitionPath): st
86
164
 
87
165
  /**
88
166
  * Extract the argument name from an argument definition path
89
- *
90
167
  * @param path - The argument definition path
91
168
  * @returns The argument name
92
- * @example getArgument([{ kind: 'type', type: 'User' }, { kind: 'field', field: 'posts' }, { kind: 'argument', argument: 'limit' }]) // 'limit'
93
169
  */
94
170
  export const getArgument = (path: ArgumentDefinitionPath): string => {
95
171
  return path[2].argument
96
172
  }
97
173
 
98
- /**
99
- * Parse field path like "User.email" into type and field names
100
- */
101
- export const parseFieldPath = (path?: string): { typeName: string | null; fieldName: string | null } => {
102
- if (!path) return { typeName: null, fieldName: null }
103
-
104
- const parts = path.split('.')
105
- if (parts.length >= 2) {
106
- return {
107
- typeName: parts[0] || null,
108
- fieldName: parts[1] || null,
109
- }
110
- }
111
-
112
- return { typeName: null, fieldName: null }
113
- }
114
-
115
- /**
116
- * Definition paths - direct paths to schema definition elements
117
- * These represent the "address" of a specific schema element
118
- */
119
- export type DefinitionPath =
120
- | TypeDefinitionPath
121
- | FieldDefinitionPath
122
- | ArgumentDefinitionPath
123
-
124
- /**
125
- * Path to a type definition
126
- * @example [{ kind: 'type', type: 'User' }]
127
- */
128
- export type TypeDefinitionPath = [TypeSegment]
129
-
130
- /**
131
- * Path to a field definition (type + field)
132
- * @example [{ kind: 'type', type: 'User' }, { kind: 'field', field: 'name' }]
133
- */
134
- export type FieldDefinitionPath = [TypeSegment, FieldSegment]
135
-
136
- /**
137
- * Path to an argument definition (type + field + argument)
138
- * @example [{ kind: 'type', type: 'User' }, { kind: 'field', field: 'posts' }, { kind: 'argument', argument: 'limit' }]
139
- */
140
- export type ArgumentDefinitionPath = [TypeSegment, FieldSegment, ArgumentSegment]
174
+ // ============================================================================
175
+ // Type Guards
176
+ // ============================================================================
141
177
 
142
178
  /**
143
179
  * Type guard to check if a path is a type definition path
144
- *
145
- * @param path - The path to check
146
- * @returns True if the path is a type definition path
147
180
  */
148
181
  export const isTypeDefinitionPath = (path: DefinitionPath): path is TypeDefinitionPath => {
149
- return path.length === 1 && path[0].kind === 'type'
182
+ return path.length === 1 && path[0]._tag === 'TypeSegment'
150
183
  }
151
184
 
152
185
  /**
153
186
  * Type guard to check if a path is a field definition path
154
- *
155
- * @param path - The path to check
156
- * @returns True if the path is a field definition path
157
187
  */
158
188
  export const isFieldDefinitionPath = (path: DefinitionPath): path is FieldDefinitionPath => {
159
- return path.length === 2 && path[0].kind === 'type' && path[1].kind === 'field'
189
+ return path.length === 2 && path[0]._tag === 'TypeSegment' && path[1]._tag === 'FieldSegment'
160
190
  }
161
191
 
162
192
  /**
163
193
  * Type guard to check if a path is an argument definition path
164
- *
165
- * @param path - The path to check
166
- * @returns True if the path is an argument definition path
167
194
  */
168
195
  export const isArgumentDefinitionPath = (path: DefinitionPath): path is ArgumentDefinitionPath => {
169
- return path.length === 3 && path[0].kind === 'type' && path[1].kind === 'field' && path[2].kind === 'argument'
170
- }
171
-
172
- /**
173
- * Create a path to a type definition
174
- *
175
- * @param type - The type name
176
- * @returns A type definition path
177
- * @example createTypeDefinitionPath('User') // [{ kind: 'type', type: 'User' }]
178
- */
179
- export const createTypeDefinitionPath = (type: string): TypeDefinitionPath => {
180
- return [createTypeSegment(type)]
181
- }
182
-
183
- /**
184
- * Create a path to a field definition
185
- *
186
- * @param type - The type name
187
- * @param field - The field name
188
- * @returns A field definition path
189
- * @example createFieldDefinitionPath('User', 'name') // [{ kind: 'type', type: 'User' }, { kind: 'field', field: 'name' }]
190
- */
191
- export const createFieldDefinitionPath = (type: string, field: string): FieldDefinitionPath => {
192
- return [createTypeSegment(type), createFieldSegment(field)]
196
+ return (
197
+ path.length === 3
198
+ && path[0]._tag === 'TypeSegment'
199
+ && path[1]._tag === 'FieldSegment'
200
+ && path[2]._tag === 'ArgumentSegment'
201
+ )
193
202
  }
194
203
 
195
- /**
196
- * Create a path to an argument definition
197
- *
198
- * @param type - The type name
199
- * @param field - The field name
200
- * @param argument - The argument name
201
- * @returns An argument definition path
202
- * @example createArgumentDefinitionPath('User', 'posts', 'limit') // [{ kind: 'type', type: 'User' }, { kind: 'field', field: 'posts' }, { kind: 'argument', argument: 'limit' }]
203
- */
204
- export const createArgumentDefinitionPath = (
205
- type: string,
206
- field: string,
207
- argument: string,
208
- ): ArgumentDefinitionPath => {
209
- return [createTypeSegment(type), createFieldSegment(field), createArgumentSegment(argument)]
210
- }
204
+ // ============================================================================
205
+ // Constructor Functions
206
+ // ============================================================================
211
207
 
212
208
  /**
213
209
  * Create a type definition path
214
- *
215
210
  * @param type - The type name
216
211
  * @returns A type definition path
217
- * @example type('User') // [{ kind: 'type', type: 'User' }]
218
212
  */
219
- export const type = createTypeDefinitionPath
213
+ export const type = (typeName: string): TypeDefinitionPath => {
214
+ return [TypeSegment.make({ type: typeName })]
215
+ }
220
216
 
221
217
  /**
222
218
  * Create a field definition path
223
- *
224
219
  * @param type - The type name
225
220
  * @param field - The field name
226
221
  * @returns A field definition path
227
- * @example field('User', 'name') // [{ kind: 'type', type: 'User' }, { kind: 'field', field: 'name' }]
228
222
  */
229
- export const field = createFieldDefinitionPath
223
+ export const field = (typeName: string, fieldName: string): FieldDefinitionPath => {
224
+ return [TypeSegment.make({ type: typeName }), FieldSegment.make({ field: fieldName })]
225
+ }
230
226
 
231
227
  /**
232
228
  * Create an argument definition path
233
- *
234
229
  * @param type - The type name
235
230
  * @param field - The field name
236
231
  * @param argument - The argument name
237
232
  * @returns An argument definition path
238
- * @example argument('User', 'posts', 'limit') // [{ kind: 'type', type: 'User' }, { kind: 'field', field: 'posts' }, { kind: 'argument', argument: 'limit' }]
239
233
  */
240
- export const argument = createArgumentDefinitionPath
234
+ export const argument = (typeName: string, fieldName: string, argumentName: string): ArgumentDefinitionPath => {
235
+ return [
236
+ TypeSegment.make({ type: typeName }),
237
+ FieldSegment.make({ field: fieldName }),
238
+ ArgumentSegment.make({ argument: argumentName }),
239
+ ]
240
+ }
@@ -2,117 +2,34 @@
2
2
  * Query path operations
3
3
  */
4
4
 
5
- import { createFieldSegment, createTypeSegment } from './constructors.js'
6
- import type { QueryPath, QuerySegment } from './types.js'
7
-
8
- /**
9
- * Builder class for creating query paths with a fluent interface
10
- *
11
- * @example
12
- * ```ts
13
- * const path = builder()
14
- * .type('User')
15
- * .field('posts')
16
- * .type('Post')
17
- * .field('author')
18
- * .build()
19
- * ```
20
- */
21
- export class QueryPathBuilder {
22
- private segments: QuerySegment[] = []
23
-
24
- /**
25
- * Add a type segment to the path
26
- *
27
- * @param typeName - The type name
28
- * @returns The builder for chaining
29
- */
30
- type(typeName: string): this {
31
- this.segments.push(createTypeSegment(typeName))
32
- return this
33
- }
34
-
35
- /**
36
- * Add a field segment to the path
37
- *
38
- * @param fieldName - The field name
39
- * @returns The builder for chaining
40
- */
41
- field(fieldName: string): this {
42
- this.segments.push(createFieldSegment(fieldName))
43
- return this
44
- }
45
-
46
- /**
47
- * Build the final query path
48
- *
49
- * @returns The constructed query path
50
- */
51
- build(): QueryPath {
52
- return this.segments
53
- }
54
- }
55
-
56
- /**
57
- * Create a new query path builder
58
- *
59
- * @returns A new query path builder instance
60
- * @example
61
- * ```ts
62
- * const path = builder()
63
- * .type('User')
64
- * .field('posts')
65
- * .type('Post')
66
- * .field('author')
67
- * .build()
68
- * ```
69
- */
70
- export const builder = (): QueryPathBuilder => new QueryPathBuilder()
5
+ import { S } from '#lib/kit-temp/effect'
6
+ import { QueryPath } from './types.js'
71
7
 
72
8
  /**
73
9
  * Encode a query path to a human-readable expression string
10
+ * Uses the Effect Schema codec for QueryPath
74
11
  *
75
- * @param path - The query path to encode
12
+ * @param path - The query path segments to encode
76
13
  * @returns A string expression representation
77
14
  * @example
78
- * encode(builder().type('User').field('posts').type('Post').field('title').build()) // 'User.posts.Post.title'
15
+ * encode([
16
+ * { _tag: 'TypeSegment', type: 'User' },
17
+ * { _tag: 'FieldSegment', field: 'posts' },
18
+ * { _tag: 'TypeSegment', type: 'Post' },
19
+ * { _tag: 'FieldSegment', field: 'title' }
20
+ * ]) // 'User.posts.Post.title'
79
21
  */
80
- export const encode = (path: QueryPath): string => {
81
- return path.map(segment => {
82
- if (segment.kind === 'type') return segment.type
83
- if (segment.kind === 'field') return segment.field
84
- return ''
85
- }).filter(Boolean).join('.')
86
- }
22
+ export const encode = S.encodeSync(QueryPath)
87
23
 
88
24
  /**
89
25
  * Decode a string expression into a query path
26
+ * Uses the Effect Schema codec for QueryPath
90
27
  * Note: This assumes alternating type.field.type.field pattern
91
28
  *
92
29
  * @param expression - The string expression to decode
93
- * @returns The decoded query path or null if invalid
30
+ * @returns The decoded query path segments
31
+ * @throws ParseError if the expression is invalid
94
32
  * @example
95
33
  * decode('User.posts.Post.title') // Query path traversing User->posts->Post->title
96
34
  */
97
- export const decode = (expression: string): QueryPath | null => {
98
- if (!expression) return null
99
-
100
- const parts = expression.split('.')
101
- const segments: QuerySegment[] = []
102
-
103
- // Assume alternating pattern: type.field.type.field...
104
- for (let i = 0; i < parts.length; i++) {
105
- const part = parts[i]
106
- if (!part) continue
107
-
108
- if (i % 2 === 0) {
109
- // Even indices are types
110
- segments.push(createTypeSegment(part))
111
- } else {
112
- // Odd indices are fields
113
- segments.push(createFieldSegment(part))
114
- }
115
- }
116
-
117
- return segments
118
- }
35
+ export const decode = S.decodeUnknownSync(QueryPath)
@@ -0,0 +1,136 @@
1
+ /**
2
+ * GraphQL schema location utilities for definition paths
3
+ */
4
+
5
+ import { Grafaid } from '#lib/grafaid'
6
+ import { Data, Either, Match } from 'effect'
7
+ import * as Definition from './definition.js'
8
+
9
+ // ============================================================================
10
+ // Errors
11
+ // ============================================================================
12
+
13
+ export class TypeNotFoundError extends Data.TaggedError('TypeNotFoundError')<{
14
+ typeName: string
15
+ path: string
16
+ }> {}
17
+
18
+ export class FieldNotFoundError extends Data.TaggedError('FieldNotFoundError')<{
19
+ typeName: string
20
+ fieldName: string
21
+ path: string
22
+ }> {}
23
+
24
+ // ============================================================================
25
+ // Locate Functions
26
+ // ============================================================================
27
+
28
+ /**
29
+ * Locate a type in the GraphQL schema from a type definition path.
30
+ *
31
+ * @param schema - The GraphQL schema
32
+ * @param path - The type definition path
33
+ * @returns Either the located type or a TypeNotFoundError
34
+ */
35
+ export const locateType = (
36
+ schema: Grafaid.Schema.Schema,
37
+ path: Definition.TypeDefinitionPath,
38
+ ): Either.Either<Grafaid.Schema.TypesLike.Named, TypeNotFoundError> => {
39
+ const typeName = Definition.getType(path)
40
+ const type = schema.getType(typeName)
41
+ if (!type) {
42
+ return Either.left(
43
+ new TypeNotFoundError({
44
+ typeName,
45
+ path: Definition.encodeSync(path),
46
+ }),
47
+ )
48
+ }
49
+ return Either.right(type)
50
+ }
51
+
52
+ /**
53
+ * Locate a field in the GraphQL schema from a field definition path.
54
+ *
55
+ * @param schema - The GraphQL schema
56
+ * @param path - The field definition path
57
+ * @returns Either the located field or a FieldNotFoundError
58
+ */
59
+ export const locateField = (
60
+ schema: Grafaid.Schema.Schema,
61
+ path: Definition.FieldDefinitionPath,
62
+ ): Either.Either<Grafaid.Schema.NodesLike.Field, FieldNotFoundError> => {
63
+ const typeName = Definition.getType(path)
64
+ const fieldName = Definition.getField(path)
65
+
66
+ const type = schema.getType(typeName)
67
+ if (!type) {
68
+ return Either.left(
69
+ new FieldNotFoundError({
70
+ typeName,
71
+ fieldName,
72
+ path: Definition.encodeSync(path),
73
+ }),
74
+ )
75
+ }
76
+
77
+ if (!Grafaid.Schema.TypesLike.isFielded(type)) {
78
+ return Either.left(
79
+ new FieldNotFoundError({
80
+ typeName,
81
+ fieldName,
82
+ path: Definition.encodeSync(path),
83
+ }),
84
+ )
85
+ }
86
+
87
+ const fields = type.getFields()
88
+ const field = fields[fieldName]
89
+
90
+ if (!field) {
91
+ // dprint-ignore
92
+ return Either.left(new FieldNotFoundError({
93
+ typeName,
94
+ fieldName,
95
+ path: Definition.encodeSync(path),
96
+ }))
97
+ }
98
+
99
+ return Either.right(field)
100
+ }
101
+
102
+ /**
103
+ * Locate a type or field in the GraphQL schema from a definition path.
104
+ *
105
+ * @param schema - The GraphQL schema
106
+ * @param path - The definition path (type or field)
107
+ * @returns Either the located type/field or an error
108
+ */
109
+ export const locate = (
110
+ schema: Grafaid.Schema.Schema,
111
+ path: Definition.DefinitionPath,
112
+ ): Either.Either<
113
+ Grafaid.Schema.TypesLike.Named | Grafaid.Schema.NodesLike.Field,
114
+ TypeNotFoundError | FieldNotFoundError
115
+ > => {
116
+ return Match.value(path).pipe(
117
+ Match.when(
118
+ Definition.isTypeDefinitionPath,
119
+ (p) => locateType(schema, p),
120
+ ),
121
+ Match.when(
122
+ Definition.isFieldDefinitionPath,
123
+ (p) => locateField(schema, p),
124
+ ),
125
+ Match.orElse(() => {
126
+ // This should never happen with proper path types
127
+ // Return a generic error for unsupported path types
128
+ return Either.left(
129
+ new TypeNotFoundError({
130
+ typeName: 'unknown',
131
+ path: Definition.encodeSync(path),
132
+ }),
133
+ )
134
+ }),
135
+ )
136
+ }