@rejot-dev/thalo 0.0.0

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 (237) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +396 -0
  3. package/dist/ast/ast-types.d.ts +469 -0
  4. package/dist/ast/ast-types.d.ts.map +1 -0
  5. package/dist/ast/ast-types.js +11 -0
  6. package/dist/ast/ast-types.js.map +1 -0
  7. package/dist/ast/builder.js +158 -0
  8. package/dist/ast/builder.js.map +1 -0
  9. package/dist/ast/extract.js +748 -0
  10. package/dist/ast/extract.js.map +1 -0
  11. package/dist/ast/node-at-position.d.ts +147 -0
  12. package/dist/ast/node-at-position.d.ts.map +1 -0
  13. package/dist/ast/node-at-position.js +382 -0
  14. package/dist/ast/node-at-position.js.map +1 -0
  15. package/dist/ast/visitor.js +232 -0
  16. package/dist/ast/visitor.js.map +1 -0
  17. package/dist/checker/check.d.ts +53 -0
  18. package/dist/checker/check.d.ts.map +1 -0
  19. package/dist/checker/check.js +105 -0
  20. package/dist/checker/check.js.map +1 -0
  21. package/dist/checker/rules/actualize-missing-updated.js +34 -0
  22. package/dist/checker/rules/actualize-missing-updated.js.map +1 -0
  23. package/dist/checker/rules/actualize-unresolved-target.js +42 -0
  24. package/dist/checker/rules/actualize-unresolved-target.js.map +1 -0
  25. package/dist/checker/rules/alter-before-define.js +53 -0
  26. package/dist/checker/rules/alter-before-define.js.map +1 -0
  27. package/dist/checker/rules/alter-undefined-entity.js +32 -0
  28. package/dist/checker/rules/alter-undefined-entity.js.map +1 -0
  29. package/dist/checker/rules/create-requires-section.js +34 -0
  30. package/dist/checker/rules/create-requires-section.js.map +1 -0
  31. package/dist/checker/rules/define-entity-requires-section.js +31 -0
  32. package/dist/checker/rules/define-entity-requires-section.js.map +1 -0
  33. package/dist/checker/rules/duplicate-entity-definition.js +37 -0
  34. package/dist/checker/rules/duplicate-entity-definition.js.map +1 -0
  35. package/dist/checker/rules/duplicate-field-in-schema.js +38 -0
  36. package/dist/checker/rules/duplicate-field-in-schema.js.map +1 -0
  37. package/dist/checker/rules/duplicate-link-id.js +52 -0
  38. package/dist/checker/rules/duplicate-link-id.js.map +1 -0
  39. package/dist/checker/rules/duplicate-metadata-key.js +21 -0
  40. package/dist/checker/rules/duplicate-metadata-key.js.map +1 -0
  41. package/dist/checker/rules/duplicate-section-heading.js +41 -0
  42. package/dist/checker/rules/duplicate-section-heading.js.map +1 -0
  43. package/dist/checker/rules/duplicate-section-in-schema.js +38 -0
  44. package/dist/checker/rules/duplicate-section-in-schema.js.map +1 -0
  45. package/dist/checker/rules/duplicate-timestamp.js +104 -0
  46. package/dist/checker/rules/duplicate-timestamp.js.map +1 -0
  47. package/dist/checker/rules/empty-required-value.js +45 -0
  48. package/dist/checker/rules/empty-required-value.js.map +1 -0
  49. package/dist/checker/rules/empty-section.js +21 -0
  50. package/dist/checker/rules/empty-section.js.map +1 -0
  51. package/dist/checker/rules/invalid-date-range-value.js +56 -0
  52. package/dist/checker/rules/invalid-date-range-value.js.map +1 -0
  53. package/dist/checker/rules/invalid-default-value.js +86 -0
  54. package/dist/checker/rules/invalid-default-value.js.map +1 -0
  55. package/dist/checker/rules/invalid-field-type.js +45 -0
  56. package/dist/checker/rules/invalid-field-type.js.map +1 -0
  57. package/dist/checker/rules/missing-required-field.js +48 -0
  58. package/dist/checker/rules/missing-required-field.js.map +1 -0
  59. package/dist/checker/rules/missing-required-section.js +51 -0
  60. package/dist/checker/rules/missing-required-section.js.map +1 -0
  61. package/dist/checker/rules/missing-title.js +56 -0
  62. package/dist/checker/rules/missing-title.js.map +1 -0
  63. package/dist/checker/rules/remove-undefined-field.js +42 -0
  64. package/dist/checker/rules/remove-undefined-field.js.map +1 -0
  65. package/dist/checker/rules/remove-undefined-section.js +42 -0
  66. package/dist/checker/rules/remove-undefined-section.js.map +1 -0
  67. package/dist/checker/rules/rules.d.ts +71 -0
  68. package/dist/checker/rules/rules.d.ts.map +1 -0
  69. package/dist/checker/rules/rules.js +102 -0
  70. package/dist/checker/rules/rules.js.map +1 -0
  71. package/dist/checker/rules/synthesis-empty-query.js +35 -0
  72. package/dist/checker/rules/synthesis-empty-query.js.map +1 -0
  73. package/dist/checker/rules/synthesis-missing-prompt.js +42 -0
  74. package/dist/checker/rules/synthesis-missing-prompt.js.map +1 -0
  75. package/dist/checker/rules/synthesis-missing-sources.js +32 -0
  76. package/dist/checker/rules/synthesis-missing-sources.js.map +1 -0
  77. package/dist/checker/rules/synthesis-unknown-query-entity.js +39 -0
  78. package/dist/checker/rules/synthesis-unknown-query-entity.js.map +1 -0
  79. package/dist/checker/rules/timestamp-out-of-order.js +55 -0
  80. package/dist/checker/rules/timestamp-out-of-order.js.map +1 -0
  81. package/dist/checker/rules/unknown-entity.js +32 -0
  82. package/dist/checker/rules/unknown-entity.js.map +1 -0
  83. package/dist/checker/rules/unknown-field.js +40 -0
  84. package/dist/checker/rules/unknown-field.js.map +1 -0
  85. package/dist/checker/rules/unknown-section.js +47 -0
  86. package/dist/checker/rules/unknown-section.js.map +1 -0
  87. package/dist/checker/rules/unresolved-link.js +34 -0
  88. package/dist/checker/rules/unresolved-link.js.map +1 -0
  89. package/dist/checker/rules/update-without-create.js +65 -0
  90. package/dist/checker/rules/update-without-create.js.map +1 -0
  91. package/dist/checker/visitor.d.ts +69 -0
  92. package/dist/checker/visitor.d.ts.map +1 -0
  93. package/dist/checker/visitor.js +67 -0
  94. package/dist/checker/visitor.js.map +1 -0
  95. package/dist/checker/workspace-index.d.ts +50 -0
  96. package/dist/checker/workspace-index.d.ts.map +1 -0
  97. package/dist/checker/workspace-index.js +108 -0
  98. package/dist/checker/workspace-index.js.map +1 -0
  99. package/dist/commands/actualize.d.ts +113 -0
  100. package/dist/commands/actualize.d.ts.map +1 -0
  101. package/dist/commands/actualize.js +111 -0
  102. package/dist/commands/actualize.js.map +1 -0
  103. package/dist/commands/check.d.ts +65 -0
  104. package/dist/commands/check.d.ts.map +1 -0
  105. package/dist/commands/check.js +61 -0
  106. package/dist/commands/check.js.map +1 -0
  107. package/dist/commands/format.d.ts +90 -0
  108. package/dist/commands/format.d.ts.map +1 -0
  109. package/dist/commands/format.js +80 -0
  110. package/dist/commands/format.js.map +1 -0
  111. package/dist/commands/query.d.ts +152 -0
  112. package/dist/commands/query.d.ts.map +1 -0
  113. package/dist/commands/query.js +151 -0
  114. package/dist/commands/query.js.map +1 -0
  115. package/dist/constants.d.ts +31 -0
  116. package/dist/constants.d.ts.map +1 -0
  117. package/dist/constants.js +51 -0
  118. package/dist/constants.js.map +1 -0
  119. package/dist/files.d.ts +58 -0
  120. package/dist/files.d.ts.map +1 -0
  121. package/dist/files.js +103 -0
  122. package/dist/files.js.map +1 -0
  123. package/dist/formatters.d.ts +39 -0
  124. package/dist/formatters.d.ts.map +1 -0
  125. package/dist/formatters.js +200 -0
  126. package/dist/formatters.js.map +1 -0
  127. package/dist/fragment.d.ts +22 -0
  128. package/dist/fragment.d.ts.map +1 -0
  129. package/dist/git/git.js +240 -0
  130. package/dist/git/git.js.map +1 -0
  131. package/dist/merge/conflict-detector.d.ts +89 -0
  132. package/dist/merge/conflict-detector.d.ts.map +1 -0
  133. package/dist/merge/conflict-detector.js +352 -0
  134. package/dist/merge/conflict-detector.js.map +1 -0
  135. package/dist/merge/conflict-formatter.js +143 -0
  136. package/dist/merge/conflict-formatter.js.map +1 -0
  137. package/dist/merge/driver.d.ts +54 -0
  138. package/dist/merge/driver.d.ts.map +1 -0
  139. package/dist/merge/driver.js +112 -0
  140. package/dist/merge/driver.js.map +1 -0
  141. package/dist/merge/entry-matcher.d.ts +50 -0
  142. package/dist/merge/entry-matcher.d.ts.map +1 -0
  143. package/dist/merge/entry-matcher.js +141 -0
  144. package/dist/merge/entry-matcher.js.map +1 -0
  145. package/dist/merge/entry-merger.js +194 -0
  146. package/dist/merge/entry-merger.js.map +1 -0
  147. package/dist/merge/merge-result-builder.d.ts +62 -0
  148. package/dist/merge/merge-result-builder.d.ts.map +1 -0
  149. package/dist/merge/merge-result-builder.js +89 -0
  150. package/dist/merge/merge-result-builder.js.map +1 -0
  151. package/dist/mod.d.ts +31 -0
  152. package/dist/mod.js +23 -0
  153. package/dist/model/document.d.ts +134 -0
  154. package/dist/model/document.d.ts.map +1 -0
  155. package/dist/model/document.js +275 -0
  156. package/dist/model/document.js.map +1 -0
  157. package/dist/model/line-index.d.ts +85 -0
  158. package/dist/model/line-index.d.ts.map +1 -0
  159. package/dist/model/line-index.js +159 -0
  160. package/dist/model/line-index.js.map +1 -0
  161. package/dist/model/workspace.d.ts +296 -0
  162. package/dist/model/workspace.d.ts.map +1 -0
  163. package/dist/model/workspace.js +562 -0
  164. package/dist/model/workspace.js.map +1 -0
  165. package/dist/parser.js +27 -0
  166. package/dist/parser.js.map +1 -0
  167. package/dist/parser.native.d.ts +51 -0
  168. package/dist/parser.native.d.ts.map +1 -0
  169. package/dist/parser.native.js +62 -0
  170. package/dist/parser.native.js.map +1 -0
  171. package/dist/parser.shared.d.ts +99 -0
  172. package/dist/parser.shared.d.ts.map +1 -0
  173. package/dist/parser.shared.js +124 -0
  174. package/dist/parser.shared.js.map +1 -0
  175. package/dist/parser.web.d.ts +67 -0
  176. package/dist/parser.web.d.ts.map +1 -0
  177. package/dist/parser.web.js +49 -0
  178. package/dist/parser.web.js.map +1 -0
  179. package/dist/schema/registry.d.ts +108 -0
  180. package/dist/schema/registry.d.ts.map +1 -0
  181. package/dist/schema/registry.js +281 -0
  182. package/dist/schema/registry.js.map +1 -0
  183. package/dist/semantic/analyzer.d.ts +107 -0
  184. package/dist/semantic/analyzer.d.ts.map +1 -0
  185. package/dist/semantic/analyzer.js +261 -0
  186. package/dist/semantic/analyzer.js.map +1 -0
  187. package/dist/services/change-tracker/change-tracker.d.ts +111 -0
  188. package/dist/services/change-tracker/change-tracker.d.ts.map +1 -0
  189. package/dist/services/change-tracker/change-tracker.js +62 -0
  190. package/dist/services/change-tracker/change-tracker.js.map +1 -0
  191. package/dist/services/change-tracker/create-tracker.d.ts +42 -0
  192. package/dist/services/change-tracker/create-tracker.d.ts.map +1 -0
  193. package/dist/services/change-tracker/create-tracker.js +53 -0
  194. package/dist/services/change-tracker/create-tracker.js.map +1 -0
  195. package/dist/services/change-tracker/git-tracker.d.ts +59 -0
  196. package/dist/services/change-tracker/git-tracker.d.ts.map +1 -0
  197. package/dist/services/change-tracker/git-tracker.js +218 -0
  198. package/dist/services/change-tracker/git-tracker.js.map +1 -0
  199. package/dist/services/change-tracker/timestamp-tracker.d.ts +22 -0
  200. package/dist/services/change-tracker/timestamp-tracker.d.ts.map +1 -0
  201. package/dist/services/change-tracker/timestamp-tracker.js +74 -0
  202. package/dist/services/change-tracker/timestamp-tracker.js.map +1 -0
  203. package/dist/services/definition.d.ts +37 -0
  204. package/dist/services/definition.d.ts.map +1 -0
  205. package/dist/services/definition.js +43 -0
  206. package/dist/services/definition.js.map +1 -0
  207. package/dist/services/entity-navigation.d.ts +200 -0
  208. package/dist/services/entity-navigation.d.ts.map +1 -0
  209. package/dist/services/entity-navigation.js +211 -0
  210. package/dist/services/entity-navigation.js.map +1 -0
  211. package/dist/services/hover.d.ts +81 -0
  212. package/dist/services/hover.d.ts.map +1 -0
  213. package/dist/services/hover.js +669 -0
  214. package/dist/services/hover.js.map +1 -0
  215. package/dist/services/query.d.ts +116 -0
  216. package/dist/services/query.d.ts.map +1 -0
  217. package/dist/services/query.js +225 -0
  218. package/dist/services/query.js.map +1 -0
  219. package/dist/services/references.d.ts +52 -0
  220. package/dist/services/references.d.ts.map +1 -0
  221. package/dist/services/references.js +66 -0
  222. package/dist/services/references.js.map +1 -0
  223. package/dist/services/semantic-tokens.d.ts +54 -0
  224. package/dist/services/semantic-tokens.d.ts.map +1 -0
  225. package/dist/services/semantic-tokens.js +213 -0
  226. package/dist/services/semantic-tokens.js.map +1 -0
  227. package/dist/services/synthesis.d.ts +90 -0
  228. package/dist/services/synthesis.d.ts.map +1 -0
  229. package/dist/services/synthesis.js +113 -0
  230. package/dist/services/synthesis.js.map +1 -0
  231. package/dist/source-map.d.ts +42 -0
  232. package/dist/source-map.d.ts.map +1 -0
  233. package/dist/source-map.js +170 -0
  234. package/dist/source-map.js.map +1 -0
  235. package/package.json +128 -0
  236. package/tree-sitter-thalo.wasm +0 -0
  237. package/web-tree-sitter.wasm +0 -0
@@ -0,0 +1,748 @@
1
+ import { buildTimestamp, createSyntaxError } from "./builder.js";
2
+
3
+ //#region src/ast/extract.ts
4
+ /**
5
+ * Extract location information from a tree-sitter node
6
+ */
7
+ function extractLocation(node) {
8
+ return {
9
+ startIndex: node.startIndex,
10
+ endIndex: node.endIndex,
11
+ startPosition: node.startPosition,
12
+ endPosition: node.endPosition
13
+ };
14
+ }
15
+ /**
16
+ * Create the base AST node properties
17
+ */
18
+ function baseNode(node, type) {
19
+ return {
20
+ type,
21
+ location: extractLocation(node),
22
+ syntaxNode: node
23
+ };
24
+ }
25
+ /**
26
+ * Get a required child by field name
27
+ */
28
+ function getChildByField(node, field) {
29
+ const child = node.childForFieldName(field);
30
+ if (!child) throw new Error(`Missing required field '${field}' in ${node.type}`);
31
+ return child;
32
+ }
33
+ /**
34
+ * Get an optional child by field name
35
+ */
36
+ function getOptionalChildByField(node, field) {
37
+ return node.childForFieldName(field);
38
+ }
39
+ /**
40
+ * Get all children of a specific type
41
+ */
42
+ function getChildrenByType(node, type) {
43
+ return node.namedChildren.filter((child) => child !== null && child.type === type);
44
+ }
45
+ /**
46
+ * Get the first child of a specific type
47
+ */
48
+ function getChildByType(node, type) {
49
+ return node.namedChildren.find((child) => child !== null && child.type === type) ?? null;
50
+ }
51
+ /**
52
+ * Strip quotes from a quoted string
53
+ */
54
+ function stripQuotes(text) {
55
+ if (text.startsWith("\"") && text.endsWith("\"")) return text.slice(1, -1);
56
+ return text;
57
+ }
58
+ /**
59
+ * Recursively find all ERROR nodes within a syntax tree.
60
+ * Used to capture syntax errors nested inside entries.
61
+ */
62
+ function findErrorNodes(node) {
63
+ const errors = [];
64
+ function walk(n) {
65
+ if (n.type === "ERROR") {
66
+ errors.push(n);
67
+ return;
68
+ }
69
+ for (const child of n.children) if (child) walk(child);
70
+ }
71
+ walk(node);
72
+ return errors;
73
+ }
74
+ /**
75
+ * Convert an ERROR syntax node to a SyntaxErrorNode
76
+ */
77
+ function errorNodeToSyntaxError(node) {
78
+ const text = node.text.trim();
79
+ return {
80
+ type: "syntax_error",
81
+ code: "parse_error",
82
+ message: `Parse error: unexpected content "${text.slice(0, 50)}${text.length > 50 ? "..." : ""}"`,
83
+ text: node.text,
84
+ location: extractLocation(node),
85
+ syntaxNode: node
86
+ };
87
+ }
88
+ /**
89
+ * Extract a SourceFile from the root node
90
+ */
91
+ function extractSourceFile(node) {
92
+ if (node.type !== "source_file") throw new Error(`Expected source_file, got ${node.type}`);
93
+ const entries = [];
94
+ const syntaxErrors = [];
95
+ for (const child of node.namedChildren) {
96
+ if (!child) continue;
97
+ if (child.type === "entry") {
98
+ const entry = extractEntry(child);
99
+ if (entry) entries.push(entry);
100
+ if (child.hasError) {
101
+ const nestedErrors = findErrorNodes(child);
102
+ for (const errorNode of nestedErrors) syntaxErrors.push(errorNodeToSyntaxError(errorNode));
103
+ }
104
+ } else if (child.type === "ERROR") syntaxErrors.push(errorNodeToSyntaxError(child));
105
+ }
106
+ return {
107
+ ...baseNode(node, "source_file"),
108
+ entries,
109
+ syntaxErrors
110
+ };
111
+ }
112
+ /**
113
+ * Extract an Entry from an entry node
114
+ */
115
+ function extractEntry(node) {
116
+ const child = node.namedChildren[0];
117
+ if (!child) return null;
118
+ if (child.type === "data_entry") return extractDataEntry(child);
119
+ if (child.type === "schema_entry") return extractSchemaEntry(child);
120
+ return null;
121
+ }
122
+ /**
123
+ * Extract a DataEntry - handles instance, synthesis, and actualize entries
124
+ * based on the directive type
125
+ */
126
+ function extractDataEntry(node) {
127
+ const directive = getChildByField(node, "directive").text;
128
+ if (directive === "define-synthesis") return extractSynthesisEntryFromData(node);
129
+ if (directive === "actualize-synthesis") return extractActualizeEntryFromData(node);
130
+ return extractInstanceEntryFromData(node);
131
+ }
132
+ /**
133
+ * Extract an InstanceEntry from a data_entry node
134
+ */
135
+ function extractInstanceEntryFromData(node) {
136
+ const timestampNode = getChildByField(node, "timestamp");
137
+ const directiveNode = getChildByField(node, "directive");
138
+ const argumentNode = getOptionalChildByField(node, "argument");
139
+ const titleNode = getOptionalChildByField(node, "title");
140
+ const linkNodes = getChildrenByType(node, "link");
141
+ const tagNodes = getChildrenByType(node, "tag");
142
+ const metadataNodes = getChildrenByType(node, "metadata");
143
+ const contentNode = getChildByType(node, "content");
144
+ const entityValue = argumentNode?.text || "";
145
+ const header = {
146
+ ...baseNode(node, "instance_header"),
147
+ timestamp: extractTimestamp(timestampNode),
148
+ directive: directiveNode.text,
149
+ entity: entityValue,
150
+ title: titleNode ? extractTitle(titleNode) : {
151
+ type: "title",
152
+ location: extractLocation(node),
153
+ syntaxNode: node,
154
+ value: ""
155
+ },
156
+ link: linkNodes.filter((l) => l !== argumentNode).length > 0 ? extractLink(linkNodes.filter((l) => l !== argumentNode)[0]) : null,
157
+ tags: tagNodes.map(extractTag)
158
+ };
159
+ return {
160
+ ...baseNode(node, "instance_entry"),
161
+ header,
162
+ metadata: metadataNodes.map(extractMetadata),
163
+ content: contentNode ? extractContent(contentNode) : null
164
+ };
165
+ }
166
+ /**
167
+ * Extract a SynthesisEntry from a data_entry node
168
+ */
169
+ function extractSynthesisEntryFromData(node) {
170
+ const timestampNode = getChildByField(node, "timestamp");
171
+ const titleNode = getOptionalChildByField(node, "title");
172
+ const argumentNode = getOptionalChildByField(node, "argument");
173
+ const linkNodes = getChildrenByType(node, "link");
174
+ const tagNodes = getChildrenByType(node, "tag");
175
+ const metadataNodes = getChildrenByType(node, "metadata");
176
+ const contentNode = getChildByType(node, "content");
177
+ const linkIdNode = argumentNode?.type === "link" ? argumentNode : linkNodes[0];
178
+ const header = {
179
+ ...baseNode(node, "synthesis_header"),
180
+ timestamp: extractTimestamp(timestampNode),
181
+ title: titleNode ? extractTitle(titleNode) : {
182
+ type: "title",
183
+ location: extractLocation(node),
184
+ syntaxNode: node,
185
+ value: ""
186
+ },
187
+ linkId: linkIdNode ? extractLink(linkIdNode) : {
188
+ type: "link",
189
+ location: extractLocation(node),
190
+ syntaxNode: node,
191
+ id: ""
192
+ },
193
+ tags: tagNodes.map(extractTag)
194
+ };
195
+ return {
196
+ ...baseNode(node, "synthesis_entry"),
197
+ header,
198
+ metadata: metadataNodes.map(extractMetadata),
199
+ content: contentNode ? extractContent(contentNode) : null
200
+ };
201
+ }
202
+ /**
203
+ * Extract an ActualizeEntry from a data_entry node
204
+ */
205
+ function extractActualizeEntryFromData(node) {
206
+ const timestampNode = getChildByField(node, "timestamp");
207
+ const argumentNode = getOptionalChildByField(node, "argument");
208
+ const linkNodes = getChildrenByType(node, "link");
209
+ const metadataNodes = getChildrenByType(node, "metadata");
210
+ const targetNode = argumentNode?.type === "link" ? argumentNode : linkNodes[0];
211
+ const header = {
212
+ ...baseNode(node, "actualize_header"),
213
+ timestamp: extractTimestamp(timestampNode),
214
+ target: targetNode ? extractLink(targetNode) : {
215
+ type: "link",
216
+ location: extractLocation(node),
217
+ syntaxNode: node,
218
+ id: ""
219
+ }
220
+ };
221
+ return {
222
+ ...baseNode(node, "actualize_entry"),
223
+ header,
224
+ metadata: metadataNodes.map(extractMetadata)
225
+ };
226
+ }
227
+ /**
228
+ * Extract a SchemaEntry - header fields are now inline
229
+ */
230
+ function extractSchemaEntry(node) {
231
+ const timestampNode = getChildByField(node, "timestamp");
232
+ const directiveNode = getChildByField(node, "directive");
233
+ const argumentNode = getOptionalChildByField(node, "argument");
234
+ const titleNode = getChildByField(node, "title");
235
+ const linkNodes = getChildrenByType(node, "link");
236
+ const tagNodes = getChildrenByType(node, "tag");
237
+ const metadataBlockNode = getChildByType(node, "metadata_block");
238
+ const sectionsBlockNode = getChildByType(node, "sections_block");
239
+ const removeMetadataBlockNode = getChildByType(node, "remove_metadata_block");
240
+ const removeSectionsBlockNode = getChildByType(node, "remove_sections_block");
241
+ const header = {
242
+ ...baseNode(node, "schema_header"),
243
+ timestamp: extractTimestamp(timestampNode),
244
+ directive: directiveNode.text,
245
+ entityName: argumentNode ? extractIdentifier(argumentNode) : {
246
+ type: "identifier",
247
+ location: extractLocation(node),
248
+ syntaxNode: node,
249
+ value: ""
250
+ },
251
+ title: extractTitle(titleNode),
252
+ link: linkNodes.length > 0 ? extractLink(linkNodes[0]) : null,
253
+ tags: tagNodes.map(extractTag)
254
+ };
255
+ return {
256
+ ...baseNode(node, "schema_entry"),
257
+ header,
258
+ metadataBlock: metadataBlockNode ? extractMetadataBlock(metadataBlockNode) : null,
259
+ sectionsBlock: sectionsBlockNode ? extractSectionsBlock(sectionsBlockNode) : null,
260
+ removeMetadataBlock: removeMetadataBlockNode ? extractRemoveMetadataBlock(removeMetadataBlockNode) : null,
261
+ removeSectionsBlock: removeSectionsBlockNode ? extractRemoveSectionsBlock(removeSectionsBlockNode) : null
262
+ };
263
+ }
264
+ /**
265
+ * Extract a MetadataBlock
266
+ */
267
+ function extractMetadataBlock(node) {
268
+ const fieldNodes = getChildrenByType(node, "field_definition");
269
+ return {
270
+ ...baseNode(node, "metadata_block"),
271
+ fields: fieldNodes.map(extractFieldDefinition)
272
+ };
273
+ }
274
+ /**
275
+ * Extract a SectionsBlock
276
+ */
277
+ function extractSectionsBlock(node) {
278
+ const sectionNodes = getChildrenByType(node, "section_definition");
279
+ return {
280
+ ...baseNode(node, "sections_block"),
281
+ sections: sectionNodes.map(extractSectionDefinition)
282
+ };
283
+ }
284
+ /**
285
+ * Extract a RemoveMetadataBlock
286
+ */
287
+ function extractRemoveMetadataBlock(node) {
288
+ const fieldNodes = getChildrenByType(node, "field_removal");
289
+ return {
290
+ ...baseNode(node, "remove_metadata_block"),
291
+ fields: fieldNodes.map(extractFieldRemoval)
292
+ };
293
+ }
294
+ /**
295
+ * Extract a RemoveSectionsBlock
296
+ */
297
+ function extractRemoveSectionsBlock(node) {
298
+ const sectionNodes = getChildrenByType(node, "section_removal");
299
+ return {
300
+ ...baseNode(node, "remove_sections_block"),
301
+ sections: sectionNodes.map(extractSectionRemoval)
302
+ };
303
+ }
304
+ /**
305
+ * Extract a FieldDefinition
306
+ */
307
+ function extractFieldDefinition(node) {
308
+ const nameNode = getChildByType(node, "field_name");
309
+ if (!nameNode) throw new Error("Missing field_name in field_definition");
310
+ const optionalMarker = getChildByType(node, "optional_marker");
311
+ const typeNode = getChildByField(node, "type");
312
+ const defaultNode = getOptionalChildByField(node, "default");
313
+ const descriptionNode = getOptionalChildByField(node, "description");
314
+ return {
315
+ ...baseNode(node, "field_definition"),
316
+ name: extractFieldName(nameNode),
317
+ optional: optionalMarker !== null,
318
+ typeExpr: extractTypeExpression(typeNode),
319
+ defaultValue: defaultNode ? extractDefaultValue(defaultNode) : null,
320
+ description: descriptionNode ? extractDescription(descriptionNode) : null
321
+ };
322
+ }
323
+ /**
324
+ * Extract a FieldRemoval
325
+ */
326
+ function extractFieldRemoval(node) {
327
+ const nameNode = getChildByType(node, "field_name");
328
+ if (!nameNode) throw new Error("Missing field_name in field_removal");
329
+ const reasonNode = getOptionalChildByField(node, "reason");
330
+ return {
331
+ ...baseNode(node, "field_removal"),
332
+ name: extractFieldName(nameNode),
333
+ reason: reasonNode ? extractDescription(reasonNode) : null
334
+ };
335
+ }
336
+ /**
337
+ * Extract a SectionDefinition
338
+ */
339
+ function extractSectionDefinition(node) {
340
+ const nameNode = getChildByType(node, "section_name");
341
+ if (!nameNode) throw new Error("Missing section_name in section_definition");
342
+ const optionalMarker = getChildByType(node, "optional_marker");
343
+ const descriptionNode = getOptionalChildByField(node, "description");
344
+ return {
345
+ ...baseNode(node, "section_definition"),
346
+ name: extractSectionName(nameNode),
347
+ optional: optionalMarker !== null,
348
+ description: descriptionNode ? extractDescription(descriptionNode) : null
349
+ };
350
+ }
351
+ /**
352
+ * Extract a SectionRemoval
353
+ */
354
+ function extractSectionRemoval(node) {
355
+ const nameNode = getChildByType(node, "section_name");
356
+ if (!nameNode) throw new Error("Missing section_name in section_removal");
357
+ const reasonNode = getOptionalChildByField(node, "reason");
358
+ return {
359
+ ...baseNode(node, "section_removal"),
360
+ name: extractSectionName(nameNode),
361
+ reason: reasonNode ? extractDescription(reasonNode) : null
362
+ };
363
+ }
364
+ /**
365
+ * Extract a TypeExpression.
366
+ * Returns a SyntaxErrorNode if an unknown type identifier is encountered.
367
+ */
368
+ function extractTypeExpression(node) {
369
+ const child = node.namedChildren[0];
370
+ if (!child) throw new Error("Empty type_expression");
371
+ switch (child.type) {
372
+ case "primitive_type": return extractPrimitiveType(child);
373
+ case "literal_type": return extractLiteralType(child);
374
+ case "array_type": return extractArrayType(child);
375
+ case "union_type": return extractUnionType(child);
376
+ case "unknown_type": return createSyntaxError("unknown_type", `Unknown type '${child.text}'. Valid types: string, datetime, daterange, link, number`, child.text, child);
377
+ default: throw new Error(`Unknown type expression: ${child.type}`);
378
+ }
379
+ }
380
+ /**
381
+ * Extract a PrimitiveType
382
+ */
383
+ function extractPrimitiveType(node) {
384
+ return {
385
+ ...baseNode(node, "primitive_type"),
386
+ name: node.text
387
+ };
388
+ }
389
+ /**
390
+ * Extract a LiteralType
391
+ */
392
+ function extractLiteralType(node) {
393
+ return {
394
+ ...baseNode(node, "literal_type"),
395
+ value: stripQuotes(node.text)
396
+ };
397
+ }
398
+ /**
399
+ * Extract an ArrayType.
400
+ * Returns a SyntaxErrorNode if the element type is unknown.
401
+ */
402
+ function extractArrayType(node) {
403
+ const child = node.namedChildren[0];
404
+ if (!child) throw new Error("Empty array_type");
405
+ let elementType;
406
+ if (child.type === "primitive_type") elementType = extractPrimitiveType(child);
407
+ else if (child.type === "literal_type") elementType = extractLiteralType(child);
408
+ else if (child.type === "unknown_type") return createSyntaxError("unknown_type", `Unknown type '${child.text}'. Valid types: string, datetime, daterange, link, number`, node.text, node);
409
+ else if (child.type === "paren_type") {
410
+ const innerTypeExpr = child.namedChildren[0];
411
+ if (!innerTypeExpr) throw new Error("Empty paren_type");
412
+ const extracted = extractTypeExpression(innerTypeExpr);
413
+ if (extracted.type === "syntax_error") return extracted;
414
+ if (extracted.type !== "union_type") throw new Error(`Unexpected paren_type content: ${extracted.type}`);
415
+ elementType = extracted;
416
+ } else throw new Error(`Invalid array element type: ${child.type}`);
417
+ return {
418
+ ...baseNode(node, "array_type"),
419
+ elementType
420
+ };
421
+ }
422
+ /**
423
+ * Extract a UnionType.
424
+ * Returns a SyntaxErrorNode if any member is an unknown type.
425
+ */
426
+ function extractUnionType(node) {
427
+ const members = [];
428
+ for (const child of node.namedChildren) {
429
+ if (!child) continue;
430
+ switch (child.type) {
431
+ case "primitive_type":
432
+ members.push(extractPrimitiveType(child));
433
+ break;
434
+ case "literal_type":
435
+ members.push(extractLiteralType(child));
436
+ break;
437
+ case "array_type": {
438
+ const arrayType = extractArrayType(child);
439
+ if (arrayType.type === "syntax_error") return arrayType;
440
+ members.push(arrayType);
441
+ break;
442
+ }
443
+ case "unknown_type": return createSyntaxError("unknown_type", `Unknown type '${child.text}'. Valid types: string, datetime, daterange, link, number`, node.text, node);
444
+ }
445
+ }
446
+ return {
447
+ ...baseNode(node, "union_type"),
448
+ members
449
+ };
450
+ }
451
+ /**
452
+ * Extract a Metadata entry
453
+ */
454
+ function extractMetadata(node) {
455
+ const keyNode = getChildByField(node, "key");
456
+ const valueNode = getChildByField(node, "value");
457
+ return {
458
+ ...baseNode(node, "metadata"),
459
+ key: extractKey(keyNode),
460
+ value: extractValue(valueNode)
461
+ };
462
+ }
463
+ /**
464
+ * Extract Content
465
+ */
466
+ function extractContent(node) {
467
+ const children = [];
468
+ for (const child of node.namedChildren) {
469
+ if (!child) continue;
470
+ if (child.type === "markdown_header") children.push(extractMarkdownHeader(child));
471
+ else if (child.type === "content_line") children.push(extractContentLine(child));
472
+ }
473
+ return {
474
+ ...baseNode(node, "content"),
475
+ children
476
+ };
477
+ }
478
+ /**
479
+ * Extract a MarkdownHeader
480
+ */
481
+ function extractMarkdownHeader(node) {
482
+ const raw = node.text;
483
+ const trimmedRight = raw.replace(/[ \t]+$/, "");
484
+ const trimDelta = raw.length - trimmedRight.length;
485
+ const base = baseNode(node, "markdown_header");
486
+ return {
487
+ ...base,
488
+ location: trimDelta === 0 ? base.location : {
489
+ ...base.location,
490
+ endIndex: base.location.endIndex - trimDelta,
491
+ endPosition: {
492
+ ...base.location.endPosition,
493
+ column: Math.max(0, base.location.endPosition.column - trimDelta)
494
+ }
495
+ },
496
+ text: raw.trim()
497
+ };
498
+ }
499
+ /**
500
+ * Extract a ContentLine
501
+ */
502
+ function extractContentLine(node) {
503
+ return {
504
+ ...baseNode(node, "content_line"),
505
+ text: node.text.trim()
506
+ };
507
+ }
508
+ function extractTimestamp(node) {
509
+ return buildTimestamp(node);
510
+ }
511
+ function extractTitle(node) {
512
+ return {
513
+ ...baseNode(node, "title"),
514
+ value: stripQuotes(node.text)
515
+ };
516
+ }
517
+ function extractLink(node) {
518
+ const text = node.text.trim();
519
+ return {
520
+ ...baseNode(node, "link"),
521
+ id: text.slice(1)
522
+ };
523
+ }
524
+ function extractTag(node) {
525
+ const text = node.text.trim();
526
+ return {
527
+ ...baseNode(node, "tag"),
528
+ name: text.slice(1)
529
+ };
530
+ }
531
+ function extractIdentifier(node) {
532
+ return {
533
+ ...baseNode(node, "identifier"),
534
+ value: node.text
535
+ };
536
+ }
537
+ function extractKey(node) {
538
+ return {
539
+ ...baseNode(node, "key"),
540
+ value: node.text
541
+ };
542
+ }
543
+ function extractValue(node) {
544
+ const child = node.namedChildren[0];
545
+ if (!child) return {
546
+ ...baseNode(node, "value"),
547
+ raw: node.text.trim(),
548
+ content: {
549
+ ...baseNode(node, "quoted_value"),
550
+ value: node.text.trim()
551
+ }
552
+ };
553
+ return {
554
+ ...baseNode(node, "value"),
555
+ raw: node.text.trim(),
556
+ content: extractValueContent(child)
557
+ };
558
+ }
559
+ /**
560
+ * Extract typed value content from a child node of value
561
+ */
562
+ function extractValueContent(node) {
563
+ switch (node.type) {
564
+ case "quoted_value": return extractQuotedValue(node);
565
+ case "link": return {
566
+ ...baseNode(node, "link_value"),
567
+ link: extractLink(node)
568
+ };
569
+ case "datetime_value": return extractDatetimeValue(node);
570
+ case "daterange": return {
571
+ ...baseNode(node, "daterange"),
572
+ raw: node.text.trim()
573
+ };
574
+ case "number_value": return {
575
+ ...baseNode(node, "number_value"),
576
+ raw: node.text.trim(),
577
+ value: parseFloat(node.text.trim())
578
+ };
579
+ case "value_array": return extractValueArray(node);
580
+ case "query": return {
581
+ ...baseNode(node, "query_value"),
582
+ query: extractQuery(node)
583
+ };
584
+ default: return {
585
+ ...baseNode(node, "quoted_value"),
586
+ value: node.text.trim()
587
+ };
588
+ }
589
+ }
590
+ /**
591
+ * Extract a datetime value with its split components
592
+ */
593
+ function extractDatetimeValue(node) {
594
+ const dateNode = node.childForFieldName("date");
595
+ const timeNode = node.childForFieldName("time");
596
+ const tzNode = node.childForFieldName("tz");
597
+ return {
598
+ ...baseNode(node, "datetime_value"),
599
+ value: node.text.trim(),
600
+ date: dateNode?.text ?? "",
601
+ time: timeNode?.text ?? null,
602
+ tz: tzNode?.text ?? null
603
+ };
604
+ }
605
+ function extractQuotedValue(node) {
606
+ return {
607
+ ...baseNode(node, "quoted_value"),
608
+ value: stripQuotes(node.text)
609
+ };
610
+ }
611
+ function extractValueArray(node) {
612
+ const elements = [];
613
+ for (const child of node.namedChildren) {
614
+ if (!child) continue;
615
+ if (child.type === "link") elements.push(extractLink(child));
616
+ else if (child.type === "quoted_value") elements.push(extractQuotedValue(child));
617
+ else if (child.type === "datetime_value") elements.push(extractDatetimeValue(child));
618
+ else if (child.type === "daterange") elements.push({
619
+ ...baseNode(child, "daterange"),
620
+ raw: child.text.trim()
621
+ });
622
+ else if (child.type === "number_value") elements.push({
623
+ ...baseNode(child, "number_value"),
624
+ raw: child.text.trim(),
625
+ value: parseFloat(child.text.trim())
626
+ });
627
+ else if (child.type === "query") elements.push(extractQuery(child));
628
+ }
629
+ return {
630
+ ...baseNode(node, "value_array"),
631
+ elements
632
+ };
633
+ }
634
+ function extractQuery(node) {
635
+ const entityNode = node.childForFieldName("entity");
636
+ const conditionsNode = node.childForFieldName("conditions");
637
+ let entityText = "";
638
+ if (entityNode) {
639
+ const innerEntity = entityNode.namedChildren[0];
640
+ entityText = innerEntity ? innerEntity.text : entityNode.text;
641
+ }
642
+ const conditions = [];
643
+ if (conditionsNode) for (const child of conditionsNode.namedChildren) {
644
+ if (!child) continue;
645
+ if (child.type === "query_condition") {
646
+ const condition = extractQueryCondition(child);
647
+ if (condition) conditions.push(condition);
648
+ }
649
+ }
650
+ return {
651
+ ...baseNode(node, "query"),
652
+ entity: entityText,
653
+ conditions
654
+ };
655
+ }
656
+ function extractQueryCondition(node) {
657
+ const child = node.namedChildren[0];
658
+ if (!child) return null;
659
+ switch (child.type) {
660
+ case "field_condition": {
661
+ const fieldNode = child.childForFieldName("field");
662
+ const valueNode = child.childForFieldName("value");
663
+ let fieldText = "";
664
+ if (fieldNode) {
665
+ const innerField = fieldNode.namedChildren[0];
666
+ fieldText = innerField ? innerField.text : fieldNode.text;
667
+ }
668
+ let valueText = "";
669
+ if (valueNode) if (valueNode.type === "link") valueText = valueNode.text;
670
+ else if (valueNode.type === "quoted_value") valueText = valueNode.text;
671
+ else {
672
+ const inner = valueNode.namedChildren[0];
673
+ valueText = inner ? inner.text : valueNode.text;
674
+ }
675
+ return {
676
+ ...baseNode(child, "field_condition"),
677
+ field: fieldText,
678
+ value: valueText
679
+ };
680
+ }
681
+ case "tag_condition": {
682
+ const tagNode = getChildByType(child, "tag");
683
+ return {
684
+ ...baseNode(child, "tag_condition"),
685
+ tag: tagNode ? tagNode.text.slice(1) : ""
686
+ };
687
+ }
688
+ case "link_condition": {
689
+ const linkNode = getChildByType(child, "link");
690
+ return {
691
+ ...baseNode(child, "link_condition"),
692
+ linkId: linkNode ? linkNode.text.slice(1) : ""
693
+ };
694
+ }
695
+ default: return null;
696
+ }
697
+ }
698
+ function extractFieldName(node) {
699
+ return {
700
+ ...baseNode(node, "field_name"),
701
+ value: node.text.trim()
702
+ };
703
+ }
704
+ function extractSectionName(node) {
705
+ return {
706
+ ...baseNode(node, "section_name"),
707
+ value: node.text.trim()
708
+ };
709
+ }
710
+ function extractDescription(node) {
711
+ return {
712
+ ...baseNode(node, "description"),
713
+ value: stripQuotes(node.text)
714
+ };
715
+ }
716
+ function extractDefaultValue(node) {
717
+ const child = node.namedChildren[0];
718
+ if (!child) throw new Error("Empty default_value");
719
+ let content;
720
+ switch (child.type) {
721
+ case "quoted_value":
722
+ content = extractQuotedValue(child);
723
+ break;
724
+ case "link":
725
+ content = extractLink(child);
726
+ break;
727
+ case "datetime_value":
728
+ content = extractDatetimeValue(child);
729
+ break;
730
+ case "number_value":
731
+ content = {
732
+ ...baseNode(child, "number_value"),
733
+ raw: child.text.trim(),
734
+ value: parseFloat(child.text.trim())
735
+ };
736
+ break;
737
+ default: throw new Error(`Unknown default_value child type: ${child.type}`);
738
+ }
739
+ return {
740
+ ...baseNode(node, "default_value"),
741
+ raw: node.text,
742
+ content
743
+ };
744
+ }
745
+
746
+ //#endregion
747
+ export { extractFieldName, extractIdentifier, extractKey, extractLink, extractSectionName, extractSourceFile, extractTag, extractTimestamp, extractTypeExpression };
748
+ //# sourceMappingURL=extract.js.map