@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,85 @@
1
+ //#region src/model/line-index.d.ts
2
+ /**
3
+ * A simple position (line and column).
4
+ * Both are 0-based to match tree-sitter's Point type.
5
+ */
6
+ interface Position {
7
+ /** 0-based line number */
8
+ line: number;
9
+ /** 0-based column number */
10
+ column: number;
11
+ }
12
+ /**
13
+ * Tree-sitter Point interface (row and column).
14
+ * Defined locally to avoid bundling native tree-sitter.
15
+ */
16
+ interface Point {
17
+ row: number;
18
+ column: number;
19
+ }
20
+ /**
21
+ * LineIndex provides O(log n) offset-to-position and position-to-offset conversions.
22
+ * It maintains an array of line start offsets for efficient lookups.
23
+ */
24
+ declare class LineIndex {
25
+ /** Array of character offsets where each line starts */
26
+ private readonly lineStarts;
27
+ /** Total length of the source text */
28
+ private readonly length;
29
+ constructor(source: string);
30
+ /**
31
+ * Get the number of lines in the source.
32
+ */
33
+ get lineCount(): number;
34
+ /**
35
+ * Convert a character offset to a Position (line, column).
36
+ * Uses binary search for O(log n) performance.
37
+ *
38
+ * @param offset - 0-based character offset
39
+ * @returns Position with 0-based line and column
40
+ */
41
+ offsetToPosition(offset: number): Position;
42
+ /**
43
+ * Convert a Position to a character offset.
44
+ *
45
+ * @param position - Position with 0-based line and column
46
+ * @returns 0-based character offset
47
+ */
48
+ positionToOffset(position: Position): number;
49
+ /**
50
+ * Convert a character offset to a tree-sitter Point.
51
+ */
52
+ offsetToPoint(offset: number): Point;
53
+ /**
54
+ * Convert a tree-sitter Point to a character offset.
55
+ */
56
+ pointToOffset(point: Point): number;
57
+ /**
58
+ * Get the character offset where a line starts.
59
+ *
60
+ * @param line - 0-based line number
61
+ * @returns Character offset, or -1 if line is out of range
62
+ */
63
+ getLineStart(line: number): number;
64
+ /**
65
+ * Get the character offset where a line ends (before the newline).
66
+ *
67
+ * @param line - 0-based line number
68
+ * @returns Character offset, or -1 if line is out of range
69
+ */
70
+ getLineEnd(line: number): number;
71
+ /**
72
+ * Create a new LineIndex with an edit applied.
73
+ * This is useful for computing edit ranges for tree-sitter.
74
+ *
75
+ * @param startOffset - Start of the edit range
76
+ * @param oldEndOffset - End of the old text being replaced
77
+ * @param newText - The new text being inserted
78
+ * @param fullNewSource - The complete new source text
79
+ * @returns A new LineIndex for the edited source
80
+ */
81
+ static fromEdit(_startOffset: number, _oldEndOffset: number, _newText: string, fullNewSource: string): LineIndex;
82
+ }
83
+ //#endregion
84
+ export { LineIndex, Position };
85
+ //# sourceMappingURL=line-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-index.d.ts","names":[],"sources":["../../src/model/line-index.ts"],"sourcesContent":[],"mappings":";;AAIA;AAKC;AAeD;AA+BoC,UAnDnB,QAAA,CAmDmB;EA6BP;EAuBI,IAAA,EAAA,MAAA;EAQV;EAiDlB,MAAA,EAAA,MAAA;;;;;;UArJK,KAAA;;;;;;;;cASG,SAAA;;;;;;;;;;;;;;;;;oCA+BuB;;;;;;;6BA6BP;;;;iCAuBI;;;;uBAQV;;;;;;;;;;;;;;;;;;;;;;;;;yGAiDlB"}
@@ -0,0 +1,159 @@
1
+ //#region src/model/line-index.ts
2
+ /**
3
+ * LineIndex provides O(log n) offset-to-position and position-to-offset conversions.
4
+ * It maintains an array of line start offsets for efficient lookups.
5
+ */
6
+ var LineIndex = class LineIndex {
7
+ /** Array of character offsets where each line starts */
8
+ lineStarts;
9
+ /** Total length of the source text */
10
+ length;
11
+ constructor(source) {
12
+ this.lineStarts = [0];
13
+ this.length = source.length;
14
+ for (let i = 0; i < source.length; i++) if (source[i] === "\n") this.lineStarts.push(i + 1);
15
+ }
16
+ /**
17
+ * Get the number of lines in the source.
18
+ */
19
+ get lineCount() {
20
+ return this.lineStarts.length;
21
+ }
22
+ /**
23
+ * Convert a character offset to a Position (line, column).
24
+ * Uses binary search for O(log n) performance.
25
+ *
26
+ * @param offset - 0-based character offset
27
+ * @returns Position with 0-based line and column
28
+ */
29
+ offsetToPosition(offset) {
30
+ const clampedOffset = Math.max(0, Math.min(offset, this.length));
31
+ let low = 0;
32
+ let high = this.lineStarts.length - 1;
33
+ while (low < high) {
34
+ const mid = Math.floor((low + high + 1) / 2);
35
+ if (this.lineStarts[mid] <= clampedOffset) low = mid;
36
+ else high = mid - 1;
37
+ }
38
+ const line = low;
39
+ return {
40
+ line,
41
+ column: clampedOffset - this.lineStarts[line]
42
+ };
43
+ }
44
+ /**
45
+ * Convert a Position to a character offset.
46
+ *
47
+ * @param position - Position with 0-based line and column
48
+ * @returns 0-based character offset
49
+ */
50
+ positionToOffset(position) {
51
+ const { line, column } = position;
52
+ const clampedLine = Math.max(0, Math.min(line, this.lineStarts.length - 1));
53
+ const lineStart = this.lineStarts[clampedLine];
54
+ const maxColumn = (clampedLine < this.lineStarts.length - 1 ? this.lineStarts[clampedLine + 1] - 1 : this.length) - lineStart;
55
+ return lineStart + Math.max(0, Math.min(column, maxColumn));
56
+ }
57
+ /**
58
+ * Convert a character offset to a tree-sitter Point.
59
+ */
60
+ offsetToPoint(offset) {
61
+ const pos = this.offsetToPosition(offset);
62
+ return {
63
+ row: pos.line,
64
+ column: pos.column
65
+ };
66
+ }
67
+ /**
68
+ * Convert a tree-sitter Point to a character offset.
69
+ */
70
+ pointToOffset(point) {
71
+ return this.positionToOffset({
72
+ line: point.row,
73
+ column: point.column
74
+ });
75
+ }
76
+ /**
77
+ * Get the character offset where a line starts.
78
+ *
79
+ * @param line - 0-based line number
80
+ * @returns Character offset, or -1 if line is out of range
81
+ */
82
+ getLineStart(line) {
83
+ if (line < 0 || line >= this.lineStarts.length) return -1;
84
+ return this.lineStarts[line];
85
+ }
86
+ /**
87
+ * Get the character offset where a line ends (before the newline).
88
+ *
89
+ * @param line - 0-based line number
90
+ * @returns Character offset, or -1 if line is out of range
91
+ */
92
+ getLineEnd(line) {
93
+ if (line < 0 || line >= this.lineStarts.length) return -1;
94
+ if (line === this.lineStarts.length - 1) return this.length;
95
+ return this.lineStarts[line + 1] - 1;
96
+ }
97
+ /**
98
+ * Create a new LineIndex with an edit applied.
99
+ * This is useful for computing edit ranges for tree-sitter.
100
+ *
101
+ * @param startOffset - Start of the edit range
102
+ * @param oldEndOffset - End of the old text being replaced
103
+ * @param newText - The new text being inserted
104
+ * @param fullNewSource - The complete new source text
105
+ * @returns A new LineIndex for the edited source
106
+ */
107
+ static fromEdit(_startOffset, _oldEndOffset, _newText, fullNewSource) {
108
+ return new LineIndex(fullNewSource);
109
+ }
110
+ };
111
+ /**
112
+ * Compute tree-sitter edit parameters from an LSP-style text edit.
113
+ *
114
+ * @param lineIndex - The line index for the current source
115
+ * @param startLine - 0-based start line
116
+ * @param startColumn - 0-based start column
117
+ * @param endLine - 0-based end line
118
+ * @param endColumn - 0-based end column
119
+ * @param newText - The replacement text
120
+ * @returns Edit parameters for tree-sitter's Tree.edit()
121
+ */
122
+ function computeEdit(lineIndex, startLine, startColumn, endLine, endColumn, newText) {
123
+ const startIndex = lineIndex.positionToOffset({
124
+ line: startLine,
125
+ column: startColumn
126
+ });
127
+ const oldEndIndex = lineIndex.positionToOffset({
128
+ line: endLine,
129
+ column: endColumn
130
+ });
131
+ const newEndIndex = startIndex + newText.length;
132
+ let newEndLine = startLine;
133
+ let newEndColumn = startColumn;
134
+ for (const char of newText) if (char === "\n") {
135
+ newEndLine++;
136
+ newEndColumn = 0;
137
+ } else newEndColumn++;
138
+ return {
139
+ startIndex,
140
+ oldEndIndex,
141
+ newEndIndex,
142
+ startPosition: {
143
+ row: startLine,
144
+ column: startColumn
145
+ },
146
+ oldEndPosition: {
147
+ row: endLine,
148
+ column: endColumn
149
+ },
150
+ newEndPosition: {
151
+ row: newEndLine,
152
+ column: newEndColumn
153
+ }
154
+ };
155
+ }
156
+
157
+ //#endregion
158
+ export { LineIndex, computeEdit };
159
+ //# sourceMappingURL=line-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line-index.js","names":[],"sources":["../../src/model/line-index.ts"],"sourcesContent":["/**\n * A simple position (line and column).\n * Both are 0-based to match tree-sitter's Point type.\n */\nexport interface Position {\n /** 0-based line number */\n line: number;\n /** 0-based column number */\n column: number;\n}\n\n/**\n * Tree-sitter Point interface (row and column).\n * Defined locally to avoid bundling native tree-sitter.\n */\ninterface Point {\n row: number;\n column: number;\n}\n\n/**\n * LineIndex provides O(log n) offset-to-position and position-to-offset conversions.\n * It maintains an array of line start offsets for efficient lookups.\n */\nexport class LineIndex {\n /** Array of character offsets where each line starts */\n private readonly lineStarts: number[];\n /** Total length of the source text */\n private readonly length: number;\n\n constructor(source: string) {\n this.lineStarts = [0]; // Line 0 starts at offset 0\n this.length = source.length;\n\n for (let i = 0; i < source.length; i++) {\n if (source[i] === \"\\n\") {\n this.lineStarts.push(i + 1);\n }\n }\n }\n\n /**\n * Get the number of lines in the source.\n */\n get lineCount(): number {\n return this.lineStarts.length;\n }\n\n /**\n * Convert a character offset to a Position (line, column).\n * Uses binary search for O(log n) performance.\n *\n * @param offset - 0-based character offset\n * @returns Position with 0-based line and column\n */\n offsetToPosition(offset: number): Position {\n // Clamp offset to valid range\n const clampedOffset = Math.max(0, Math.min(offset, this.length));\n\n // Binary search to find the line\n let low = 0;\n let high = this.lineStarts.length - 1;\n\n while (low < high) {\n const mid = Math.floor((low + high + 1) / 2);\n if (this.lineStarts[mid] <= clampedOffset) {\n low = mid;\n } else {\n high = mid - 1;\n }\n }\n\n const line = low;\n const column = clampedOffset - this.lineStarts[line];\n\n return { line, column };\n }\n\n /**\n * Convert a Position to a character offset.\n *\n * @param position - Position with 0-based line and column\n * @returns 0-based character offset\n */\n positionToOffset(position: Position): number {\n const { line, column } = position;\n\n // Clamp line to valid range\n const clampedLine = Math.max(0, Math.min(line, this.lineStarts.length - 1));\n const lineStart = this.lineStarts[clampedLine];\n\n // Calculate max column for this line\n const lineEnd =\n clampedLine < this.lineStarts.length - 1\n ? this.lineStarts[clampedLine + 1] - 1 // Don't include the newline\n : this.length;\n const maxColumn = lineEnd - lineStart;\n\n // Clamp column to valid range\n const clampedColumn = Math.max(0, Math.min(column, maxColumn));\n\n return lineStart + clampedColumn;\n }\n\n /**\n * Convert a character offset to a tree-sitter Point.\n */\n offsetToPoint(offset: number): Point {\n const pos = this.offsetToPosition(offset);\n return { row: pos.line, column: pos.column };\n }\n\n /**\n * Convert a tree-sitter Point to a character offset.\n */\n pointToOffset(point: Point): number {\n return this.positionToOffset({ line: point.row, column: point.column });\n }\n\n /**\n * Get the character offset where a line starts.\n *\n * @param line - 0-based line number\n * @returns Character offset, or -1 if line is out of range\n */\n getLineStart(line: number): number {\n if (line < 0 || line >= this.lineStarts.length) {\n return -1;\n }\n return this.lineStarts[line];\n }\n\n /**\n * Get the character offset where a line ends (before the newline).\n *\n * @param line - 0-based line number\n * @returns Character offset, or -1 if line is out of range\n */\n getLineEnd(line: number): number {\n if (line < 0 || line >= this.lineStarts.length) {\n return -1;\n }\n if (line === this.lineStarts.length - 1) {\n return this.length;\n }\n // Return position before the newline character\n return this.lineStarts[line + 1] - 1;\n }\n\n /**\n * Create a new LineIndex with an edit applied.\n * This is useful for computing edit ranges for tree-sitter.\n *\n * @param startOffset - Start of the edit range\n * @param oldEndOffset - End of the old text being replaced\n * @param newText - The new text being inserted\n * @param fullNewSource - The complete new source text\n * @returns A new LineIndex for the edited source\n */\n static fromEdit(\n _startOffset: number,\n _oldEndOffset: number,\n _newText: string,\n fullNewSource: string,\n ): LineIndex {\n // For now, just rebuild from scratch\n // A more sophisticated implementation could incrementally update lineStarts\n return new LineIndex(fullNewSource);\n }\n}\n\n/**\n * Compute tree-sitter edit parameters from an LSP-style text edit.\n *\n * @param lineIndex - The line index for the current source\n * @param startLine - 0-based start line\n * @param startColumn - 0-based start column\n * @param endLine - 0-based end line\n * @param endColumn - 0-based end column\n * @param newText - The replacement text\n * @returns Edit parameters for tree-sitter's Tree.edit()\n */\nexport function computeEdit(\n lineIndex: LineIndex,\n startLine: number,\n startColumn: number,\n endLine: number,\n endColumn: number,\n newText: string,\n): {\n startIndex: number;\n oldEndIndex: number;\n newEndIndex: number;\n startPosition: Point;\n oldEndPosition: Point;\n newEndPosition: Point;\n} {\n const startIndex = lineIndex.positionToOffset({ line: startLine, column: startColumn });\n const oldEndIndex = lineIndex.positionToOffset({ line: endLine, column: endColumn });\n\n // Calculate the new end position\n const newEndIndex = startIndex + newText.length;\n\n // Count lines in the new text to determine new end position\n let newEndLine = startLine;\n let newEndColumn = startColumn;\n\n for (const char of newText) {\n if (char === \"\\n\") {\n newEndLine++;\n newEndColumn = 0;\n } else {\n newEndColumn++;\n }\n }\n\n return {\n startIndex,\n oldEndIndex,\n newEndIndex,\n startPosition: { row: startLine, column: startColumn },\n oldEndPosition: { row: endLine, column: endColumn },\n newEndPosition: { row: newEndLine, column: newEndColumn },\n };\n}\n"],"mappings":";;;;;AAwBA,IAAa,YAAb,MAAa,UAAU;;CAErB,AAAiB;;CAEjB,AAAiB;CAEjB,YAAY,QAAgB;AAC1B,OAAK,aAAa,CAAC,EAAE;AACrB,OAAK,SAAS,OAAO;AAErB,OAAK,IAAI,IAAI,GAAG,IAAI,OAAO,QAAQ,IACjC,KAAI,OAAO,OAAO,KAChB,MAAK,WAAW,KAAK,IAAI,EAAE;;;;;CAQjC,IAAI,YAAoB;AACtB,SAAO,KAAK,WAAW;;;;;;;;;CAUzB,iBAAiB,QAA0B;EAEzC,MAAM,gBAAgB,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,KAAK,OAAO,CAAC;EAGhE,IAAI,MAAM;EACV,IAAI,OAAO,KAAK,WAAW,SAAS;AAEpC,SAAO,MAAM,MAAM;GACjB,MAAM,MAAM,KAAK,OAAO,MAAM,OAAO,KAAK,EAAE;AAC5C,OAAI,KAAK,WAAW,QAAQ,cAC1B,OAAM;OAEN,QAAO,MAAM;;EAIjB,MAAM,OAAO;AAGb,SAAO;GAAE;GAAM,QAFA,gBAAgB,KAAK,WAAW;GAExB;;;;;;;;CASzB,iBAAiB,UAA4B;EAC3C,MAAM,EAAE,MAAM,WAAW;EAGzB,MAAM,cAAc,KAAK,IAAI,GAAG,KAAK,IAAI,MAAM,KAAK,WAAW,SAAS,EAAE,CAAC;EAC3E,MAAM,YAAY,KAAK,WAAW;EAOlC,MAAM,aAHJ,cAAc,KAAK,WAAW,SAAS,IACnC,KAAK,WAAW,cAAc,KAAK,IACnC,KAAK,UACiB;AAK5B,SAAO,YAFe,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,UAAU,CAAC;;;;;CAQhE,cAAc,QAAuB;EACnC,MAAM,MAAM,KAAK,iBAAiB,OAAO;AACzC,SAAO;GAAE,KAAK,IAAI;GAAM,QAAQ,IAAI;GAAQ;;;;;CAM9C,cAAc,OAAsB;AAClC,SAAO,KAAK,iBAAiB;GAAE,MAAM,MAAM;GAAK,QAAQ,MAAM;GAAQ,CAAC;;;;;;;;CASzE,aAAa,MAAsB;AACjC,MAAI,OAAO,KAAK,QAAQ,KAAK,WAAW,OACtC,QAAO;AAET,SAAO,KAAK,WAAW;;;;;;;;CASzB,WAAW,MAAsB;AAC/B,MAAI,OAAO,KAAK,QAAQ,KAAK,WAAW,OACtC,QAAO;AAET,MAAI,SAAS,KAAK,WAAW,SAAS,EACpC,QAAO,KAAK;AAGd,SAAO,KAAK,WAAW,OAAO,KAAK;;;;;;;;;;;;CAarC,OAAO,SACL,cACA,eACA,UACA,eACW;AAGX,SAAO,IAAI,UAAU,cAAc;;;;;;;;;;;;;;AAevC,SAAgB,YACd,WACA,WACA,aACA,SACA,WACA,SAQA;CACA,MAAM,aAAa,UAAU,iBAAiB;EAAE,MAAM;EAAW,QAAQ;EAAa,CAAC;CACvF,MAAM,cAAc,UAAU,iBAAiB;EAAE,MAAM;EAAS,QAAQ;EAAW,CAAC;CAGpF,MAAM,cAAc,aAAa,QAAQ;CAGzC,IAAI,aAAa;CACjB,IAAI,eAAe;AAEnB,MAAK,MAAM,QAAQ,QACjB,KAAI,SAAS,MAAM;AACjB;AACA,iBAAe;OAEf;AAIJ,QAAO;EACL;EACA;EACA;EACA,eAAe;GAAE,KAAK;GAAW,QAAQ;GAAa;EACtD,gBAAgB;GAAE,KAAK;GAAS,QAAQ;GAAW;EACnD,gBAAgB;GAAE,KAAK;GAAY,QAAQ;GAAc;EAC1D"}
@@ -0,0 +1,296 @@
1
+ import { ActualizeEntry, Entry, InstanceEntry, Location, SchemaEntry, SynthesisEntry } from "../ast/ast-types.js";
2
+ import { SourceMap } from "../source-map.js";
3
+ import { FileType, GenericTree, ThaloParser } from "../parser.shared.js";
4
+ import { LinkDefinition, LinkIndex, LinkReference, SemanticModel } from "../semantic/analyzer.js";
5
+ import { SchemaRegistry } from "../schema/registry.js";
6
+ import { Document } from "./document.js";
7
+
8
+ //#region src/model/workspace.d.ts
9
+ /**
10
+ * A schema entry (define-entity/alter-entity)
11
+ */
12
+ interface ModelSchemaEntry {
13
+ kind: "schema";
14
+ /** The timestamp from the header */
15
+ timestamp: string;
16
+ /** The directive (define-entity or alter-entity) */
17
+ directive: "define-entity" | "alter-entity";
18
+ /** The entity name being defined/altered */
19
+ entityName: string;
20
+ /** The title/description */
21
+ title: string;
22
+ /** Explicit link ID from header (if any) */
23
+ linkId: string | null;
24
+ /** Tags from the header */
25
+ tags: string[];
26
+ /** Field definitions (for define/alter) */
27
+ fields: ModelFieldDefinition[];
28
+ /** Section definitions (for define/alter) */
29
+ sections: ModelSectionDefinition[];
30
+ /** Field removals (for alter) */
31
+ removeFields: string[];
32
+ /** Section removals (for alter) */
33
+ removeSections: string[];
34
+ /** Location in source (block-relative) */
35
+ location: Location;
36
+ /** The file path containing this entry */
37
+ file: string;
38
+ /** Source map for translating block-relative to file-absolute positions */
39
+ sourceMap: SourceMap;
40
+ }
41
+ /**
42
+ * A field definition from a schema entry
43
+ */
44
+ interface ModelFieldDefinition {
45
+ name: string;
46
+ optional: boolean;
47
+ type: ModelTypeExpression;
48
+ /** The typed default value content (quoted, link, or datetime) */
49
+ defaultValue: ModelDefaultValue | null;
50
+ description: string | null;
51
+ location: Location;
52
+ }
53
+ /**
54
+ * A typed default value from a field definition.
55
+ * Can be a quoted string, link reference, datetime, or number.
56
+ */
57
+ type ModelDefaultValue = {
58
+ kind: "quoted";
59
+ value: string;
60
+ raw: string;
61
+ } | {
62
+ kind: "link";
63
+ id: string;
64
+ raw: string;
65
+ } | {
66
+ kind: "datetime";
67
+ value: string;
68
+ raw: string;
69
+ } | {
70
+ kind: "number";
71
+ value: number;
72
+ raw: string;
73
+ };
74
+ /**
75
+ * A section definition from a schema entry
76
+ */
77
+ interface ModelSectionDefinition {
78
+ name: string;
79
+ optional: boolean;
80
+ description: string | null;
81
+ location: Location;
82
+ }
83
+ /**
84
+ * Type expressions in field definitions
85
+ */
86
+ type ModelTypeExpression = ModelPrimitiveType | ModelLiteralType | ModelArrayType | ModelUnionType | ModelUnknownType;
87
+ interface ModelPrimitiveType {
88
+ kind: "primitive";
89
+ name: "string" | "datetime" | "daterange" | "link" | "number";
90
+ }
91
+ /**
92
+ * An unknown/invalid type (e.g., typo like "date-time" instead of "datetime").
93
+ * Fields with this type are included in the schema but type validation is skipped.
94
+ */
95
+ interface ModelUnknownType {
96
+ kind: "unknown";
97
+ /** The unrecognized type name as written */
98
+ name: string;
99
+ }
100
+ interface ModelLiteralType {
101
+ kind: "literal";
102
+ value: string;
103
+ }
104
+ interface ModelArrayType {
105
+ kind: "array";
106
+ elementType: ModelPrimitiveType | ModelLiteralType | ModelUnionType | ModelUnknownType;
107
+ }
108
+ interface ModelUnionType {
109
+ kind: "union";
110
+ members: (ModelPrimitiveType | ModelLiteralType | ModelArrayType | ModelUnknownType)[];
111
+ }
112
+ /**
113
+ * Options for adding a document to the workspace
114
+ */
115
+ interface AddDocumentOptions {
116
+ /** The file type. If not provided, uses heuristics based on filename or content. */
117
+ fileType?: FileType;
118
+ /** The filename/path for the document (required for workspace indexing) */
119
+ filename: string;
120
+ }
121
+ /**
122
+ * Result of applying an edit or update to the workspace.
123
+ * Used for incremental diagnostics and targeted invalidation.
124
+ */
125
+ interface InvalidationResult {
126
+ /** Files whose diagnostics may have changed */
127
+ affectedFiles: string[];
128
+ /** Whether schema definitions changed (affects type checking) */
129
+ schemasChanged: boolean;
130
+ /** Whether link definitions changed (affects link resolution) */
131
+ linksChanged: boolean;
132
+ /** Entity names whose schemas changed */
133
+ changedEntityNames: string[];
134
+ /** Link IDs that were added or removed */
135
+ changedLinkIds: string[];
136
+ }
137
+ /**
138
+ * A workspace containing multiple thalo documents.
139
+ * Provides cross-file link resolution and schema management.
140
+ *
141
+ * The workspace is parser-agnostic - it accepts any parser that implements
142
+ * the ThaloParser interface, allowing it to work with both native (Node.js)
143
+ * and web (WASM) tree-sitter implementations.
144
+ *
145
+ * @example
146
+ * ```typescript
147
+ * // With native parser (Node.js) - parser is optional, defaults to native
148
+ * import { Workspace } from "@rejot-dev/thalo";
149
+ * const workspace = new Workspace();
150
+ *
151
+ * // With explicit parser
152
+ * import { createParser } from "@rejot-dev/thalo/native";
153
+ * const parser = createParser();
154
+ * const workspace = new Workspace(parser);
155
+ *
156
+ * // With web parser (browser)
157
+ * import { createParser } from "@rejot-dev/thalo/web";
158
+ * const parser = await createParser({ treeSitterWasm, languageWasm });
159
+ * const workspace = new Workspace(parser);
160
+ * ```
161
+ */
162
+ declare class Workspace {
163
+ private parser;
164
+ private models;
165
+ private documents;
166
+ private _schemaRegistry;
167
+ private _linkIndex;
168
+ private linkDependencies;
169
+ private entityDependencies;
170
+ /**
171
+ * Create a new Workspace.
172
+ *
173
+ * @param parser - A ThaloParser instance. For Node.js, use createParser() from "@rejot-dev/thalo".
174
+ * For browser, use createParser() from "@rejot-dev/thalo/web".
175
+ */
176
+ constructor(parser: ThaloParser<GenericTree>);
177
+ /**
178
+ * Get the schema registry for this workspace
179
+ */
180
+ get schemaRegistry(): SchemaRegistry;
181
+ /**
182
+ * Get the combined link index for all documents.
183
+ */
184
+ get linkIndex(): LinkIndex;
185
+ /**
186
+ * Add a document to the workspace.
187
+ */
188
+ addDocument(source: string, options: AddDocumentOptions): SemanticModel;
189
+ /**
190
+ * Remove a document from the workspace
191
+ */
192
+ removeDocument(file: string): void;
193
+ /**
194
+ * Get a SemanticModel by file path.
195
+ */
196
+ getModel(file: string): SemanticModel | undefined;
197
+ /**
198
+ * Check if a document exists
199
+ */
200
+ hasDocument(file: string): boolean;
201
+ /**
202
+ * Get all document file paths
203
+ */
204
+ files(): string[];
205
+ /**
206
+ * Get all SemanticModels.
207
+ */
208
+ allModels(): SemanticModel[];
209
+ /**
210
+ * Get all AST entries across all SemanticModels.
211
+ */
212
+ allEntries(): Entry[];
213
+ /**
214
+ * Get all instance entries (create/update) across all SemanticModels.
215
+ */
216
+ allInstanceEntries(): InstanceEntry[];
217
+ /**
218
+ * Get all schema entries (define-entity/alter-entity) across all SemanticModels.
219
+ */
220
+ allSchemaEntries(): SchemaEntry[];
221
+ /**
222
+ * Get all synthesis entries (define-synthesis) across all SemanticModels.
223
+ */
224
+ allSynthesisEntries(): SynthesisEntry[];
225
+ /**
226
+ * Get all actualize entries (actualize-synthesis) across all SemanticModels.
227
+ */
228
+ allActualizeEntries(): ActualizeEntry[];
229
+ /**
230
+ * Get the definition for a link ID
231
+ */
232
+ getLinkDefinition(id: string): LinkDefinition | undefined;
233
+ /**
234
+ * Get all references for a link ID
235
+ */
236
+ getLinkReferences(id: string): LinkReference[];
237
+ /**
238
+ * Get the Document instance for incremental editing.
239
+ * Returns undefined if the document hasn't been added with incremental support.
240
+ */
241
+ getDocument(file: string): Document<GenericTree> | undefined;
242
+ /**
243
+ * Apply an incremental edit to a document.
244
+ * This is more efficient than addDocument() for small edits.
245
+ *
246
+ * @param filename - The file to edit
247
+ * @param startLine - 0-based start line
248
+ * @param startColumn - 0-based start column
249
+ * @param endLine - 0-based end line
250
+ * @param endColumn - 0-based end column
251
+ * @param newText - The replacement text
252
+ * @returns Information about what was invalidated
253
+ */
254
+ applyEdit(filename: string, startLine: number, startColumn: number, endLine: number, endColumn: number, newText: string): InvalidationResult;
255
+ /**
256
+ * Update a document with new content.
257
+ * This replaces the entire document and recalculates all dependencies.
258
+ *
259
+ * @param filename - The file to update
260
+ * @param newSource - The new source content
261
+ * @returns Information about what was invalidated
262
+ */
263
+ updateDocument(filename: string, newSource: string): InvalidationResult;
264
+ /**
265
+ * Get files that would be affected by changes in a specific file.
266
+ * Useful for targeted diagnostics refresh.
267
+ */
268
+ getAffectedFiles(filename: string): string[];
269
+ /**
270
+ * Clear all documents
271
+ */
272
+ clear(): void;
273
+ /**
274
+ * Rebuild schema registry and link index from all models
275
+ */
276
+ private rebuild;
277
+ /**
278
+ * Merge a SemanticModel's links into the workspace link index
279
+ */
280
+ private mergeLinks;
281
+ /**
282
+ * Update entity dependencies for a model
283
+ */
284
+ private updateEntityDependencies;
285
+ /**
286
+ * Remove a file's dependencies from the tracking maps
287
+ */
288
+ private removeDependencies;
289
+ /**
290
+ * Update the semantic model from a Document's parse results.
291
+ */
292
+ private updateModelFromDocument;
293
+ }
294
+ //#endregion
295
+ export { InvalidationResult, ModelDefaultValue, ModelFieldDefinition, ModelSchemaEntry, ModelSectionDefinition, ModelTypeExpression, Workspace };
296
+ //# sourceMappingURL=workspace.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.d.ts","names":[],"sources":["../../src/model/workspace.ts"],"sourcesContent":[],"mappings":";;;;;;;;;;;UAUiB,gBAAA;;;EAAA,SAAA,EAAA,MAAA;EAeP;EAEE,SAAA,EAAA,eAAA,GAAA,cAAA;EAMA;EAIC,UAAA,EAAA,MAAA;EAAS;EAML,KAAA,EAAA,MAAA;EAGT;EAEQ,MAAA,EAAA,MAAA,GAAA,IAAA;EAEJ;EAAQ,IAAA,EAAA,MAAA,EAAA;EAOR;EASK,MAAA,EAzCP,oBAyC6B,EAAA;EAU3B;EACR,QAAA,EAlDQ,sBAkDR,EAAA;EACA;EACA,YAAA,EAAA,MAAA,EAAA;EACA;EACA,cAAA,EAAA,MAAA,EAAA;EAAgB;EAEH,QAAA,EAlDL,QAkDK;EASA;EAMA,IAAA,EAAA,MAAA;EAKA;EAEF,SAAA,EApEF,SAoEE;;;;;AAGE,UAjEA,oBAAA,CAiEc;EAEnB,IAAA,EAAA,MAAA;EAAqB,QAAA,EAAA,OAAA;EAAmB,IAAA,EAhE5C,mBAgE4C;EAAiB;EAAgB,YAAA,EA9DrE,iBA8DqE,GAAA,IAAA;EA+BpE,WAAA,EAAA,MAAA,GAAkB,IAAA;EAWlB,QAAA,EAtGL,QAsGK;AAsCjB;;;;;AA2CuC,KAhL3B,iBAAA,GAgL2B;EAAqB,IAAA,EAAA,QAAA;EAgFlC,KAAA,EAAA,MAAA;EAqBX,GAAA,EAAA,MAAA;CAOC,GAAA;EAWQ,IAAA,EAAA,MAAA;EAOF,EAAA,EAAA,MAAA;EAOG,GAAA,EAAA,MAAA;CAOA,GAAA;EAOQ,IAAA,EAAA,UAAA;EAOA,KAAA,EAAA,MAAA;EAQK,GAAA,EAAA,MAAA;CAAT,GAAA;EAuBxB,IAAA,EAAA,QAAA;EAsCkD,KAAA,EAAA,MAAA;EAAkB,GAAA,EAAA,MAAA;;;;;UAtYxD,sBAAA;;;;YAIL;;;;;KAMA,mBAAA,GACR,qBACA,mBACA,iBACA,iBACA;UAEa,kBAAA;;;;;;;;UASA,gBAAA;;;;;UAMA,gBAAA;;;;UAKA,cAAA;;eAEF,qBAAqB,mBAAmB,iBAAiB;;UAGvD,cAAA;;YAEL,qBAAqB,mBAAmB,iBAAiB;;;;;UA+BpD,kBAAA;;aAEJ;;;;;;;;UASI,kBAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsCJ,SAAA;;;;;;;;;;;;;;sBAsBS,YAAY;;;;wBAOV;;;;mBAOL;;;;uCAOoB,qBAAqB;;;;;;;;0BAgFlC;;;;;;;;;;;;eAqBX;;;;gBAOC;;;;wBAWQ;;;;sBAOF;;;;yBAOG;;;;yBAOA;;;;iCAOQ;;;;iCAOA;;;;;6BAQJ,SAAS;;;;;;;;;;;;;4HAuBjC;;;;;;;;;uDAsCkD"}