@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.
- package/LICENSE +21 -0
- package/README.md +396 -0
- package/dist/ast/ast-types.d.ts +469 -0
- package/dist/ast/ast-types.d.ts.map +1 -0
- package/dist/ast/ast-types.js +11 -0
- package/dist/ast/ast-types.js.map +1 -0
- package/dist/ast/builder.js +158 -0
- package/dist/ast/builder.js.map +1 -0
- package/dist/ast/extract.js +748 -0
- package/dist/ast/extract.js.map +1 -0
- package/dist/ast/node-at-position.d.ts +147 -0
- package/dist/ast/node-at-position.d.ts.map +1 -0
- package/dist/ast/node-at-position.js +382 -0
- package/dist/ast/node-at-position.js.map +1 -0
- package/dist/ast/visitor.js +232 -0
- package/dist/ast/visitor.js.map +1 -0
- package/dist/checker/check.d.ts +53 -0
- package/dist/checker/check.d.ts.map +1 -0
- package/dist/checker/check.js +105 -0
- package/dist/checker/check.js.map +1 -0
- package/dist/checker/rules/actualize-missing-updated.js +34 -0
- package/dist/checker/rules/actualize-missing-updated.js.map +1 -0
- package/dist/checker/rules/actualize-unresolved-target.js +42 -0
- package/dist/checker/rules/actualize-unresolved-target.js.map +1 -0
- package/dist/checker/rules/alter-before-define.js +53 -0
- package/dist/checker/rules/alter-before-define.js.map +1 -0
- package/dist/checker/rules/alter-undefined-entity.js +32 -0
- package/dist/checker/rules/alter-undefined-entity.js.map +1 -0
- package/dist/checker/rules/create-requires-section.js +34 -0
- package/dist/checker/rules/create-requires-section.js.map +1 -0
- package/dist/checker/rules/define-entity-requires-section.js +31 -0
- package/dist/checker/rules/define-entity-requires-section.js.map +1 -0
- package/dist/checker/rules/duplicate-entity-definition.js +37 -0
- package/dist/checker/rules/duplicate-entity-definition.js.map +1 -0
- package/dist/checker/rules/duplicate-field-in-schema.js +38 -0
- package/dist/checker/rules/duplicate-field-in-schema.js.map +1 -0
- package/dist/checker/rules/duplicate-link-id.js +52 -0
- package/dist/checker/rules/duplicate-link-id.js.map +1 -0
- package/dist/checker/rules/duplicate-metadata-key.js +21 -0
- package/dist/checker/rules/duplicate-metadata-key.js.map +1 -0
- package/dist/checker/rules/duplicate-section-heading.js +41 -0
- package/dist/checker/rules/duplicate-section-heading.js.map +1 -0
- package/dist/checker/rules/duplicate-section-in-schema.js +38 -0
- package/dist/checker/rules/duplicate-section-in-schema.js.map +1 -0
- package/dist/checker/rules/duplicate-timestamp.js +104 -0
- package/dist/checker/rules/duplicate-timestamp.js.map +1 -0
- package/dist/checker/rules/empty-required-value.js +45 -0
- package/dist/checker/rules/empty-required-value.js.map +1 -0
- package/dist/checker/rules/empty-section.js +21 -0
- package/dist/checker/rules/empty-section.js.map +1 -0
- package/dist/checker/rules/invalid-date-range-value.js +56 -0
- package/dist/checker/rules/invalid-date-range-value.js.map +1 -0
- package/dist/checker/rules/invalid-default-value.js +86 -0
- package/dist/checker/rules/invalid-default-value.js.map +1 -0
- package/dist/checker/rules/invalid-field-type.js +45 -0
- package/dist/checker/rules/invalid-field-type.js.map +1 -0
- package/dist/checker/rules/missing-required-field.js +48 -0
- package/dist/checker/rules/missing-required-field.js.map +1 -0
- package/dist/checker/rules/missing-required-section.js +51 -0
- package/dist/checker/rules/missing-required-section.js.map +1 -0
- package/dist/checker/rules/missing-title.js +56 -0
- package/dist/checker/rules/missing-title.js.map +1 -0
- package/dist/checker/rules/remove-undefined-field.js +42 -0
- package/dist/checker/rules/remove-undefined-field.js.map +1 -0
- package/dist/checker/rules/remove-undefined-section.js +42 -0
- package/dist/checker/rules/remove-undefined-section.js.map +1 -0
- package/dist/checker/rules/rules.d.ts +71 -0
- package/dist/checker/rules/rules.d.ts.map +1 -0
- package/dist/checker/rules/rules.js +102 -0
- package/dist/checker/rules/rules.js.map +1 -0
- package/dist/checker/rules/synthesis-empty-query.js +35 -0
- package/dist/checker/rules/synthesis-empty-query.js.map +1 -0
- package/dist/checker/rules/synthesis-missing-prompt.js +42 -0
- package/dist/checker/rules/synthesis-missing-prompt.js.map +1 -0
- package/dist/checker/rules/synthesis-missing-sources.js +32 -0
- package/dist/checker/rules/synthesis-missing-sources.js.map +1 -0
- package/dist/checker/rules/synthesis-unknown-query-entity.js +39 -0
- package/dist/checker/rules/synthesis-unknown-query-entity.js.map +1 -0
- package/dist/checker/rules/timestamp-out-of-order.js +55 -0
- package/dist/checker/rules/timestamp-out-of-order.js.map +1 -0
- package/dist/checker/rules/unknown-entity.js +32 -0
- package/dist/checker/rules/unknown-entity.js.map +1 -0
- package/dist/checker/rules/unknown-field.js +40 -0
- package/dist/checker/rules/unknown-field.js.map +1 -0
- package/dist/checker/rules/unknown-section.js +47 -0
- package/dist/checker/rules/unknown-section.js.map +1 -0
- package/dist/checker/rules/unresolved-link.js +34 -0
- package/dist/checker/rules/unresolved-link.js.map +1 -0
- package/dist/checker/rules/update-without-create.js +65 -0
- package/dist/checker/rules/update-without-create.js.map +1 -0
- package/dist/checker/visitor.d.ts +69 -0
- package/dist/checker/visitor.d.ts.map +1 -0
- package/dist/checker/visitor.js +67 -0
- package/dist/checker/visitor.js.map +1 -0
- package/dist/checker/workspace-index.d.ts +50 -0
- package/dist/checker/workspace-index.d.ts.map +1 -0
- package/dist/checker/workspace-index.js +108 -0
- package/dist/checker/workspace-index.js.map +1 -0
- package/dist/commands/actualize.d.ts +113 -0
- package/dist/commands/actualize.d.ts.map +1 -0
- package/dist/commands/actualize.js +111 -0
- package/dist/commands/actualize.js.map +1 -0
- package/dist/commands/check.d.ts +65 -0
- package/dist/commands/check.d.ts.map +1 -0
- package/dist/commands/check.js +61 -0
- package/dist/commands/check.js.map +1 -0
- package/dist/commands/format.d.ts +90 -0
- package/dist/commands/format.d.ts.map +1 -0
- package/dist/commands/format.js +80 -0
- package/dist/commands/format.js.map +1 -0
- package/dist/commands/query.d.ts +152 -0
- package/dist/commands/query.d.ts.map +1 -0
- package/dist/commands/query.js +151 -0
- package/dist/commands/query.js.map +1 -0
- package/dist/constants.d.ts +31 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +51 -0
- package/dist/constants.js.map +1 -0
- package/dist/files.d.ts +58 -0
- package/dist/files.d.ts.map +1 -0
- package/dist/files.js +103 -0
- package/dist/files.js.map +1 -0
- package/dist/formatters.d.ts +39 -0
- package/dist/formatters.d.ts.map +1 -0
- package/dist/formatters.js +200 -0
- package/dist/formatters.js.map +1 -0
- package/dist/fragment.d.ts +22 -0
- package/dist/fragment.d.ts.map +1 -0
- package/dist/git/git.js +240 -0
- package/dist/git/git.js.map +1 -0
- package/dist/merge/conflict-detector.d.ts +89 -0
- package/dist/merge/conflict-detector.d.ts.map +1 -0
- package/dist/merge/conflict-detector.js +352 -0
- package/dist/merge/conflict-detector.js.map +1 -0
- package/dist/merge/conflict-formatter.js +143 -0
- package/dist/merge/conflict-formatter.js.map +1 -0
- package/dist/merge/driver.d.ts +54 -0
- package/dist/merge/driver.d.ts.map +1 -0
- package/dist/merge/driver.js +112 -0
- package/dist/merge/driver.js.map +1 -0
- package/dist/merge/entry-matcher.d.ts +50 -0
- package/dist/merge/entry-matcher.d.ts.map +1 -0
- package/dist/merge/entry-matcher.js +141 -0
- package/dist/merge/entry-matcher.js.map +1 -0
- package/dist/merge/entry-merger.js +194 -0
- package/dist/merge/entry-merger.js.map +1 -0
- package/dist/merge/merge-result-builder.d.ts +62 -0
- package/dist/merge/merge-result-builder.d.ts.map +1 -0
- package/dist/merge/merge-result-builder.js +89 -0
- package/dist/merge/merge-result-builder.js.map +1 -0
- package/dist/mod.d.ts +31 -0
- package/dist/mod.js +23 -0
- package/dist/model/document.d.ts +134 -0
- package/dist/model/document.d.ts.map +1 -0
- package/dist/model/document.js +275 -0
- package/dist/model/document.js.map +1 -0
- package/dist/model/line-index.d.ts +85 -0
- package/dist/model/line-index.d.ts.map +1 -0
- package/dist/model/line-index.js +159 -0
- package/dist/model/line-index.js.map +1 -0
- package/dist/model/workspace.d.ts +296 -0
- package/dist/model/workspace.d.ts.map +1 -0
- package/dist/model/workspace.js +562 -0
- package/dist/model/workspace.js.map +1 -0
- package/dist/parser.js +27 -0
- package/dist/parser.js.map +1 -0
- package/dist/parser.native.d.ts +51 -0
- package/dist/parser.native.d.ts.map +1 -0
- package/dist/parser.native.js +62 -0
- package/dist/parser.native.js.map +1 -0
- package/dist/parser.shared.d.ts +99 -0
- package/dist/parser.shared.d.ts.map +1 -0
- package/dist/parser.shared.js +124 -0
- package/dist/parser.shared.js.map +1 -0
- package/dist/parser.web.d.ts +67 -0
- package/dist/parser.web.d.ts.map +1 -0
- package/dist/parser.web.js +49 -0
- package/dist/parser.web.js.map +1 -0
- package/dist/schema/registry.d.ts +108 -0
- package/dist/schema/registry.d.ts.map +1 -0
- package/dist/schema/registry.js +281 -0
- package/dist/schema/registry.js.map +1 -0
- package/dist/semantic/analyzer.d.ts +107 -0
- package/dist/semantic/analyzer.d.ts.map +1 -0
- package/dist/semantic/analyzer.js +261 -0
- package/dist/semantic/analyzer.js.map +1 -0
- package/dist/services/change-tracker/change-tracker.d.ts +111 -0
- package/dist/services/change-tracker/change-tracker.d.ts.map +1 -0
- package/dist/services/change-tracker/change-tracker.js +62 -0
- package/dist/services/change-tracker/change-tracker.js.map +1 -0
- package/dist/services/change-tracker/create-tracker.d.ts +42 -0
- package/dist/services/change-tracker/create-tracker.d.ts.map +1 -0
- package/dist/services/change-tracker/create-tracker.js +53 -0
- package/dist/services/change-tracker/create-tracker.js.map +1 -0
- package/dist/services/change-tracker/git-tracker.d.ts +59 -0
- package/dist/services/change-tracker/git-tracker.d.ts.map +1 -0
- package/dist/services/change-tracker/git-tracker.js +218 -0
- package/dist/services/change-tracker/git-tracker.js.map +1 -0
- package/dist/services/change-tracker/timestamp-tracker.d.ts +22 -0
- package/dist/services/change-tracker/timestamp-tracker.d.ts.map +1 -0
- package/dist/services/change-tracker/timestamp-tracker.js +74 -0
- package/dist/services/change-tracker/timestamp-tracker.js.map +1 -0
- package/dist/services/definition.d.ts +37 -0
- package/dist/services/definition.d.ts.map +1 -0
- package/dist/services/definition.js +43 -0
- package/dist/services/definition.js.map +1 -0
- package/dist/services/entity-navigation.d.ts +200 -0
- package/dist/services/entity-navigation.d.ts.map +1 -0
- package/dist/services/entity-navigation.js +211 -0
- package/dist/services/entity-navigation.js.map +1 -0
- package/dist/services/hover.d.ts +81 -0
- package/dist/services/hover.d.ts.map +1 -0
- package/dist/services/hover.js +669 -0
- package/dist/services/hover.js.map +1 -0
- package/dist/services/query.d.ts +116 -0
- package/dist/services/query.d.ts.map +1 -0
- package/dist/services/query.js +225 -0
- package/dist/services/query.js.map +1 -0
- package/dist/services/references.d.ts +52 -0
- package/dist/services/references.d.ts.map +1 -0
- package/dist/services/references.js +66 -0
- package/dist/services/references.js.map +1 -0
- package/dist/services/semantic-tokens.d.ts +54 -0
- package/dist/services/semantic-tokens.d.ts.map +1 -0
- package/dist/services/semantic-tokens.js +213 -0
- package/dist/services/semantic-tokens.js.map +1 -0
- package/dist/services/synthesis.d.ts +90 -0
- package/dist/services/synthesis.d.ts.map +1 -0
- package/dist/services/synthesis.js +113 -0
- package/dist/services/synthesis.js.map +1 -0
- package/dist/source-map.d.ts +42 -0
- package/dist/source-map.d.ts.map +1 -0
- package/dist/source-map.js +170 -0
- package/dist/source-map.js.map +1 -0
- package/package.json +128 -0
- package/tree-sitter-thalo.wasm +0 -0
- package/web-tree-sitter.wasm +0 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Workspace } from "../model/workspace.js";
|
|
2
|
+
import { CheckConfig } from "../checker/check.js";
|
|
3
|
+
|
|
4
|
+
//#region src/commands/check.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Severity levels for diagnostics
|
|
8
|
+
*/
|
|
9
|
+
type DiagnosticSeverity = "error" | "warning" | "info";
|
|
10
|
+
/**
|
|
11
|
+
* A single diagnostic (error, warning, or info) from the checker.
|
|
12
|
+
*/
|
|
13
|
+
interface DiagnosticInfo {
|
|
14
|
+
/** File path where the diagnostic occurred */
|
|
15
|
+
file: string;
|
|
16
|
+
/** 1-based line number */
|
|
17
|
+
line: number;
|
|
18
|
+
/** 1-based column number */
|
|
19
|
+
column: number;
|
|
20
|
+
/** End line (1-based) */
|
|
21
|
+
endLine: number;
|
|
22
|
+
/** End column (1-based) */
|
|
23
|
+
endColumn: number;
|
|
24
|
+
/** Severity level */
|
|
25
|
+
severity: DiagnosticSeverity;
|
|
26
|
+
/** Rule code (e.g., "unknown-entity", "missing-title") */
|
|
27
|
+
code: string;
|
|
28
|
+
/** Human-readable error message */
|
|
29
|
+
message: string;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Result of running the check command.
|
|
33
|
+
*/
|
|
34
|
+
interface CheckResult {
|
|
35
|
+
/** Number of files that were checked */
|
|
36
|
+
filesChecked: number;
|
|
37
|
+
/** Diagnostics grouped by file path */
|
|
38
|
+
diagnosticsByFile: Map<string, DiagnosticInfo[]>;
|
|
39
|
+
/** Total number of errors */
|
|
40
|
+
errorCount: number;
|
|
41
|
+
/** Total number of warnings */
|
|
42
|
+
warningCount: number;
|
|
43
|
+
/** Total number of info messages */
|
|
44
|
+
infoCount: number;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Options for running the check command.
|
|
48
|
+
*/
|
|
49
|
+
interface RunCheckOptions {
|
|
50
|
+
/** Checker configuration (rule overrides, etc.) */
|
|
51
|
+
config?: CheckConfig;
|
|
52
|
+
/** Minimum severity to include (default: "info") */
|
|
53
|
+
minSeverity?: DiagnosticSeverity;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Run the check command on a workspace.
|
|
57
|
+
*
|
|
58
|
+
* @param workspace - The workspace to check
|
|
59
|
+
* @param options - Check options
|
|
60
|
+
* @returns Structured check results
|
|
61
|
+
*/
|
|
62
|
+
declare function runCheck(workspace: Workspace, options?: RunCheckOptions): CheckResult;
|
|
63
|
+
//#endregion
|
|
64
|
+
export { CheckResult, DiagnosticInfo, DiagnosticSeverity, RunCheckOptions, runCheck };
|
|
65
|
+
//# sourceMappingURL=check.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.d.ts","names":[],"sources":["../../src/commands/check.ts"],"sourcesContent":[],"mappings":";;;;;AAoBA;AAsBA;AAgBA;AAoCgB,KA/EJ,kBAAA,GA+EY,OAAA,GAAA,SAAA,GAAA,MAAA;;;;AAAkE,UA1EzE,cAAA,CA0EyE;;;;;;;;;;;;YA9D9E;;;;;;;;;UAUK,WAAA;;;;qBAII,YAAY;;;;;;;;;;;UAYhB,eAAA;;WAEN;;gBAEK;;;;;;;;;iBAgCA,QAAA,YAAoB,qBAAoB,kBAAuB"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { check } from "../checker/check.js";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/check.ts
|
|
4
|
+
const SEVERITY_ORDER = {
|
|
5
|
+
error: 0,
|
|
6
|
+
warning: 1,
|
|
7
|
+
info: 2
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Convert a diagnostic to DiagnosticInfo.
|
|
11
|
+
*/
|
|
12
|
+
function toDiagnosticInfo(diagnostic) {
|
|
13
|
+
return {
|
|
14
|
+
file: diagnostic.file,
|
|
15
|
+
line: diagnostic.location.startPosition.row + 1,
|
|
16
|
+
column: diagnostic.location.startPosition.column + 1,
|
|
17
|
+
endLine: diagnostic.location.endPosition.row + 1,
|
|
18
|
+
endColumn: diagnostic.location.endPosition.column + 1,
|
|
19
|
+
severity: diagnostic.severity,
|
|
20
|
+
code: diagnostic.code,
|
|
21
|
+
message: diagnostic.message
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Run the check command on a workspace.
|
|
26
|
+
*
|
|
27
|
+
* @param workspace - The workspace to check
|
|
28
|
+
* @param options - Check options
|
|
29
|
+
* @returns Structured check results
|
|
30
|
+
*/
|
|
31
|
+
function runCheck(workspace, options = {}) {
|
|
32
|
+
const { config = {}, minSeverity = "info" } = options;
|
|
33
|
+
const diagnostics = check(workspace, config);
|
|
34
|
+
const minSeverityOrder = SEVERITY_ORDER[minSeverity];
|
|
35
|
+
const filteredDiagnostics = diagnostics.filter((d) => SEVERITY_ORDER[d.severity] <= minSeverityOrder);
|
|
36
|
+
filteredDiagnostics.sort((a, b) => {
|
|
37
|
+
if (a.file !== b.file) return a.file.localeCompare(b.file);
|
|
38
|
+
if (a.location.startPosition.row !== b.location.startPosition.row) return a.location.startPosition.row - b.location.startPosition.row;
|
|
39
|
+
return a.location.startPosition.column - b.location.startPosition.column;
|
|
40
|
+
});
|
|
41
|
+
const diagnosticsByFile = /* @__PURE__ */ new Map();
|
|
42
|
+
for (const d of filteredDiagnostics) {
|
|
43
|
+
const existing = diagnosticsByFile.get(d.file) || [];
|
|
44
|
+
existing.push(toDiagnosticInfo(d));
|
|
45
|
+
diagnosticsByFile.set(d.file, existing);
|
|
46
|
+
}
|
|
47
|
+
const errorCount = filteredDiagnostics.filter((d) => d.severity === "error").length;
|
|
48
|
+
const warningCount = filteredDiagnostics.filter((d) => d.severity === "warning").length;
|
|
49
|
+
const infoCount = filteredDiagnostics.filter((d) => d.severity === "info").length;
|
|
50
|
+
return {
|
|
51
|
+
filesChecked: workspace.files().length,
|
|
52
|
+
diagnosticsByFile,
|
|
53
|
+
errorCount,
|
|
54
|
+
warningCount,
|
|
55
|
+
infoCount
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//#endregion
|
|
60
|
+
export { runCheck };
|
|
61
|
+
//# sourceMappingURL=check.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check.js","names":["SEVERITY_ORDER: Record<DiagnosticSeverity, number>"],"sources":["../../src/commands/check.ts"],"sourcesContent":["/**\n * Check command - runs the checker on a workspace and returns structured results.\n */\n\nimport type { Workspace } from \"../model/workspace.js\";\nimport { check } from \"../checker/check.js\";\nimport type { CheckConfig, Diagnostic } from \"../checker/check.js\";\n\n// ===================\n// Types\n// ===================\n\n/**\n * Severity levels for diagnostics\n */\nexport type DiagnosticSeverity = \"error\" | \"warning\" | \"info\";\n\n/**\n * A single diagnostic (error, warning, or info) from the checker.\n */\nexport interface DiagnosticInfo {\n /** File path where the diagnostic occurred */\n file: string;\n /** 1-based line number */\n line: number;\n /** 1-based column number */\n column: number;\n /** End line (1-based) */\n endLine: number;\n /** End column (1-based) */\n endColumn: number;\n /** Severity level */\n severity: DiagnosticSeverity;\n /** Rule code (e.g., \"unknown-entity\", \"missing-title\") */\n code: string;\n /** Human-readable error message */\n message: string;\n}\n\n/**\n * Result of running the check command.\n */\nexport interface CheckResult {\n /** Number of files that were checked */\n filesChecked: number;\n /** Diagnostics grouped by file path */\n diagnosticsByFile: Map<string, DiagnosticInfo[]>;\n /** Total number of errors */\n errorCount: number;\n /** Total number of warnings */\n warningCount: number;\n /** Total number of info messages */\n infoCount: number;\n}\n\n/**\n * Options for running the check command.\n */\nexport interface RunCheckOptions {\n /** Checker configuration (rule overrides, etc.) */\n config?: CheckConfig;\n /** Minimum severity to include (default: \"info\") */\n minSeverity?: DiagnosticSeverity;\n}\n\nconst SEVERITY_ORDER: Record<DiagnosticSeverity, number> = {\n error: 0,\n warning: 1,\n info: 2,\n};\n\n/**\n * Convert a diagnostic to DiagnosticInfo.\n */\nfunction toDiagnosticInfo(diagnostic: Diagnostic): DiagnosticInfo {\n return {\n file: diagnostic.file,\n line: diagnostic.location.startPosition.row + 1,\n column: diagnostic.location.startPosition.column + 1,\n endLine: diagnostic.location.endPosition.row + 1,\n endColumn: diagnostic.location.endPosition.column + 1,\n severity: diagnostic.severity as DiagnosticSeverity,\n code: diagnostic.code,\n message: diagnostic.message,\n };\n}\n\n/**\n * Run the check command on a workspace.\n *\n * @param workspace - The workspace to check\n * @param options - Check options\n * @returns Structured check results\n */\nexport function runCheck(workspace: Workspace, options: RunCheckOptions = {}): CheckResult {\n const { config = {}, minSeverity = \"info\" } = options;\n\n // Run the checker\n const diagnostics = check(workspace, config);\n\n // Filter by minimum severity\n const minSeverityOrder = SEVERITY_ORDER[minSeverity];\n const filteredDiagnostics = diagnostics.filter(\n (d) => SEVERITY_ORDER[d.severity as DiagnosticSeverity] <= minSeverityOrder,\n );\n\n // Sort diagnostics by file, then position\n filteredDiagnostics.sort((a, b) => {\n if (a.file !== b.file) {\n return a.file.localeCompare(b.file);\n }\n if (a.location.startPosition.row !== b.location.startPosition.row) {\n return a.location.startPosition.row - b.location.startPosition.row;\n }\n return a.location.startPosition.column - b.location.startPosition.column;\n });\n\n // Group by file\n const diagnosticsByFile = new Map<string, DiagnosticInfo[]>();\n for (const d of filteredDiagnostics) {\n const existing = diagnosticsByFile.get(d.file) || [];\n existing.push(toDiagnosticInfo(d));\n diagnosticsByFile.set(d.file, existing);\n }\n\n // Count by severity\n const errorCount = filteredDiagnostics.filter((d) => d.severity === \"error\").length;\n const warningCount = filteredDiagnostics.filter((d) => d.severity === \"warning\").length;\n const infoCount = filteredDiagnostics.filter((d) => d.severity === \"info\").length;\n\n return {\n filesChecked: workspace.files().length,\n diagnosticsByFile,\n errorCount,\n warningCount,\n infoCount,\n };\n}\n"],"mappings":";;;AAiEA,MAAMA,iBAAqD;CACzD,OAAO;CACP,SAAS;CACT,MAAM;CACP;;;;AAKD,SAAS,iBAAiB,YAAwC;AAChE,QAAO;EACL,MAAM,WAAW;EACjB,MAAM,WAAW,SAAS,cAAc,MAAM;EAC9C,QAAQ,WAAW,SAAS,cAAc,SAAS;EACnD,SAAS,WAAW,SAAS,YAAY,MAAM;EAC/C,WAAW,WAAW,SAAS,YAAY,SAAS;EACpD,UAAU,WAAW;EACrB,MAAM,WAAW;EACjB,SAAS,WAAW;EACrB;;;;;;;;;AAUH,SAAgB,SAAS,WAAsB,UAA2B,EAAE,EAAe;CACzF,MAAM,EAAE,SAAS,EAAE,EAAE,cAAc,WAAW;CAG9C,MAAM,cAAc,MAAM,WAAW,OAAO;CAG5C,MAAM,mBAAmB,eAAe;CACxC,MAAM,sBAAsB,YAAY,QACrC,MAAM,eAAe,EAAE,aAAmC,iBAC5D;AAGD,qBAAoB,MAAM,GAAG,MAAM;AACjC,MAAI,EAAE,SAAS,EAAE,KACf,QAAO,EAAE,KAAK,cAAc,EAAE,KAAK;AAErC,MAAI,EAAE,SAAS,cAAc,QAAQ,EAAE,SAAS,cAAc,IAC5D,QAAO,EAAE,SAAS,cAAc,MAAM,EAAE,SAAS,cAAc;AAEjE,SAAO,EAAE,SAAS,cAAc,SAAS,EAAE,SAAS,cAAc;GAClE;CAGF,MAAM,oCAAoB,IAAI,KAA+B;AAC7D,MAAK,MAAM,KAAK,qBAAqB;EACnC,MAAM,WAAW,kBAAkB,IAAI,EAAE,KAAK,IAAI,EAAE;AACpD,WAAS,KAAK,iBAAiB,EAAE,CAAC;AAClC,oBAAkB,IAAI,EAAE,MAAM,SAAS;;CAIzC,MAAM,aAAa,oBAAoB,QAAQ,MAAM,EAAE,aAAa,QAAQ,CAAC;CAC7E,MAAM,eAAe,oBAAoB,QAAQ,MAAM,EAAE,aAAa,UAAU,CAAC;CACjF,MAAM,YAAY,oBAAoB,QAAQ,MAAM,EAAE,aAAa,OAAO,CAAC;AAE3E,QAAO;EACL,cAAc,UAAU,OAAO,CAAC;EAChC;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { Workspace } from "../model/workspace.js";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/format.d.ts
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A syntax error found during parsing.
|
|
7
|
+
*/
|
|
8
|
+
interface SyntaxErrorInfo {
|
|
9
|
+
/** File path where the error occurred */
|
|
10
|
+
file: string;
|
|
11
|
+
/** 1-based line number */
|
|
12
|
+
line: number;
|
|
13
|
+
/** 1-based column number */
|
|
14
|
+
column: number;
|
|
15
|
+
/** Human-readable error message */
|
|
16
|
+
message: string;
|
|
17
|
+
/** Error code (e.g., "syntax-parse_error") */
|
|
18
|
+
code: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Result of formatting a single file.
|
|
22
|
+
*/
|
|
23
|
+
interface FormatFileResult {
|
|
24
|
+
/** The file path */
|
|
25
|
+
file: string;
|
|
26
|
+
/** The formatted content (or original if unchanged/error) */
|
|
27
|
+
formatted: string;
|
|
28
|
+
/** Whether the content changed after formatting */
|
|
29
|
+
isChanged: boolean;
|
|
30
|
+
/** Whether the file has syntax errors (formatting skipped) */
|
|
31
|
+
hasSyntaxErrors: boolean;
|
|
32
|
+
/** Syntax errors found in the file (if any) */
|
|
33
|
+
syntaxErrors: SyntaxErrorInfo[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Result of running the format command.
|
|
37
|
+
*/
|
|
38
|
+
interface FormatResult {
|
|
39
|
+
/** Number of files that were processed */
|
|
40
|
+
filesProcessed: number;
|
|
41
|
+
/** Results for each file */
|
|
42
|
+
fileResults: FormatFileResult[];
|
|
43
|
+
/** Number of files that were changed/need changes */
|
|
44
|
+
changedCount: number;
|
|
45
|
+
/** Number of files with syntax errors */
|
|
46
|
+
syntaxErrorCount: number;
|
|
47
|
+
/** Total number of syntax errors across all files */
|
|
48
|
+
totalSyntaxErrors: number;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* A formatter function that formats source code.
|
|
52
|
+
*/
|
|
53
|
+
type Formatter = (source: string, filepath: string) => Promise<string>;
|
|
54
|
+
/**
|
|
55
|
+
* Input for formatting a single file.
|
|
56
|
+
*/
|
|
57
|
+
interface FormatFileInput {
|
|
58
|
+
/** The file path */
|
|
59
|
+
file: string;
|
|
60
|
+
/** The file content */
|
|
61
|
+
content: string;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Options for running the format command.
|
|
65
|
+
*/
|
|
66
|
+
interface RunFormatOptions {
|
|
67
|
+
/** Custom formatter function (e.g., prettier) */
|
|
68
|
+
formatter: Formatter;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format a single file, checking for syntax errors first.
|
|
72
|
+
*
|
|
73
|
+
* @param workspace - The workspace to use for syntax checking
|
|
74
|
+
* @param input - The file input (path and content)
|
|
75
|
+
* @param formatter - The formatter function to apply
|
|
76
|
+
* @returns The format result for this file
|
|
77
|
+
*/
|
|
78
|
+
declare function formatFile(workspace: Workspace, input: FormatFileInput, formatter: Formatter): Promise<FormatFileResult>;
|
|
79
|
+
/**
|
|
80
|
+
* Run the format command on multiple files.
|
|
81
|
+
*
|
|
82
|
+
* @param workspace - The workspace to use for syntax checking
|
|
83
|
+
* @param files - The files to format (path and content)
|
|
84
|
+
* @param options - Format options including the formatter function
|
|
85
|
+
* @returns Structured format results
|
|
86
|
+
*/
|
|
87
|
+
declare function runFormat(workspace: Workspace, files: FormatFileInput[], options: RunFormatOptions): Promise<FormatResult>;
|
|
88
|
+
//#endregion
|
|
89
|
+
export { FormatFileInput, FormatFileResult, FormatResult, Formatter, RunFormatOptions, SyntaxErrorInfo, formatFile, runFormat };
|
|
90
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","names":[],"sources":["../../src/commands/format.ts"],"sourcesContent":[],"mappings":";;;;AA6BA;AAgBA;AAgBA;AAKiB,UArDA,eAAA,CAqDe;EAUf;EAoDK,IAAA,EAAA,MAAA;EACT;EACJ,IAAA,EAAA,MAAA;EACI;EACF,MAAA,EAAA,MAAA;EAAR;EAAO,OAAA,EAAA,MAAA;EAoCY;EACT,IAAA,EAAA,MAAA;;;;;AAGH,UA/IO,gBAAA,CA+IP;;;;;;;;;;gBArIM;;;;;UAMC,YAAA;;;;eAIF;;;;;;;;;;;KAYH,SAAA,yCAAkD;;;;UAK7C,eAAA;;;;;;;;;UAUA,gBAAA;;aAEJ;;;;;;;;;;iBAkDS,UAAA,YACT,kBACJ,4BACI,YACV,QAAQ;;;;;;;;;iBAoCW,SAAA,YACT,kBACJ,4BACE,mBACR,QAAQ"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
//#region src/commands/format.ts
|
|
2
|
+
/**
|
|
3
|
+
* Check a file for syntax errors using the thalo parser.
|
|
4
|
+
* Returns syntax errors without running semantic analysis or rules.
|
|
5
|
+
*/
|
|
6
|
+
function collectSyntaxErrors(workspace, file, content) {
|
|
7
|
+
const errors = [];
|
|
8
|
+
workspace.addDocument(content, { filename: file });
|
|
9
|
+
try {
|
|
10
|
+
const model = workspace.getModel(file);
|
|
11
|
+
if (!model) return errors;
|
|
12
|
+
for (const error of model.ast.syntaxErrors) errors.push({
|
|
13
|
+
file,
|
|
14
|
+
line: error.location.startPosition.row + 1,
|
|
15
|
+
column: error.location.startPosition.column + 1,
|
|
16
|
+
message: error.message,
|
|
17
|
+
code: `syntax-${error.code}`
|
|
18
|
+
});
|
|
19
|
+
return errors;
|
|
20
|
+
} finally {
|
|
21
|
+
workspace.removeDocument(file);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Format a single file, checking for syntax errors first.
|
|
26
|
+
*
|
|
27
|
+
* @param workspace - The workspace to use for syntax checking
|
|
28
|
+
* @param input - The file input (path and content)
|
|
29
|
+
* @param formatter - The formatter function to apply
|
|
30
|
+
* @returns The format result for this file
|
|
31
|
+
*/
|
|
32
|
+
async function formatFile(workspace, input, formatter) {
|
|
33
|
+
const { file, content } = input;
|
|
34
|
+
const syntaxErrors = collectSyntaxErrors(workspace, file, content);
|
|
35
|
+
if (syntaxErrors.length > 0) return {
|
|
36
|
+
file,
|
|
37
|
+
formatted: content,
|
|
38
|
+
isChanged: false,
|
|
39
|
+
hasSyntaxErrors: true,
|
|
40
|
+
syntaxErrors
|
|
41
|
+
};
|
|
42
|
+
const formatted = await formatter(content, file);
|
|
43
|
+
return {
|
|
44
|
+
file,
|
|
45
|
+
formatted,
|
|
46
|
+
isChanged: content !== formatted,
|
|
47
|
+
hasSyntaxErrors: false,
|
|
48
|
+
syntaxErrors: []
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Run the format command on multiple files.
|
|
53
|
+
*
|
|
54
|
+
* @param workspace - The workspace to use for syntax checking
|
|
55
|
+
* @param files - The files to format (path and content)
|
|
56
|
+
* @param options - Format options including the formatter function
|
|
57
|
+
* @returns Structured format results
|
|
58
|
+
*/
|
|
59
|
+
async function runFormat(workspace, files, options) {
|
|
60
|
+
const { formatter } = options;
|
|
61
|
+
const fileResults = [];
|
|
62
|
+
for (const input of files) {
|
|
63
|
+
const result = await formatFile(workspace, input, formatter);
|
|
64
|
+
fileResults.push(result);
|
|
65
|
+
}
|
|
66
|
+
const changedCount = fileResults.filter((r) => r.isChanged).length;
|
|
67
|
+
const syntaxErrorCount = fileResults.filter((r) => r.hasSyntaxErrors).length;
|
|
68
|
+
const totalSyntaxErrors = fileResults.reduce((sum, r) => sum + r.syntaxErrors.length, 0);
|
|
69
|
+
return {
|
|
70
|
+
filesProcessed: files.length,
|
|
71
|
+
fileResults,
|
|
72
|
+
changedCount,
|
|
73
|
+
syntaxErrorCount,
|
|
74
|
+
totalSyntaxErrors
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
export { formatFile, runFormat };
|
|
80
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","names":["errors: SyntaxErrorInfo[]","fileResults: FormatFileResult[]"],"sources":["../../src/commands/format.ts"],"sourcesContent":["/**\n * Format command - checks syntax and formats files, returning structured results.\n */\n\nimport type { Workspace } from \"../model/workspace.js\";\n\n// ===================\n// Types\n// ===================\n\n/**\n * A syntax error found during parsing.\n */\nexport interface SyntaxErrorInfo {\n /** File path where the error occurred */\n file: string;\n /** 1-based line number */\n line: number;\n /** 1-based column number */\n column: number;\n /** Human-readable error message */\n message: string;\n /** Error code (e.g., \"syntax-parse_error\") */\n code: string;\n}\n\n/**\n * Result of formatting a single file.\n */\nexport interface FormatFileResult {\n /** The file path */\n file: string;\n /** The formatted content (or original if unchanged/error) */\n formatted: string;\n /** Whether the content changed after formatting */\n isChanged: boolean;\n /** Whether the file has syntax errors (formatting skipped) */\n hasSyntaxErrors: boolean;\n /** Syntax errors found in the file (if any) */\n syntaxErrors: SyntaxErrorInfo[];\n}\n\n/**\n * Result of running the format command.\n */\nexport interface FormatResult {\n /** Number of files that were processed */\n filesProcessed: number;\n /** Results for each file */\n fileResults: FormatFileResult[];\n /** Number of files that were changed/need changes */\n changedCount: number;\n /** Number of files with syntax errors */\n syntaxErrorCount: number;\n /** Total number of syntax errors across all files */\n totalSyntaxErrors: number;\n}\n\n/**\n * A formatter function that formats source code.\n */\nexport type Formatter = (source: string, filepath: string) => Promise<string>;\n\n/**\n * Input for formatting a single file.\n */\nexport interface FormatFileInput {\n /** The file path */\n file: string;\n /** The file content */\n content: string;\n}\n\n/**\n * Options for running the format command.\n */\nexport interface RunFormatOptions {\n /** Custom formatter function (e.g., prettier) */\n formatter: Formatter;\n}\n\n// ===================\n// Core Logic\n// ===================\n\n/**\n * Check a file for syntax errors using the thalo parser.\n * Returns syntax errors without running semantic analysis or rules.\n */\nfunction collectSyntaxErrors(\n workspace: Workspace,\n file: string,\n content: string,\n): SyntaxErrorInfo[] {\n const errors: SyntaxErrorInfo[] = [];\n\n workspace.addDocument(content, { filename: file });\n try {\n const model = workspace.getModel(file);\n if (!model) {\n return errors;\n }\n\n // Collect root-level syntax errors\n for (const error of model.ast.syntaxErrors) {\n errors.push({\n file,\n line: error.location.startPosition.row + 1,\n column: error.location.startPosition.column + 1,\n message: error.message,\n code: `syntax-${error.code}`,\n });\n }\n\n return errors;\n } finally {\n workspace.removeDocument(file);\n }\n}\n\n/**\n * Format a single file, checking for syntax errors first.\n *\n * @param workspace - The workspace to use for syntax checking\n * @param input - The file input (path and content)\n * @param formatter - The formatter function to apply\n * @returns The format result for this file\n */\nexport async function formatFile(\n workspace: Workspace,\n input: FormatFileInput,\n formatter: Formatter,\n): Promise<FormatFileResult> {\n const { file, content } = input;\n\n // Check for syntax errors first\n const syntaxErrors = collectSyntaxErrors(workspace, file, content);\n if (syntaxErrors.length > 0) {\n // Return unchanged content - don't format files with syntax errors\n return {\n file,\n formatted: content,\n isChanged: false,\n hasSyntaxErrors: true,\n syntaxErrors,\n };\n }\n\n // Format the file\n const formatted = await formatter(content, file);\n\n return {\n file,\n formatted,\n isChanged: content !== formatted,\n hasSyntaxErrors: false,\n syntaxErrors: [],\n };\n}\n\n/**\n * Run the format command on multiple files.\n *\n * @param workspace - The workspace to use for syntax checking\n * @param files - The files to format (path and content)\n * @param options - Format options including the formatter function\n * @returns Structured format results\n */\nexport async function runFormat(\n workspace: Workspace,\n files: FormatFileInput[],\n options: RunFormatOptions,\n): Promise<FormatResult> {\n const { formatter } = options;\n\n const fileResults: FormatFileResult[] = [];\n\n // Process files sequentially to avoid workspace conflicts\n // (workspace.addDocument/removeDocument is not concurrent-safe)\n for (const input of files) {\n const result = await formatFile(workspace, input, formatter);\n fileResults.push(result);\n }\n\n // Calculate summary statistics\n const changedCount = fileResults.filter((r) => r.isChanged).length;\n const syntaxErrorCount = fileResults.filter((r) => r.hasSyntaxErrors).length;\n const totalSyntaxErrors = fileResults.reduce((sum, r) => sum + r.syntaxErrors.length, 0);\n\n return {\n filesProcessed: files.length,\n fileResults,\n changedCount,\n syntaxErrorCount,\n totalSyntaxErrors,\n };\n}\n"],"mappings":";;;;;AAyFA,SAAS,oBACP,WACA,MACA,SACmB;CACnB,MAAMA,SAA4B,EAAE;AAEpC,WAAU,YAAY,SAAS,EAAE,UAAU,MAAM,CAAC;AAClD,KAAI;EACF,MAAM,QAAQ,UAAU,SAAS,KAAK;AACtC,MAAI,CAAC,MACH,QAAO;AAIT,OAAK,MAAM,SAAS,MAAM,IAAI,aAC5B,QAAO,KAAK;GACV;GACA,MAAM,MAAM,SAAS,cAAc,MAAM;GACzC,QAAQ,MAAM,SAAS,cAAc,SAAS;GAC9C,SAAS,MAAM;GACf,MAAM,UAAU,MAAM;GACvB,CAAC;AAGJ,SAAO;WACC;AACR,YAAU,eAAe,KAAK;;;;;;;;;;;AAYlC,eAAsB,WACpB,WACA,OACA,WAC2B;CAC3B,MAAM,EAAE,MAAM,YAAY;CAG1B,MAAM,eAAe,oBAAoB,WAAW,MAAM,QAAQ;AAClE,KAAI,aAAa,SAAS,EAExB,QAAO;EACL;EACA,WAAW;EACX,WAAW;EACX,iBAAiB;EACjB;EACD;CAIH,MAAM,YAAY,MAAM,UAAU,SAAS,KAAK;AAEhD,QAAO;EACL;EACA;EACA,WAAW,YAAY;EACvB,iBAAiB;EACjB,cAAc,EAAE;EACjB;;;;;;;;;;AAWH,eAAsB,UACpB,WACA,OACA,SACuB;CACvB,MAAM,EAAE,cAAc;CAEtB,MAAMC,cAAkC,EAAE;AAI1C,MAAK,MAAM,SAAS,OAAO;EACzB,MAAM,SAAS,MAAM,WAAW,WAAW,OAAO,UAAU;AAC5D,cAAY,KAAK,OAAO;;CAI1B,MAAM,eAAe,YAAY,QAAQ,MAAM,EAAE,UAAU,CAAC;CAC5D,MAAM,mBAAmB,YAAY,QAAQ,MAAM,EAAE,gBAAgB,CAAC;CACtE,MAAM,oBAAoB,YAAY,QAAQ,KAAK,MAAM,MAAM,EAAE,aAAa,QAAQ,EAAE;AAExF,QAAO;EACL,gBAAgB,MAAM;EACtB;EACA;EACA;EACA;EACD"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Workspace } from "../model/workspace.js";
|
|
2
|
+
import { Query, QueryCondition, parseQueryString } from "../services/query.js";
|
|
3
|
+
import { ChangeTracker } from "../services/change-tracker/change-tracker.js";
|
|
4
|
+
|
|
5
|
+
//#region src/commands/query.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Information about a condition in a query.
|
|
9
|
+
*/
|
|
10
|
+
interface QueryConditionInfo {
|
|
11
|
+
kind: QueryCondition["kind"];
|
|
12
|
+
/** For field conditions */
|
|
13
|
+
field?: string;
|
|
14
|
+
value?: string;
|
|
15
|
+
/** For tag conditions */
|
|
16
|
+
tag?: string;
|
|
17
|
+
/** For link conditions */
|
|
18
|
+
link?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Information about an entry that matched a query.
|
|
22
|
+
*/
|
|
23
|
+
interface QueryEntryInfo {
|
|
24
|
+
/** File path containing the entry */
|
|
25
|
+
file: string;
|
|
26
|
+
/** Formatted timestamp string */
|
|
27
|
+
timestamp: string;
|
|
28
|
+
/** Entity type (e.g., "lore", "opinion") */
|
|
29
|
+
entity: string;
|
|
30
|
+
/** Entry title */
|
|
31
|
+
title: string;
|
|
32
|
+
/** Link ID if present */
|
|
33
|
+
linkId: string | null;
|
|
34
|
+
/** Tags on the entry */
|
|
35
|
+
tags: string[];
|
|
36
|
+
/** 1-based start line */
|
|
37
|
+
startLine: number;
|
|
38
|
+
/** 1-based end line */
|
|
39
|
+
endLine: number;
|
|
40
|
+
/** Raw source text of the entry (optional, for "raw" format) */
|
|
41
|
+
rawText?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Result of running the query command (single query).
|
|
45
|
+
*/
|
|
46
|
+
interface QueryResult {
|
|
47
|
+
/** The parsed query */
|
|
48
|
+
query: Query;
|
|
49
|
+
/** Formatted query string for display */
|
|
50
|
+
queryString: string;
|
|
51
|
+
/** Matching entries */
|
|
52
|
+
entries: QueryEntryInfo[];
|
|
53
|
+
/** Total count (may be more than entries.length if limited) */
|
|
54
|
+
totalCount: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Result of running queries (multiple queries).
|
|
58
|
+
*/
|
|
59
|
+
interface QueriesResult {
|
|
60
|
+
/** The parsed queries */
|
|
61
|
+
queries: Query[];
|
|
62
|
+
/** Formatted query string for display */
|
|
63
|
+
queryString: string;
|
|
64
|
+
/** Matching entries (deduplicated across all queries) */
|
|
65
|
+
entries: QueryEntryInfo[];
|
|
66
|
+
/** Total count (may be more than entries.length if limited) */
|
|
67
|
+
totalCount: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Error result when queries reference unknown entities.
|
|
71
|
+
*/
|
|
72
|
+
interface QueryValidationError {
|
|
73
|
+
kind: "unknown-entities";
|
|
74
|
+
/** The unknown entity names */
|
|
75
|
+
entities: string[];
|
|
76
|
+
/** Human-readable error message */
|
|
77
|
+
message: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Options for running the query command.
|
|
81
|
+
*/
|
|
82
|
+
interface RunQueryOptions {
|
|
83
|
+
/** Maximum number of results to return */
|
|
84
|
+
limit?: number;
|
|
85
|
+
/** Include raw source text in results */
|
|
86
|
+
includeRawText?: boolean;
|
|
87
|
+
/** Whether to validate that queried entities exist (default: true) */
|
|
88
|
+
validateEntities?: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* Only return entries since this checkpoint.
|
|
91
|
+
* Format: "ts:2026-01-10T15:00Z" for timestamp-based filtering.
|
|
92
|
+
* Format: "git:abc123" for git-based filtering (requires tracker option).
|
|
93
|
+
*/
|
|
94
|
+
since?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Change tracker for git-based filtering.
|
|
97
|
+
* Required when using git checkpoints (git:...).
|
|
98
|
+
*/
|
|
99
|
+
tracker?: ChangeTracker;
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Error result when a checkpoint is invalid or missing required options.
|
|
103
|
+
*/
|
|
104
|
+
interface CheckpointError {
|
|
105
|
+
kind: "invalid-checkpoint";
|
|
106
|
+
/** Human-readable error message */
|
|
107
|
+
message: string;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Run multiple queries on a workspace.
|
|
111
|
+
* Supports comma-separated query syntax like "lore, journal where #career".
|
|
112
|
+
*
|
|
113
|
+
* @param workspace - The workspace to query
|
|
114
|
+
* @param queryString - The query string to parse and execute (may contain multiple queries)
|
|
115
|
+
* @param options - Query options
|
|
116
|
+
* @returns Structured query results, validation error, checkpoint error, or null if query syntax is invalid
|
|
117
|
+
*/
|
|
118
|
+
declare function runQueries(workspace: Workspace, queryString: string, options?: RunQueryOptions): Promise<QueriesResult | QueryValidationError | CheckpointError | null>;
|
|
119
|
+
/**
|
|
120
|
+
* Run the query command on a workspace.
|
|
121
|
+
* For backward compatibility, this only supports a single query.
|
|
122
|
+
* Use `runQueries` for multiple queries or comma-separated syntax.
|
|
123
|
+
*
|
|
124
|
+
* @param workspace - The workspace to query
|
|
125
|
+
* @param queryString - The query string to parse and execute
|
|
126
|
+
* @param options - Query options
|
|
127
|
+
* @returns Structured query results, validation error, checkpoint error, or null if query is invalid
|
|
128
|
+
*/
|
|
129
|
+
declare function runQuery(workspace: Workspace, queryString: string, options?: RunQueryOptions): Promise<QueryResult | QueryValidationError | CheckpointError | null>;
|
|
130
|
+
/**
|
|
131
|
+
* Type guard to check if a query result is a validation error.
|
|
132
|
+
*/
|
|
133
|
+
declare function isQueryValidationError(result: QueryResult | QueriesResult | QueryValidationError | CheckpointError | null): result is QueryValidationError;
|
|
134
|
+
/**
|
|
135
|
+
* Type guard to check if a query result is a checkpoint error.
|
|
136
|
+
*/
|
|
137
|
+
declare function isCheckpointError(result: QueryResult | QueriesResult | QueryValidationError | CheckpointError | null): result is CheckpointError;
|
|
138
|
+
/**
|
|
139
|
+
* Type guard to check if a query result is any error type.
|
|
140
|
+
*/
|
|
141
|
+
declare function isQueryError(result: QueryResult | QueriesResult | QueryValidationError | CheckpointError | null): result is QueryValidationError | CheckpointError;
|
|
142
|
+
/**
|
|
143
|
+
* Type guard to check if a query result is a successful result (not an error).
|
|
144
|
+
*/
|
|
145
|
+
declare function isQuerySuccess(result: QueryResult | QueryValidationError | CheckpointError | null): result is QueryResult;
|
|
146
|
+
/**
|
|
147
|
+
* Type guard to check if a queries result is a successful result (not an error).
|
|
148
|
+
*/
|
|
149
|
+
declare function isQueriesSuccess(result: QueriesResult | QueryValidationError | CheckpointError | null): result is QueriesResult;
|
|
150
|
+
//#endregion
|
|
151
|
+
export { CheckpointError, QueriesResult, QueryConditionInfo, QueryEntryInfo, QueryResult, QueryValidationError, RunQueryOptions, isCheckpointError, isQueriesSuccess, isQueryError, isQuerySuccess, isQueryValidationError, parseQueryString, runQueries, runQuery };
|
|
152
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","names":[],"sources":["../../src/commands/query.ts"],"sourcesContent":[],"mappings":";;;;;;AAoFA;AAcA;AAcA;AAWiB,UA7EA,kBAAA,CA8FL;EAMK,IAAA,EAnGT,cAmGwB,CAAA,MAAA,CAAA;EA6CV;EACT,KAAA,CAAA,EAAA,MAAA;EAEF,KAAA,CAAA,EAAA,MAAA;EACA;EAAgB,GAAA,CAAA,EAAA,MAAA;EAAuB;EAA/C,IAAA,CAAA,EAAA,MAAA;;AA2FH;;;AAIW,UAtOM,cAAA,CAsON;EAAc;EAAuB,IAAA,EAAA,MAAA;EAA7C;EAAO,SAAA,EAAA,MAAA;EAyBM;EACN,MAAA,EAAA,MAAA;EAAc;EAAgB,KAAA,EAAA,MAAA;EAAuB;EAClD,MAAA,EAAA,MAAA,GAAA,IAAA;EAAoB;EAOjB,IAAA,EAAA,MAAA,EAAA;EACN;EAAc,SAAA,EAAA,MAAA;EAAgB;EAAuB,OAAA,EAAA,MAAA;EAClD;EAAe,OAAA,CAAA,EAAA,MAAA;AAO5B;;;;AAC+D,UA1P9C,WAAA,CA0P8C;EAClD;EAAuB,KAAA,EAzP3B,KAyP2B;EAAe;EAOnC,WAAA,EAAA,MAAc;EACpB;EAAc,OAAA,EA7Pb,cA6Pa,EAAA;EAAuB;EAClC,UAAA,EAAA,MAAA;;AAOb;;;AACiD,UA9PhC,aAAA,CA8PgC;EACpC;EAAa,OAAA,EA7Pf,KA6Pe,EAAA;;;;WAzPf;;;;;;;UAQM,oBAAA;;;;;;;;;;UAWA,eAAA;;;;;;;;;;;;;;;;;YAiBL;;;;;UAMK,eAAA;;;;;;;;;;;;;;iBA6CK,UAAA,YACT,0CAEF,kBACR,QAAQ,gBAAgB,uBAAuB;;;;;;;;;;;iBA2F5B,QAAA,YACT,0CAEF,kBACR,QAAQ,cAAc,uBAAuB;;;;iBAyBhC,sBAAA,SACN,cAAc,gBAAgB,uBAAuB,mCAClD;;;;iBAOG,iBAAA,SACN,cAAc,gBAAgB,uBAAuB,mCAClD;;;;iBAOG,YAAA,SACN,cAAc,gBAAgB,uBAAuB,mCAClD,uBAAuB;;;;iBAOpB,cAAA,SACN,cAAc,uBAAuB,mCAClC;;;;iBAOG,gBAAA,SACN,gBAAgB,uBAAuB,mCACpC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { executeQueries, formatQuery, parseQueryString, validateQueryEntities } from "../services/query.js";
|
|
2
|
+
import { parseCheckpoint } from "../services/change-tracker/change-tracker.js";
|
|
3
|
+
import { formatTimestamp } from "../formatters.js";
|
|
4
|
+
import { findEntryFile, getEntrySourceText } from "../services/synthesis.js";
|
|
5
|
+
|
|
6
|
+
//#region src/commands/query.ts
|
|
7
|
+
/**
|
|
8
|
+
* Convert a timestamp to epoch milliseconds for correct comparison across timezones
|
|
9
|
+
*/
|
|
10
|
+
function timestampToEpoch(ts) {
|
|
11
|
+
const isoStr = formatTimestamp(ts);
|
|
12
|
+
return Date.parse(isoStr);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Parse an ISO timestamp string to epoch milliseconds
|
|
16
|
+
*/
|
|
17
|
+
function parseTimestampToEpoch(isoStr) {
|
|
18
|
+
return Date.parse(isoStr);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Convert an InstanceEntry to QueryEntryInfo.
|
|
22
|
+
*/
|
|
23
|
+
function toQueryEntryInfo(entry, file, workspace, includeRawText) {
|
|
24
|
+
const info = {
|
|
25
|
+
file,
|
|
26
|
+
timestamp: formatTimestamp(entry.header.timestamp),
|
|
27
|
+
entity: entry.header.entity,
|
|
28
|
+
title: entry.header.title.value,
|
|
29
|
+
linkId: entry.header.link?.id ?? null,
|
|
30
|
+
tags: entry.header.tags.map((t) => t.name),
|
|
31
|
+
startLine: entry.location.startPosition.row + 1,
|
|
32
|
+
endLine: entry.location.endPosition.row + 1
|
|
33
|
+
};
|
|
34
|
+
if (includeRawText) {
|
|
35
|
+
const model = workspace.getModel(file);
|
|
36
|
+
if (model) info.rawText = getEntrySourceText(entry, model.source);
|
|
37
|
+
}
|
|
38
|
+
return info;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Run multiple queries on a workspace.
|
|
42
|
+
* Supports comma-separated query syntax like "lore, journal where #career".
|
|
43
|
+
*
|
|
44
|
+
* @param workspace - The workspace to query
|
|
45
|
+
* @param queryString - The query string to parse and execute (may contain multiple queries)
|
|
46
|
+
* @param options - Query options
|
|
47
|
+
* @returns Structured query results, validation error, checkpoint error, or null if query syntax is invalid
|
|
48
|
+
*/
|
|
49
|
+
async function runQueries(workspace, queryString, options = {}) {
|
|
50
|
+
const { limit, includeRawText = false, validateEntities = true, since, tracker } = options;
|
|
51
|
+
let sinceMarker = null;
|
|
52
|
+
if (since) {
|
|
53
|
+
sinceMarker = parseCheckpoint(since);
|
|
54
|
+
if (!sinceMarker) return {
|
|
55
|
+
kind: "invalid-checkpoint",
|
|
56
|
+
message: `Invalid checkpoint format: '${since}'. Use 'ts:2026-01-10T15:00Z' for timestamps or 'git:abc123' for git commits.`
|
|
57
|
+
};
|
|
58
|
+
if (sinceMarker.type === "git" && !tracker) return {
|
|
59
|
+
kind: "invalid-checkpoint",
|
|
60
|
+
message: `Git checkpoints require a change tracker. Provide a tracker option or use timestamp checkpoints (ts:...).`
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const queries = parseQueryString(queryString);
|
|
64
|
+
if (!queries) return null;
|
|
65
|
+
if (validateEntities) {
|
|
66
|
+
const unknownEntities = validateQueryEntities(workspace, queries);
|
|
67
|
+
if (unknownEntities.length > 0) return {
|
|
68
|
+
kind: "unknown-entities",
|
|
69
|
+
entities: unknownEntities,
|
|
70
|
+
message: `Unknown entity type${unknownEntities.length > 1 ? "s" : ""}: ${unknownEntities.map((e) => `'${e}'`).join(", ")}. Define ${unknownEntities.length > 1 ? "them" : "it"} using 'define-entity'.`
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
let results;
|
|
74
|
+
if (sinceMarker?.type === "git" && tracker) results = (await tracker.getChangedEntries(workspace, queries, sinceMarker)).entries;
|
|
75
|
+
else {
|
|
76
|
+
results = executeQueries(workspace, queries);
|
|
77
|
+
if (sinceMarker?.type === "ts") {
|
|
78
|
+
const sinceEpoch = parseTimestampToEpoch(sinceMarker.value);
|
|
79
|
+
results = results.filter((entry) => {
|
|
80
|
+
return timestampToEpoch(entry.header.timestamp) > sinceEpoch;
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
const entries = [];
|
|
85
|
+
const limitedResults = limit && limit > 0 ? results.slice(0, limit) : results;
|
|
86
|
+
for (const entry of limitedResults) {
|
|
87
|
+
const file = findEntryFile(workspace, entry);
|
|
88
|
+
if (file) entries.push(toQueryEntryInfo(entry, file, workspace, includeRawText));
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
queries,
|
|
92
|
+
queryString: queries.map(formatQuery).join(", "),
|
|
93
|
+
entries,
|
|
94
|
+
totalCount: results.length
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Run the query command on a workspace.
|
|
99
|
+
* For backward compatibility, this only supports a single query.
|
|
100
|
+
* Use `runQueries` for multiple queries or comma-separated syntax.
|
|
101
|
+
*
|
|
102
|
+
* @param workspace - The workspace to query
|
|
103
|
+
* @param queryString - The query string to parse and execute
|
|
104
|
+
* @param options - Query options
|
|
105
|
+
* @returns Structured query results, validation error, checkpoint error, or null if query is invalid
|
|
106
|
+
*/
|
|
107
|
+
async function runQuery(workspace, queryString, options = {}) {
|
|
108
|
+
const result = await runQueries(workspace, queryString, options);
|
|
109
|
+
if (!result) return null;
|
|
110
|
+
if ("kind" in result) return result;
|
|
111
|
+
return {
|
|
112
|
+
query: result.queries[0],
|
|
113
|
+
queryString: result.queryString,
|
|
114
|
+
entries: result.entries,
|
|
115
|
+
totalCount: result.totalCount
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Type guard to check if a query result is a validation error.
|
|
120
|
+
*/
|
|
121
|
+
function isQueryValidationError(result) {
|
|
122
|
+
return result !== null && "kind" in result && result.kind === "unknown-entities";
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Type guard to check if a query result is a checkpoint error.
|
|
126
|
+
*/
|
|
127
|
+
function isCheckpointError(result) {
|
|
128
|
+
return result !== null && "kind" in result && result.kind === "invalid-checkpoint";
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Type guard to check if a query result is any error type.
|
|
132
|
+
*/
|
|
133
|
+
function isQueryError(result) {
|
|
134
|
+
return result !== null && "kind" in result;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Type guard to check if a query result is a successful result (not an error).
|
|
138
|
+
*/
|
|
139
|
+
function isQuerySuccess(result) {
|
|
140
|
+
return result !== null && !("kind" in result);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Type guard to check if a queries result is a successful result (not an error).
|
|
144
|
+
*/
|
|
145
|
+
function isQueriesSuccess(result) {
|
|
146
|
+
return result !== null && !("kind" in result);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
//#endregion
|
|
150
|
+
export { isCheckpointError, isQueriesSuccess, isQueryError, isQuerySuccess, isQueryValidationError, parseQueryString, runQueries, runQuery };
|
|
151
|
+
//# sourceMappingURL=query.js.map
|