@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,281 @@
1
+ //#region src/schema/registry.ts
2
+ /**
3
+ * Registry for entity schemas.
4
+ * Collects define-entity and alter-entity entries and resolves them into EntitySchemas.
5
+ */
6
+ var SchemaRegistry = class {
7
+ schemas = /* @__PURE__ */ new Map();
8
+ defineEntries = /* @__PURE__ */ new Map();
9
+ alterEntries = /* @__PURE__ */ new Map();
10
+ /**
11
+ * Add a schema entry (define-entity or alter-entity)
12
+ */
13
+ add(entry) {
14
+ if (entry.directive === "define-entity") this.defineEntries.set(entry.entityName, entry);
15
+ else {
16
+ const alters = this.alterEntries.get(entry.entityName) ?? [];
17
+ alters.push(entry);
18
+ this.alterEntries.set(entry.entityName, alters);
19
+ }
20
+ this.schemas.delete(entry.entityName);
21
+ }
22
+ /**
23
+ * Get a resolved entity schema by name
24
+ */
25
+ get(name) {
26
+ if (this.schemas.has(name)) return this.schemas.get(name);
27
+ const schema = this.resolve(name);
28
+ if (schema) this.schemas.set(name, schema);
29
+ return schema;
30
+ }
31
+ /**
32
+ * Check if an entity is defined
33
+ */
34
+ has(name) {
35
+ return this.defineEntries.has(name);
36
+ }
37
+ /**
38
+ * Get all defined entity names
39
+ */
40
+ entityNames() {
41
+ return Array.from(this.defineEntries.keys());
42
+ }
43
+ /**
44
+ * Clear all schemas
45
+ */
46
+ clear() {
47
+ this.schemas.clear();
48
+ this.defineEntries.clear();
49
+ this.alterEntries.clear();
50
+ }
51
+ /**
52
+ * Resolve an entity schema from its define and alter entries
53
+ */
54
+ resolve(name) {
55
+ const defineEntry = this.defineEntries.get(name);
56
+ if (!defineEntry) return;
57
+ const schema = {
58
+ name,
59
+ description: defineEntry.title,
60
+ fields: /* @__PURE__ */ new Map(),
61
+ sections: /* @__PURE__ */ new Map(),
62
+ definedAt: defineEntry.timestamp,
63
+ definedIn: defineEntry.file
64
+ };
65
+ for (const field of defineEntry.fields) schema.fields.set(field.name, {
66
+ name: field.name,
67
+ optional: field.optional,
68
+ type: field.type,
69
+ defaultValue: field.defaultValue,
70
+ description: field.description
71
+ });
72
+ for (const section of defineEntry.sections) schema.sections.set(section.name, {
73
+ name: section.name,
74
+ optional: section.optional,
75
+ description: section.description
76
+ });
77
+ const sortedAlters = [...this.alterEntries.get(name) ?? []].sort((a, b) => a.timestamp.localeCompare(b.timestamp));
78
+ for (const alter of sortedAlters) this.applyAlter(schema, alter);
79
+ return schema;
80
+ }
81
+ /**
82
+ * Apply an alter-entity entry to a schema
83
+ */
84
+ applyAlter(schema, alter) {
85
+ for (const field of alter.fields) schema.fields.set(field.name, {
86
+ name: field.name,
87
+ optional: field.optional,
88
+ type: field.type,
89
+ defaultValue: field.defaultValue,
90
+ description: field.description
91
+ });
92
+ for (const section of alter.sections) schema.sections.set(section.name, {
93
+ name: section.name,
94
+ optional: section.optional,
95
+ description: section.description
96
+ });
97
+ for (const fieldName of alter.removeFields) schema.fields.delete(fieldName);
98
+ for (const sectionName of alter.removeSections) schema.sections.delete(sectionName);
99
+ }
100
+ };
101
+ /**
102
+ * Type checking utilities for type expressions.
103
+ * Uses the grammar-parsed ValueContent for type validation.
104
+ */
105
+ const TypeExpr = {
106
+ matchesContent(content, type) {
107
+ switch (type.kind) {
108
+ case "primitive": return matchesPrimitiveContent(content, type.name);
109
+ case "literal": return matchesLiteralContent(content, type.value);
110
+ case "array": return matchesArrayContent(content, type.elementType);
111
+ case "union": return type.members.some((member) => TypeExpr.matchesContent(content, member));
112
+ case "unknown": return true;
113
+ }
114
+ },
115
+ matchesDefaultValue(defaultValue, type) {
116
+ switch (type.kind) {
117
+ case "primitive": return matchesDefaultPrimitive(defaultValue, type.name);
118
+ case "literal": return defaultValue.kind === "quoted" && defaultValue.value === type.value;
119
+ case "array": return matchesDefaultAsArrayElement(defaultValue, type.elementType);
120
+ case "union": return type.members.some((member) => TypeExpr.matchesDefaultValue(defaultValue, member));
121
+ case "unknown": return true;
122
+ }
123
+ },
124
+ toString(type) {
125
+ switch (type.kind) {
126
+ case "primitive": return type.name;
127
+ case "literal": return `"${type.value}"`;
128
+ case "array":
129
+ if (type.elementType.kind === "union") return `(${TypeExpr.toString(type.elementType)})[]`;
130
+ return `${TypeExpr.toString(type.elementType)}[]`;
131
+ case "union": return type.members.map((m) => TypeExpr.toString(m)).join(" | ");
132
+ case "unknown": return type.name;
133
+ }
134
+ }
135
+ };
136
+ /**
137
+ * Check if content matches a primitive type
138
+ */
139
+ function matchesPrimitiveContent(content, type) {
140
+ switch (type) {
141
+ case "string": return true;
142
+ case "link": return content.type === "link_value";
143
+ case "daterange": return content.type === "daterange";
144
+ case "datetime":
145
+ if (content.type === "datetime_value") return content.time === null;
146
+ return false;
147
+ case "number": return content.type === "number_value";
148
+ }
149
+ }
150
+ /**
151
+ * Check if content matches a literal type
152
+ */
153
+ function matchesLiteralContent(content, expectedValue) {
154
+ if (content.type === "quoted_value") return content.value === expectedValue;
155
+ return false;
156
+ }
157
+ /**
158
+ * Check if content matches an array type.
159
+ * Arrays can be:
160
+ * 1. A value_array (comma-separated: ^ref1, ^ref2)
161
+ * 2. A single value that matches the element type
162
+ */
163
+ function matchesArrayContent(content, elementType) {
164
+ if (elementType.kind === "unknown") return true;
165
+ if (content.type === "value_array") {
166
+ if (content.elements.length === 0) return false;
167
+ return content.elements.every((element) => matchesArrayElementContent(element, elementType));
168
+ }
169
+ return matchesSingleValueAsArrayElement(content, elementType);
170
+ }
171
+ /**
172
+ * Check if a single (non-array) value matches an array element type
173
+ */
174
+ function matchesSingleValueAsArrayElement(content, elementType) {
175
+ if (content.type === "quoted_value" && content.value === "") return false;
176
+ switch (elementType.kind) {
177
+ case "primitive": return matchesSingleValueAsPrimitive(content, elementType.name);
178
+ case "literal":
179
+ if (content.type === "quoted_value") return content.value === elementType.value;
180
+ return false;
181
+ case "union": return elementType.members.some((member) => {
182
+ if (member.kind === "primitive") return matchesSingleValueAsPrimitive(content, member.name);
183
+ else if (member.kind === "literal") return content.type === "quoted_value" && content.value === member.value;
184
+ return false;
185
+ });
186
+ }
187
+ }
188
+ /**
189
+ * Check if a single value matches a primitive type (for single-element arrays)
190
+ */
191
+ function matchesSingleValueAsPrimitive(content, type) {
192
+ switch (type) {
193
+ case "string": return content.type === "quoted_value" && content.value.length > 0;
194
+ case "link": return content.type === "link_value";
195
+ case "daterange": return content.type === "daterange";
196
+ case "datetime":
197
+ if (content.type === "datetime_value") return content.time === null;
198
+ return false;
199
+ case "number": return content.type === "number_value";
200
+ }
201
+ }
202
+ /**
203
+ * Check if an array element matches the expected element type
204
+ */
205
+ function matchesArrayElementContent(element, elementType) {
206
+ switch (elementType.kind) {
207
+ case "primitive": return matchesArrayPrimitiveContent(element, elementType.name);
208
+ case "literal":
209
+ if (element.type === "quoted_value") return element.value === elementType.value;
210
+ return false;
211
+ case "union": return elementType.members.some((member) => {
212
+ if (member.kind === "primitive") return matchesArrayPrimitiveContent(element, member.name);
213
+ else if (member.kind === "literal") return element.type === "quoted_value" && element.value === member.value;
214
+ return false;
215
+ });
216
+ }
217
+ }
218
+ /**
219
+ * Check if an array element matches a primitive type
220
+ */
221
+ function matchesArrayPrimitiveContent(element, type) {
222
+ switch (type) {
223
+ case "string": return element.type === "quoted_value";
224
+ case "link": return element.type === "link";
225
+ case "datetime":
226
+ if (element.type === "datetime_value") return element.time === null;
227
+ return false;
228
+ case "daterange":
229
+ if (element.type === "daterange") return true;
230
+ if (element.type === "quoted_value") return /^\d{4}(-\d{2}(-\d{2})?)?\s*~\s*\d{4}(-\d{2}(-\d{2})?)?$/.test(element.value);
231
+ return false;
232
+ case "number": return element.type === "number_value";
233
+ }
234
+ }
235
+ /**
236
+ * Check if a default value matches a primitive type
237
+ */
238
+ function matchesDefaultPrimitive(defaultValue, type) {
239
+ switch (type) {
240
+ case "string": return true;
241
+ case "link": return defaultValue.kind === "link";
242
+ case "datetime":
243
+ if (defaultValue.kind === "datetime") return !defaultValue.value.includes("T");
244
+ return false;
245
+ case "daterange": return false;
246
+ case "number": return defaultValue.kind === "number";
247
+ }
248
+ }
249
+ /**
250
+ * Check if a default value matches as a single array element
251
+ */
252
+ function matchesDefaultAsArrayElement(defaultValue, elementType) {
253
+ switch (elementType.kind) {
254
+ case "primitive": return matchesDefaultAsPrimitive(defaultValue, elementType.name);
255
+ case "literal": return defaultValue.kind === "quoted" && defaultValue.value === elementType.value;
256
+ case "union": return elementType.members.some((member) => {
257
+ if (member.kind === "primitive") return matchesDefaultAsPrimitive(defaultValue, member.name);
258
+ else if (member.kind === "literal") return defaultValue.kind === "quoted" && defaultValue.value === member.value;
259
+ return false;
260
+ });
261
+ case "unknown": return true;
262
+ }
263
+ }
264
+ /**
265
+ * Check if a default value matches a primitive type as array element
266
+ */
267
+ function matchesDefaultAsPrimitive(defaultValue, type) {
268
+ switch (type) {
269
+ case "string": return defaultValue.kind === "quoted" && defaultValue.value.length > 0;
270
+ case "link": return defaultValue.kind === "link";
271
+ case "datetime":
272
+ if (defaultValue.kind === "datetime") return !defaultValue.value.includes("T");
273
+ return false;
274
+ case "daterange": return false;
275
+ case "number": return defaultValue.kind === "number";
276
+ }
277
+ }
278
+
279
+ //#endregion
280
+ export { SchemaRegistry, TypeExpr };
281
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","names":["schema: EntitySchema"],"sources":["../../src/schema/registry.ts"],"sourcesContent":["import type {\n ModelSchemaEntry,\n ModelDefaultValue,\n ModelTypeExpression,\n ModelPrimitiveType,\n ModelLiteralType,\n ModelUnionType,\n ModelUnknownType,\n} from \"../model/workspace.js\";\nimport type {\n ValueContent,\n Link,\n QuotedValue,\n DatetimeValue,\n DaterangeValue,\n NumberValue,\n Query,\n} from \"../ast/ast-types.js\";\n\n/**\n * A resolved entity schema (after applying all define-entity and alter-entity entries)\n */\nexport interface EntitySchema {\n /** The entity name */\n name: string;\n /** Description from the define-entity entry */\n description: string;\n /** Field definitions */\n fields: Map<string, FieldSchema>;\n /** Section definitions */\n sections: Map<string, SectionSchema>;\n /** Timestamp of the define-entity that created this schema */\n definedAt: string;\n /** File where this schema was defined */\n definedIn: string;\n}\n\n/**\n * A field schema in an entity definition\n */\nexport interface FieldSchema {\n /** Field name */\n name: string;\n /** Whether the field is optional */\n optional: boolean;\n /** The type expression */\n type: ModelTypeExpression;\n /** Default value (if any) */\n defaultValue: ModelDefaultValue | null;\n /** Description (if any) */\n description: string | null;\n}\n\n/**\n * A section schema in an entity definition\n */\nexport interface SectionSchema {\n /** Section name (PascalCase) */\n name: string;\n /** Whether the section is optional */\n optional: boolean;\n /** Description (if any) */\n description: string | null;\n}\n\n/**\n * Registry for entity schemas.\n * Collects define-entity and alter-entity entries and resolves them into EntitySchemas.\n */\nexport class SchemaRegistry {\n private schemas = new Map<string, EntitySchema>();\n private defineEntries = new Map<string, ModelSchemaEntry>();\n private alterEntries = new Map<string, ModelSchemaEntry[]>();\n\n /**\n * Add a schema entry (define-entity or alter-entity)\n */\n add(entry: ModelSchemaEntry): void {\n if (entry.directive === \"define-entity\") {\n this.defineEntries.set(entry.entityName, entry);\n } else {\n const alters = this.alterEntries.get(entry.entityName) ?? [];\n alters.push(entry);\n this.alterEntries.set(entry.entityName, alters);\n }\n\n // Clear cached schema to force re-resolution\n this.schemas.delete(entry.entityName);\n }\n\n /**\n * Get a resolved entity schema by name\n */\n get(name: string): EntitySchema | undefined {\n // Return cached if available\n if (this.schemas.has(name)) {\n return this.schemas.get(name);\n }\n\n // Try to resolve\n const schema = this.resolve(name);\n if (schema) {\n this.schemas.set(name, schema);\n }\n return schema;\n }\n\n /**\n * Check if an entity is defined\n */\n has(name: string): boolean {\n return this.defineEntries.has(name);\n }\n\n /**\n * Get all defined entity names\n */\n entityNames(): string[] {\n return Array.from(this.defineEntries.keys());\n }\n\n /**\n * Clear all schemas\n */\n clear(): void {\n this.schemas.clear();\n this.defineEntries.clear();\n this.alterEntries.clear();\n }\n\n /**\n * Resolve an entity schema from its define and alter entries\n */\n private resolve(name: string): EntitySchema | undefined {\n const defineEntry = this.defineEntries.get(name);\n if (!defineEntry) {\n return undefined;\n }\n\n // Start with the base schema from define-entity\n const schema: EntitySchema = {\n name,\n description: defineEntry.title,\n fields: new Map(),\n sections: new Map(),\n definedAt: defineEntry.timestamp,\n definedIn: defineEntry.file,\n };\n\n // Add fields from define-entity\n for (const field of defineEntry.fields) {\n schema.fields.set(field.name, {\n name: field.name,\n optional: field.optional,\n type: field.type,\n defaultValue: field.defaultValue,\n description: field.description,\n });\n }\n\n // Add sections from define-entity\n for (const section of defineEntry.sections) {\n schema.sections.set(section.name, {\n name: section.name,\n optional: section.optional,\n description: section.description,\n });\n }\n\n // Apply alter-entity entries in order (by timestamp)\n const alters = this.alterEntries.get(name) ?? [];\n const sortedAlters = [...alters].sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n for (const alter of sortedAlters) {\n this.applyAlter(schema, alter);\n }\n\n return schema;\n }\n\n /**\n * Apply an alter-entity entry to a schema\n */\n private applyAlter(schema: EntitySchema, alter: ModelSchemaEntry): void {\n // Add/update fields\n for (const field of alter.fields) {\n schema.fields.set(field.name, {\n name: field.name,\n optional: field.optional,\n type: field.type,\n defaultValue: field.defaultValue,\n description: field.description,\n });\n }\n\n // Add/update sections\n for (const section of alter.sections) {\n schema.sections.set(section.name, {\n name: section.name,\n optional: section.optional,\n description: section.description,\n });\n }\n\n // Remove fields\n for (const fieldName of alter.removeFields) {\n schema.fields.delete(fieldName);\n }\n\n // Remove sections\n for (const sectionName of alter.removeSections) {\n schema.sections.delete(sectionName);\n }\n }\n}\n\n/**\n * Create a field schema helper\n */\nexport function createFieldSchema(\n name: string,\n optional: boolean,\n type: FieldSchema[\"type\"],\n defaultValue?: ModelDefaultValue | null,\n description?: string,\n): FieldSchema {\n return {\n name,\n optional,\n type,\n defaultValue: defaultValue ?? null,\n description: description ?? null,\n };\n}\n\n/**\n * Create a section schema helper\n */\nexport function createSectionSchema(\n name: string,\n optional: boolean,\n description?: string,\n): SectionSchema {\n return {\n name,\n optional,\n description: description ?? null,\n };\n}\n\n/**\n * Type checking utilities for type expressions.\n * Uses the grammar-parsed ValueContent for type validation.\n */\nexport const TypeExpr = {\n /**\n * Check if a value content matches a type expression.\n * This uses the grammar-parsed structure for reliable type checking.\n */\n matchesContent(content: ValueContent, type: ModelTypeExpression): boolean {\n switch (type.kind) {\n case \"primitive\":\n return matchesPrimitiveContent(content, type.name);\n case \"literal\":\n return matchesLiteralContent(content, type.value);\n case \"array\":\n return matchesArrayContent(content, type.elementType);\n case \"union\":\n return type.members.some((member) => TypeExpr.matchesContent(content, member));\n case \"unknown\":\n // Unknown types can't be validated - accept any value\n // (the unknown type itself is reported as a syntax error)\n return true;\n }\n },\n\n /**\n * Check if a default value matches a type expression.\n * Default values can only be quoted strings, links, or datetimes.\n */\n matchesDefaultValue(defaultValue: ModelDefaultValue, type: ModelTypeExpression): boolean {\n switch (type.kind) {\n case \"primitive\":\n return matchesDefaultPrimitive(defaultValue, type.name);\n case \"literal\":\n // Literal types require quoted values with matching content\n return defaultValue.kind === \"quoted\" && defaultValue.value === type.value;\n case \"array\":\n // Default values can't be arrays (grammar doesn't support it)\n // But a single value can match an array type as a single-element array\n return matchesDefaultAsArrayElement(defaultValue, type.elementType);\n case \"union\":\n return type.members.some((member) => TypeExpr.matchesDefaultValue(defaultValue, member));\n case \"unknown\":\n // Unknown types can't be validated - accept any default value\n return true;\n }\n },\n\n /**\n * Get a human-readable string for a type expression\n */\n toString(type: ModelTypeExpression): string {\n switch (type.kind) {\n case \"primitive\":\n return type.name;\n case \"literal\":\n return `\"${type.value}\"`;\n case \"array\":\n // For union element types, wrap in parentheses\n if (type.elementType.kind === \"union\") {\n return `(${TypeExpr.toString(type.elementType)})[]`;\n }\n return `${TypeExpr.toString(type.elementType)}[]`;\n case \"union\":\n return type.members.map((m) => TypeExpr.toString(m)).join(\" | \");\n case \"unknown\":\n return type.name;\n }\n },\n};\n\n// ===================\n// Content-based matching (using grammar-parsed structure)\n// ===================\n\n/**\n * Check if content matches a primitive type\n */\nfunction matchesPrimitiveContent(\n content: ValueContent,\n type: \"string\" | \"datetime\" | \"daterange\" | \"link\" | \"number\",\n): boolean {\n switch (type) {\n case \"string\":\n // Any content matches string type\n return true;\n case \"link\":\n // Must be a link value\n return content.type === \"link_value\";\n case \"daterange\":\n // Grammar identifies date ranges\n return content.type === \"daterange\";\n case \"datetime\":\n // Date must be datetime_value without time component (YYYY-MM-DD only)\n if (content.type === \"datetime_value\") {\n return content.time === null;\n }\n return false;\n case \"number\":\n // Must be a number value\n return content.type === \"number_value\";\n }\n}\n\n/**\n * Check if content matches a literal type\n */\nfunction matchesLiteralContent(content: ValueContent, expectedValue: string): boolean {\n // Literal types require quoted values\n if (content.type === \"quoted_value\") {\n return content.value === expectedValue;\n }\n return false;\n}\n\n/**\n * Check if content matches an array type.\n * Arrays can be:\n * 1. A value_array (comma-separated: ^ref1, ^ref2)\n * 2. A single value that matches the element type\n */\nfunction matchesArrayContent(\n content: ValueContent,\n elementType: ModelPrimitiveType | ModelLiteralType | ModelUnionType | ModelUnknownType,\n): boolean {\n // Unknown element types can't be validated - accept any value\n if (elementType.kind === \"unknown\") {\n return true;\n }\n // If it's a value_array, validate each element\n if (content.type === \"value_array\") {\n // Empty arrays are not allowed\n if (content.elements.length === 0) {\n return false;\n }\n // Each element must match the element type\n return content.elements.every((element) => matchesArrayElementContent(element, elementType));\n }\n\n // Single value - check if it matches the element type directly\n return matchesSingleValueAsArrayElement(content, elementType);\n}\n\n/**\n * Check if a single (non-array) value matches an array element type\n */\nfunction matchesSingleValueAsArrayElement(\n content: ValueContent,\n elementType: ModelPrimitiveType | ModelLiteralType | ModelUnionType,\n): boolean {\n // Reject empty values (grammar may parse empty as quoted_value)\n if (content.type === \"quoted_value\" && content.value === \"\") {\n return false;\n }\n\n switch (elementType.kind) {\n case \"primitive\":\n return matchesSingleValueAsPrimitive(content, elementType.name);\n case \"literal\":\n // Must be a quoted value with matching content\n if (content.type === \"quoted_value\") {\n return content.value === elementType.value;\n }\n return false;\n case \"union\":\n return elementType.members.some((member) => {\n if (member.kind === \"primitive\") {\n return matchesSingleValueAsPrimitive(content, member.name);\n } else if (member.kind === \"literal\") {\n return content.type === \"quoted_value\" && content.value === member.value;\n }\n return false;\n });\n }\n}\n\n/**\n * Check if a single value matches a primitive type (for single-element arrays)\n */\nfunction matchesSingleValueAsPrimitive(\n content: ValueContent,\n type: \"string\" | \"datetime\" | \"daterange\" | \"link\" | \"number\",\n): boolean {\n switch (type) {\n case \"string\":\n // String in array must be quoted and non-empty\n return content.type === \"quoted_value\" && content.value.length > 0;\n case \"link\":\n return content.type === \"link_value\";\n case \"daterange\":\n return content.type === \"daterange\";\n case \"datetime\":\n // Date must be datetime_value without time component (YYYY-MM-DD only)\n if (content.type === \"datetime_value\") {\n return content.time === null;\n }\n return false;\n case \"number\":\n return content.type === \"number_value\";\n }\n}\n\n/**\n * Check if an array element matches the expected element type\n */\nfunction matchesArrayElementContent(\n element: Link | QuotedValue | DatetimeValue | DaterangeValue | NumberValue | Query,\n elementType: ModelPrimitiveType | ModelLiteralType | ModelUnionType,\n): boolean {\n switch (elementType.kind) {\n case \"primitive\":\n return matchesArrayPrimitiveContent(element, elementType.name);\n case \"literal\":\n // Must be a quoted value with matching content\n if (element.type === \"quoted_value\") {\n return element.value === elementType.value;\n }\n return false;\n case \"union\":\n return elementType.members.some((member) => {\n if (member.kind === \"primitive\") {\n return matchesArrayPrimitiveContent(element, member.name);\n } else if (member.kind === \"literal\") {\n return element.type === \"quoted_value\" && element.value === member.value;\n }\n // Nested arrays not supported\n return false;\n });\n }\n}\n\n/**\n * Check if an array element matches a primitive type\n */\nfunction matchesArrayPrimitiveContent(\n element: Link | QuotedValue | DatetimeValue | DaterangeValue | NumberValue | Query,\n type: \"string\" | \"datetime\" | \"daterange\" | \"link\" | \"number\",\n): boolean {\n switch (type) {\n case \"string\":\n // Strings in arrays must be quoted\n return element.type === \"quoted_value\";\n case \"link\":\n return element.type === \"link\";\n case \"datetime\":\n // Date in arrays must be datetime_value without time (YYYY-MM-DD only)\n if (element.type === \"datetime_value\") {\n return element.time === null;\n }\n return false;\n case \"daterange\":\n // Date ranges parsed by grammar are valid\n if (element.type === \"daterange\") {\n return true;\n }\n // Also accept quoted date ranges\n if (element.type === \"quoted_value\") {\n return /^\\d{4}(-\\d{2}(-\\d{2})?)?\\s*~\\s*\\d{4}(-\\d{2}(-\\d{2})?)?$/.test(element.value);\n }\n return false;\n case \"number\":\n return element.type === \"number_value\";\n }\n}\n\n// ===================\n// Default value matching\n// ===================\n\n/**\n * Check if a default value matches a primitive type\n */\nfunction matchesDefaultPrimitive(\n defaultValue: ModelDefaultValue,\n type: \"string\" | \"datetime\" | \"daterange\" | \"link\" | \"number\",\n): boolean {\n switch (type) {\n case \"string\":\n // Any default value can be coerced to string\n return true;\n case \"link\":\n return defaultValue.kind === \"link\";\n case \"datetime\":\n // Date must be datetime without time component (YYYY-MM-DD only)\n if (defaultValue.kind === \"datetime\") {\n return !defaultValue.value.includes(\"T\");\n }\n return false;\n case \"daterange\":\n // Default values can't be date ranges (grammar doesn't support it)\n return false;\n case \"number\":\n return defaultValue.kind === \"number\";\n }\n}\n\n/**\n * Check if a default value matches as a single array element\n */\nfunction matchesDefaultAsArrayElement(\n defaultValue: ModelDefaultValue,\n elementType: ModelPrimitiveType | ModelLiteralType | ModelUnionType | ModelUnknownType,\n): boolean {\n switch (elementType.kind) {\n case \"primitive\":\n return matchesDefaultAsPrimitive(defaultValue, elementType.name);\n case \"literal\":\n return defaultValue.kind === \"quoted\" && defaultValue.value === elementType.value;\n case \"union\":\n return elementType.members.some((member) => {\n if (member.kind === \"primitive\") {\n return matchesDefaultAsPrimitive(defaultValue, member.name);\n } else if (member.kind === \"literal\") {\n return defaultValue.kind === \"quoted\" && defaultValue.value === member.value;\n }\n return false;\n });\n case \"unknown\":\n // Unknown types can't be validated - accept any default value\n return true;\n }\n}\n\n/**\n * Check if a default value matches a primitive type as array element\n */\nfunction matchesDefaultAsPrimitive(\n defaultValue: ModelDefaultValue,\n type: \"string\" | \"datetime\" | \"daterange\" | \"link\" | \"number\",\n): boolean {\n switch (type) {\n case \"string\":\n // String in array context requires quoted value\n return defaultValue.kind === \"quoted\" && defaultValue.value.length > 0;\n case \"link\":\n return defaultValue.kind === \"link\";\n case \"datetime\":\n if (defaultValue.kind === \"datetime\") {\n return !defaultValue.value.includes(\"T\");\n }\n return false;\n case \"daterange\":\n // Default values can't be date ranges\n return false;\n case \"number\":\n return defaultValue.kind === \"number\";\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,107 @@
1
+ import { Entry, Location, SchemaEntry, SourceFile } from "../ast/ast-types.js";
2
+ import { SourceMap } from "../source-map.js";
3
+ import { GenericTree, ParsedBlock } from "../parser.shared.js";
4
+
5
+ //#region src/semantic/analyzer.d.ts
6
+
7
+ /**
8
+ * A link definition in an entry header.
9
+ * Created when an entry has an explicit ^linkId in its header.
10
+ */
11
+ interface LinkDefinition {
12
+ /** The link ID (without ^ prefix) */
13
+ id: string;
14
+ /** The file path containing this definition */
15
+ file: string;
16
+ /** Location of the link in the source */
17
+ location: Location;
18
+ /** The entry that defines this link */
19
+ entry: Entry;
20
+ }
21
+ /**
22
+ * A link reference in metadata or as an actualize target.
23
+ * Created when an entry references another entry via ^linkId.
24
+ */
25
+ interface LinkReference {
26
+ /** The link ID (without ^ prefix) */
27
+ id: string;
28
+ /** The file path containing this reference */
29
+ file: string;
30
+ /** Location of the link in the source */
31
+ location: Location;
32
+ /** The entry containing this reference */
33
+ entry: Entry;
34
+ /** The context where this reference appears (metadata key or "target") */
35
+ context: string;
36
+ }
37
+ /**
38
+ * Index for link definitions and references within a document.
39
+ */
40
+ interface LinkIndex {
41
+ /** Map from link ID to its definition (if any) */
42
+ definitions: Map<string, LinkDefinition>;
43
+ /** Map from link ID to all references */
44
+ references: Map<string, LinkReference[]>;
45
+ }
46
+ /**
47
+ * A semantic model for a single document.
48
+ * Contains the AST plus indexes built during semantic analysis.
49
+ *
50
+ * This is the per-document semantic representation. The Workspace
51
+ * aggregates multiple SemanticModels and combines their indexes.
52
+ */
53
+ interface SemanticModel {
54
+ /** The AST for this document */
55
+ ast: SourceFile;
56
+ /** The file path */
57
+ file: string;
58
+ /** The original source text */
59
+ source: string;
60
+ /** Source map for position translation (block-relative to file-absolute) */
61
+ sourceMap: SourceMap;
62
+ /** The parsed blocks (containing tree-sitter trees) for CST operations */
63
+ blocks: ParsedBlock<GenericTree>[];
64
+ /**
65
+ * Link index for this document.
66
+ * Contains definitions and references found in this document only.
67
+ */
68
+ linkIndex: LinkIndex;
69
+ /**
70
+ * Schema entries from this document.
71
+ * These are used by the SchemaRegistry at the workspace level
72
+ * to build resolved entity schemas.
73
+ */
74
+ schemaEntries: SchemaEntry[];
75
+ /**
76
+ * Dirty flags for incremental updates.
77
+ * When true, the corresponding index needs to be rebuilt.
78
+ */
79
+ dirty?: SemanticModelDirtyFlags;
80
+ }
81
+ /**
82
+ * Dirty flags indicating which parts of the semantic model need rebuilding.
83
+ */
84
+ interface SemanticModelDirtyFlags {
85
+ /** Link index needs rebuild (definitions or references changed) */
86
+ linkIndex: boolean;
87
+ /** Schema entries need re-extraction (schema entries changed) */
88
+ schemaEntries: boolean;
89
+ }
90
+ /**
91
+ * Result of an incremental semantic model update.
92
+ */
93
+ interface SemanticUpdateResult {
94
+ /** Link IDs that were added (new definitions) */
95
+ addedLinkDefinitions: string[];
96
+ /** Link IDs that were removed (deleted definitions) */
97
+ removedLinkDefinitions: string[];
98
+ /** Link IDs whose references changed */
99
+ changedLinkReferences: string[];
100
+ /** Whether schema entries changed */
101
+ schemaEntriesChanged: boolean;
102
+ /** Entity names whose schema definitions changed */
103
+ changedEntityNames: string[];
104
+ }
105
+ //#endregion
106
+ export { LinkDefinition, LinkIndex, LinkReference, SemanticModel, SemanticModelDirtyFlags, SemanticUpdateResult };
107
+ //# sourceMappingURL=analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"analyzer.d.ts","names":[],"sources":["../../src/semantic/analyzer.ts"],"sourcesContent":[],"mappings":";;;;;;;;AAYA;AAeA;AAgBiB,UA/BA,cAAA,CA+BS;EAEC;EAAZ,EAAA,EAAA,MAAA;EAEW;EAAZ,IAAA,EAAA,MAAA;EAAG;EAcA,QAAA,EA3CL,QA2CkB;EAEvB;EAMM,KAAA,EAjDJ,KAiDI;;;;;;AAqBoB,UA/DhB,aAAA,CA+DgB;EAMhB;EAUA,EAAA,EAAA,MAAA;;;;YAzEL;;SAEH;;;;;;;UAQQ,SAAA;;eAEF,YAAY;;cAEb,YAAY;;;;;;;;;UAcT,aAAA;;OAEV;;;;;;aAMM;;UAEH,YAAY;;;;;aAMT;;;;;;iBAOI;;;;;UAMP;;;;;UAMO,uBAAA;;;;;;;;;UAUA,oBAAA"}