@sigil-engine/core 0.1.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/.turbo/turbo-build.log +4 -0
- package/dist/cache.d.ts +24 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +97 -0
- package/dist/cache.js.map +1 -0
- package/dist/diff.d.ts +34 -0
- package/dist/diff.d.ts.map +1 -0
- package/dist/diff.js +319 -0
- package/dist/diff.js.map +1 -0
- package/dist/extract.d.ts +27 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +162 -0
- package/dist/extract.js.map +1 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin.d.ts +103 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +47 -0
- package/dist/plugin.js.map +1 -0
- package/dist/safety.d.ts +25 -0
- package/dist/safety.d.ts.map +1 -0
- package/dist/safety.js +139 -0
- package/dist/safety.js.map +1 -0
- package/dist/schema.d.ts +184 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +33 -0
- package/dist/schema.js.map +1 -0
- package/dist/serialize.d.ts +16 -0
- package/dist/serialize.d.ts.map +1 -0
- package/dist/serialize.js +75 -0
- package/dist/serialize.js.map +1 -0
- package/package.json +35 -0
- package/src/cache.ts +133 -0
- package/src/diff.ts +421 -0
- package/src/extract.ts +196 -0
- package/src/index.ts +94 -0
- package/src/plugin.ts +186 -0
- package/src/safety.ts +185 -0
- package/src/schema.ts +270 -0
- package/src/serialize.ts +97 -0
- package/tests/cache.test.ts +47 -0
- package/tests/diff.test.ts +222 -0
- package/tests/plugin.test.ts +107 -0
- package/tests/schema.test.ts +132 -0
- package/tests/serialize.test.ts +92 -0
- package/tsconfig.json +20 -0
package/dist/extract.js
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Extraction orchestrator — discovers plugins, runs them, merges results.
|
|
3
|
+
*
|
|
4
|
+
* PURE: This module returns a ContextDocument. It does NOT write to disk.
|
|
5
|
+
* I/O is handled by the CLI or calling code.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from "child_process";
|
|
8
|
+
import { resolve, basename } from "path";
|
|
9
|
+
import { existsSync, readFileSync } from "fs";
|
|
10
|
+
import { createEmptyDocument } from "./schema.js";
|
|
11
|
+
import { detectPlugins, getPlugins, } from "./plugin.js";
|
|
12
|
+
/**
|
|
13
|
+
* Extract a ContextDocument from a project.
|
|
14
|
+
*
|
|
15
|
+
* This is the primary API — it discovers applicable plugins,
|
|
16
|
+
* runs them, and merges results into a unified document.
|
|
17
|
+
*
|
|
18
|
+
* Returns a ContextDocument. Does NOT write to disk.
|
|
19
|
+
*/
|
|
20
|
+
export async function extractContext(opts) {
|
|
21
|
+
const startTime = Date.now();
|
|
22
|
+
const projectPath = resolve(opts.projectPath);
|
|
23
|
+
const projectName = inferProjectName(projectPath);
|
|
24
|
+
const progress = opts.onProgress ?? (() => { });
|
|
25
|
+
progress({ phase: "init", message: `Parsing ${projectName} at ${projectPath}` });
|
|
26
|
+
// Discover which plugins apply to this project
|
|
27
|
+
progress({ phase: "detect", message: "Detecting project type..." });
|
|
28
|
+
let plugins;
|
|
29
|
+
if (opts.plugins && opts.plugins.length > 0) {
|
|
30
|
+
// Use explicitly specified plugins
|
|
31
|
+
const allPlugins = getPlugins();
|
|
32
|
+
plugins = allPlugins.filter((p) => opts.plugins.includes(p.name));
|
|
33
|
+
if (plugins.length === 0) {
|
|
34
|
+
throw new Error(`No registered plugins match: ${opts.plugins.join(", ")}. ` +
|
|
35
|
+
`Available: ${allPlugins.map((p) => p.name).join(", ") || "none"}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
// Auto-detect
|
|
40
|
+
plugins = await detectPlugins(projectPath);
|
|
41
|
+
if (plugins.length === 0) {
|
|
42
|
+
throw new Error("No plugins detected support for this project. " +
|
|
43
|
+
"Install a parser plugin (e.g., @sigil-engine/parser-typescript).");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
progress({
|
|
47
|
+
phase: "detect",
|
|
48
|
+
message: `Detected plugins: ${plugins.map((p) => p.name).join(", ")}`,
|
|
49
|
+
});
|
|
50
|
+
// Create the document
|
|
51
|
+
const doc = createEmptyDocument(projectName);
|
|
52
|
+
// Run each plugin: init → extract → merge
|
|
53
|
+
for (const plugin of plugins) {
|
|
54
|
+
progress({
|
|
55
|
+
phase: "extract",
|
|
56
|
+
plugin: plugin.name,
|
|
57
|
+
message: `Running ${plugin.name} plugin...`,
|
|
58
|
+
});
|
|
59
|
+
const project = await plugin.init(projectPath);
|
|
60
|
+
progress({
|
|
61
|
+
phase: "extract",
|
|
62
|
+
plugin: plugin.name,
|
|
63
|
+
message: `${plugin.name}: found ${project.sourceFiles.length} source files`,
|
|
64
|
+
});
|
|
65
|
+
const result = await plugin.extract(project);
|
|
66
|
+
progress({
|
|
67
|
+
phase: "merge",
|
|
68
|
+
plugin: plugin.name,
|
|
69
|
+
message: `Merging ${plugin.name} results...`,
|
|
70
|
+
});
|
|
71
|
+
mergeResult(doc, result);
|
|
72
|
+
}
|
|
73
|
+
// Finalize metadata
|
|
74
|
+
const elapsed = Date.now() - startTime;
|
|
75
|
+
doc._extraction = {
|
|
76
|
+
extracted_at: new Date().toISOString(),
|
|
77
|
+
sigil_version: "0.1.0",
|
|
78
|
+
source_commit: getGitCommit(projectPath),
|
|
79
|
+
extraction_ms: elapsed,
|
|
80
|
+
plugins_used: plugins.map((p) => `${p.name}@${p.version}`),
|
|
81
|
+
};
|
|
82
|
+
progress({
|
|
83
|
+
phase: "done",
|
|
84
|
+
message: `Done in ${elapsed}ms — ${doc.entities.length} entities, ${doc.components.length} components, ${doc.routes.length} routes, ${doc.exports.length} exports`,
|
|
85
|
+
elapsed_ms: elapsed,
|
|
86
|
+
});
|
|
87
|
+
return doc;
|
|
88
|
+
}
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Merge plugin results into document
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
function mergeResult(doc, result) {
|
|
93
|
+
// Arrays: concatenate
|
|
94
|
+
if (result.entities)
|
|
95
|
+
doc.entities.push(...result.entities);
|
|
96
|
+
if (result.components)
|
|
97
|
+
doc.components.push(...result.components);
|
|
98
|
+
if (result.routes)
|
|
99
|
+
doc.routes.push(...result.routes);
|
|
100
|
+
if (result.exports)
|
|
101
|
+
doc.exports.push(...result.exports);
|
|
102
|
+
if (result.call_graph)
|
|
103
|
+
doc.call_graph.push(...result.call_graph);
|
|
104
|
+
if (result.component_graph)
|
|
105
|
+
doc.component_graph.push(...result.component_graph);
|
|
106
|
+
if (result.env_vars)
|
|
107
|
+
doc.env_vars.push(...result.env_vars);
|
|
108
|
+
if (result.dependencies)
|
|
109
|
+
doc.dependencies.push(...result.dependencies);
|
|
110
|
+
// Records: merge (later plugins can override earlier ones)
|
|
111
|
+
if (result.stack)
|
|
112
|
+
Object.assign(doc.stack, result.stack);
|
|
113
|
+
if (result.patterns)
|
|
114
|
+
Object.assign(doc.patterns, result.patterns);
|
|
115
|
+
if (result.conventions)
|
|
116
|
+
Object.assign(doc.conventions, result.conventions);
|
|
117
|
+
// Extensions: deep merge
|
|
118
|
+
if (result.extensions) {
|
|
119
|
+
doc.extensions = doc.extensions ?? {};
|
|
120
|
+
Object.assign(doc.extensions, result.extensions);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Deduplication — remove exports already captured as components/entities
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
export function deduplicateExports(doc) {
|
|
127
|
+
const componentNames = new Set(doc.components.map((c) => c.name));
|
|
128
|
+
const entitySymbols = new Set(doc.entities.map((e) => e._meta.symbol));
|
|
129
|
+
doc.exports = doc.exports.filter((exp) => !componentNames.has(exp.name) && !entitySymbols.has(exp.name));
|
|
130
|
+
}
|
|
131
|
+
// ---------------------------------------------------------------------------
|
|
132
|
+
// Helpers
|
|
133
|
+
// ---------------------------------------------------------------------------
|
|
134
|
+
function inferProjectName(projectPath) {
|
|
135
|
+
const pkgPath = resolve(projectPath, "package.json");
|
|
136
|
+
if (existsSync(pkgPath)) {
|
|
137
|
+
try {
|
|
138
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
|
|
139
|
+
if (pkg.name && !pkg.name.startsWith("@"))
|
|
140
|
+
return pkg.name;
|
|
141
|
+
if (pkg.name)
|
|
142
|
+
return pkg.name.split("/").pop() ?? basename(projectPath);
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// fall through
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return basename(projectPath);
|
|
149
|
+
}
|
|
150
|
+
function getGitCommit(projectPath) {
|
|
151
|
+
try {
|
|
152
|
+
return execSync("git rev-parse --short HEAD", {
|
|
153
|
+
cwd: projectPath,
|
|
154
|
+
encoding: "utf-8",
|
|
155
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
156
|
+
}).trim();
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return undefined;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
//# sourceMappingURL=extract.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract.js","sourceRoot":"","sources":["../src/extract.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sigil-engine/core — Public API
|
|
3
|
+
*
|
|
4
|
+
* The core engine for Sigil. Language-agnostic schema, plugin system,
|
|
5
|
+
* extraction orchestrator, diff engine, and serialization.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { extractContext, diffContexts, registerPlugin } from '@sigil-engine/core';
|
|
9
|
+
*
|
|
10
|
+
* registerPlugin(typescriptPlugin);
|
|
11
|
+
* const doc = await extractContext({ projectPath: './my-app' });
|
|
12
|
+
*/
|
|
13
|
+
export type { ContextDocument, Meta, MetaType, StackInfo, ExtractionMeta, Entity, EntityField, EntityRelation, Component, ComponentProp, Route, RouteMethod, ExportedSymbol, Patterns, Conventions, Dependency, CallEdge, ComponentEdge, EnvVar, } from "./schema.js";
|
|
14
|
+
export { createEmptyDocument } from "./schema.js";
|
|
15
|
+
export type { ExtractorPlugin, ParsedProject, ExtractResult, ApplyIntent, ApplyResult, IntentType, IntentConfidence, ProgressCallback, ProgressEvent, ProgressPhase, } from "./plugin.js";
|
|
16
|
+
export { registerPlugin, getPlugins, detectPlugins, clearPlugins, } from "./plugin.js";
|
|
17
|
+
export type { ExtractOptions } from "./extract.js";
|
|
18
|
+
export { extractContext, deduplicateExports } from "./extract.js";
|
|
19
|
+
export type { DiffResult, Change, ChangeType, ChangeCategory } from "./diff.js";
|
|
20
|
+
export { diffContexts, formatDiff } from "./diff.js";
|
|
21
|
+
export { serializeYaml, serializeJson, deserializeYaml, deserializeJson, writeContextFile, readContextFile, } from "./serialize.js";
|
|
22
|
+
export type { FileCache, ChangedFiles } from "./cache.js";
|
|
23
|
+
export { readCache, writeCache, buildCacheFromFiles, getChangedFiles, } from "./cache.js";
|
|
24
|
+
export type { SafetyCheckpoint, ValidationResult, ConfirmCallback } from "./safety.js";
|
|
25
|
+
export { preApplySafety, postApplyValidation, rollbackApply, getGitStatus, } from "./safety.js";
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,YAAY,EACV,eAAe,EACf,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,cAAc,EACd,MAAM,EACN,WAAW,EACX,cAAc,EACd,SAAS,EACT,aAAa,EACb,KAAK,EACL,WAAW,EACX,cAAc,EACd,QAAQ,EACR,WAAW,EACX,UAAU,EACV,QAAQ,EACR,aAAa,EACb,MAAM,GACP,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,YAAY,EACV,eAAe,EACf,aAAa,EACb,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,aAAa,EACb,aAAa,GACd,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC;AAGrB,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAGlE,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChF,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,EACL,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,eAAe,GAChB,MAAM,YAAY,CAAC;AAGpB,YAAY,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sigil-engine/core — Public API
|
|
3
|
+
*
|
|
4
|
+
* The core engine for Sigil. Language-agnostic schema, plugin system,
|
|
5
|
+
* extraction orchestrator, diff engine, and serialization.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* import { extractContext, diffContexts, registerPlugin } from '@sigil-engine/core';
|
|
9
|
+
*
|
|
10
|
+
* registerPlugin(typescriptPlugin);
|
|
11
|
+
* const doc = await extractContext({ projectPath: './my-app' });
|
|
12
|
+
*/
|
|
13
|
+
export { createEmptyDocument } from "./schema.js";
|
|
14
|
+
export { registerPlugin, getPlugins, detectPlugins, clearPlugins, } from "./plugin.js";
|
|
15
|
+
export { extractContext, deduplicateExports } from "./extract.js";
|
|
16
|
+
export { diffContexts, formatDiff } from "./diff.js";
|
|
17
|
+
// Serialization
|
|
18
|
+
export { serializeYaml, serializeJson, deserializeYaml, deserializeJson, writeContextFile, readContextFile, } from "./serialize.js";
|
|
19
|
+
export { readCache, writeCache, buildCacheFromFiles, getChangedFiles, } from "./cache.js";
|
|
20
|
+
export { preApplySafety, postApplyValidation, rollbackApply, getGitStatus, } from "./safety.js";
|
|
21
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAyBH,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAgBlD,OAAO,EACL,cAAc,EACd,UAAU,EACV,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC;AAIrB,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAIlE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAErD,gBAAgB;AAChB,OAAO,EACL,aAAa,EACb,aAAa,EACb,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAIxB,OAAO,EACL,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,eAAe,GAChB,MAAM,YAAY,CAAC;AAIpB,OAAO,EACL,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,YAAY,GACb,MAAM,aAAa,CAAC"}
|
package/dist/plugin.d.ts
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sigil Plugin System — the extensibility contract.
|
|
3
|
+
*
|
|
4
|
+
* Every language parser implements `ExtractorPlugin`. The core engine
|
|
5
|
+
* discovers registered plugins and orchestrates them.
|
|
6
|
+
*
|
|
7
|
+
* To add Python support:
|
|
8
|
+
* 1. Create @sigil-engine/parser-python
|
|
9
|
+
* 2. Implement ExtractorPlugin
|
|
10
|
+
* 3. Export a default plugin instance
|
|
11
|
+
* 4. Users install it — Sigil discovers it automatically
|
|
12
|
+
*/
|
|
13
|
+
import type { ContextDocument } from "./schema.js";
|
|
14
|
+
/**
|
|
15
|
+
* The parsed project representation passed to plugins.
|
|
16
|
+
* Language-agnostic — each plugin casts or wraps this with its own type.
|
|
17
|
+
*/
|
|
18
|
+
export interface ParsedProject {
|
|
19
|
+
/** Absolute path to the project root */
|
|
20
|
+
projectPath: string;
|
|
21
|
+
/** List of source file paths (absolute) */
|
|
22
|
+
sourceFiles: string[];
|
|
23
|
+
/** Package manifest (package.json, pyproject.toml, etc.) parsed as object */
|
|
24
|
+
manifest?: Record<string, unknown>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Result returned by a plugin's extract method.
|
|
28
|
+
* Partial<ContextDocument> — plugins only fill what they understand.
|
|
29
|
+
*/
|
|
30
|
+
export type ExtractResult = Partial<Omit<ContextDocument, "version" | "project" | "_extraction">>;
|
|
31
|
+
/**
|
|
32
|
+
* The core plugin contract. Every language parser implements this.
|
|
33
|
+
*/
|
|
34
|
+
export interface ExtractorPlugin {
|
|
35
|
+
/** Unique plugin name (e.g., "typescript", "python", "go") */
|
|
36
|
+
name: string;
|
|
37
|
+
/** Semver version of the plugin */
|
|
38
|
+
version: string;
|
|
39
|
+
/** Languages/frameworks this plugin handles */
|
|
40
|
+
languages: string[];
|
|
41
|
+
/**
|
|
42
|
+
* Check if this plugin should run for the given project.
|
|
43
|
+
* Called before extract() — return false to skip.
|
|
44
|
+
*
|
|
45
|
+
* Example: typescript plugin checks for tsconfig.json or .ts files
|
|
46
|
+
*/
|
|
47
|
+
detect(projectPath: string): boolean | Promise<boolean>;
|
|
48
|
+
/**
|
|
49
|
+
* Initialize the plugin for a specific project.
|
|
50
|
+
* Returns a ParsedProject (or plugin-specific extension of it).
|
|
51
|
+
* Called once before extract().
|
|
52
|
+
*/
|
|
53
|
+
init(projectPath: string): ParsedProject | Promise<ParsedProject>;
|
|
54
|
+
/**
|
|
55
|
+
* Extract context from the project.
|
|
56
|
+
* Returns partial context — the orchestrator merges results from all plugins.
|
|
57
|
+
*/
|
|
58
|
+
extract(project: ParsedProject): ExtractResult | Promise<ExtractResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Optional: handle apply intents for elements this plugin created.
|
|
61
|
+
* Called by the apply engine when an intent targets a _meta.tags
|
|
62
|
+
* value owned by this plugin.
|
|
63
|
+
*/
|
|
64
|
+
apply?(intent: ApplyIntent, projectPath: string): ApplyResult | Promise<ApplyResult>;
|
|
65
|
+
}
|
|
66
|
+
export type IntentType = "AddEntity" | "RemoveEntity" | "AddField" | "RemoveField" | "ModifyField" | "RenameSymbol" | "AddComponent" | "RemoveComponent" | "AddRoute" | "RemoveRoute" | "AddMethod" | "RemoveMethod" | "ModifyProps" | "ChangeSignature" | "MoveFile" | "AddDependency" | "RemoveDependency";
|
|
67
|
+
export type IntentConfidence = "deterministic" | "needs-ai";
|
|
68
|
+
export interface ApplyIntent {
|
|
69
|
+
type: IntentType;
|
|
70
|
+
confidence: IntentConfidence;
|
|
71
|
+
target_file?: string;
|
|
72
|
+
target_symbol?: string;
|
|
73
|
+
description: string;
|
|
74
|
+
old_value?: unknown;
|
|
75
|
+
new_value?: unknown;
|
|
76
|
+
priority: number;
|
|
77
|
+
}
|
|
78
|
+
export interface ApplyResult {
|
|
79
|
+
intent: ApplyIntent;
|
|
80
|
+
success: boolean;
|
|
81
|
+
error?: string;
|
|
82
|
+
files_created: string[];
|
|
83
|
+
files_modified: string[];
|
|
84
|
+
preview?: string;
|
|
85
|
+
code?: string;
|
|
86
|
+
}
|
|
87
|
+
/** Register a plugin with Sigil */
|
|
88
|
+
export declare function registerPlugin(plugin: ExtractorPlugin): void;
|
|
89
|
+
/** Get all registered plugins */
|
|
90
|
+
export declare function getPlugins(): readonly ExtractorPlugin[];
|
|
91
|
+
/** Get plugins that detect support for a given project */
|
|
92
|
+
export declare function detectPlugins(projectPath: string): Promise<ExtractorPlugin[]>;
|
|
93
|
+
/** Clear all registered plugins (for testing) */
|
|
94
|
+
export declare function clearPlugins(): void;
|
|
95
|
+
export type ProgressPhase = "init" | "detect" | "extract" | "merge" | "serialize" | "cache" | "done";
|
|
96
|
+
export interface ProgressEvent {
|
|
97
|
+
phase: ProgressPhase;
|
|
98
|
+
plugin?: string;
|
|
99
|
+
message: string;
|
|
100
|
+
elapsed_ms?: number;
|
|
101
|
+
}
|
|
102
|
+
export type ProgressCallback = (event: ProgressEvent) => void;
|
|
103
|
+
//# sourceMappingURL=plugin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
|
package/dist/plugin.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sigil Plugin System — the extensibility contract.
|
|
3
|
+
*
|
|
4
|
+
* Every language parser implements `ExtractorPlugin`. The core engine
|
|
5
|
+
* discovers registered plugins and orchestrates them.
|
|
6
|
+
*
|
|
7
|
+
* To add Python support:
|
|
8
|
+
* 1. Create @sigil-engine/parser-python
|
|
9
|
+
* 2. Implement ExtractorPlugin
|
|
10
|
+
* 3. Export a default plugin instance
|
|
11
|
+
* 4. Users install it — Sigil discovers it automatically
|
|
12
|
+
*/
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// Plugin registry
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
const registry = [];
|
|
17
|
+
/** Register a plugin with Sigil */
|
|
18
|
+
export function registerPlugin(plugin) {
|
|
19
|
+
// Prevent duplicate registration
|
|
20
|
+
const existing = registry.findIndex((p) => p.name === plugin.name);
|
|
21
|
+
if (existing >= 0) {
|
|
22
|
+
registry[existing] = plugin;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
registry.push(plugin);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/** Get all registered plugins */
|
|
29
|
+
export function getPlugins() {
|
|
30
|
+
return registry;
|
|
31
|
+
}
|
|
32
|
+
/** Get plugins that detect support for a given project */
|
|
33
|
+
export async function detectPlugins(projectPath) {
|
|
34
|
+
const detected = [];
|
|
35
|
+
for (const plugin of registry) {
|
|
36
|
+
const supports = await plugin.detect(projectPath);
|
|
37
|
+
if (supports) {
|
|
38
|
+
detected.push(plugin);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return detected;
|
|
42
|
+
}
|
|
43
|
+
/** Clear all registered plugins (for testing) */
|
|
44
|
+
export function clearPlugins() {
|
|
45
|
+
registry.length = 0;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=plugin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmHH,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,MAAM,QAAQ,GAAsB,EAAE,CAAC;AAEvC,mCAAmC;AACnC,MAAM,UAAU,cAAc,CAAC,MAAuB;IACpD,iCAAiC;IACjC,MAAM,QAAQ,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC;IACnE,IAAI,QAAQ,IAAI,CAAC,EAAE,CAAC;QAClB,QAAQ,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC;IAC9B,CAAC;SAAM,CAAC;QACN,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACxB,CAAC;AACH,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,UAAU;IACxB,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,WAAmB;IACrD,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,KAAK,MAAM,MAAM,IAAI,QAAQ,EAAE,CAAC;QAC9B,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;QAClD,IAAI,QAAQ,EAAE,CAAC;YACb,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxB,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,YAAY;IAC1B,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;AACtB,CAAC"}
|
package/dist/safety.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply safety mechanisms — git stash before, validation after, rollback on failure.
|
|
3
|
+
*
|
|
4
|
+
* SECURITY: All git operations use execFileSync (not execSync) to prevent
|
|
5
|
+
* shell injection. Destructive operations require explicit confirmation.
|
|
6
|
+
*/
|
|
7
|
+
export interface SafetyCheckpoint {
|
|
8
|
+
hadDirtyFiles: boolean;
|
|
9
|
+
stashCreated: boolean;
|
|
10
|
+
originalHead: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Callback for confirming destructive operations.
|
|
14
|
+
* Return true to proceed, false to abort.
|
|
15
|
+
*/
|
|
16
|
+
export type ConfirmCallback = (message: string) => boolean | Promise<boolean>;
|
|
17
|
+
export declare function preApplySafety(projectPath: string, confirm?: ConfirmCallback): SafetyCheckpoint;
|
|
18
|
+
export interface ValidationResult {
|
|
19
|
+
typesOk: boolean;
|
|
20
|
+
errors: string[];
|
|
21
|
+
}
|
|
22
|
+
export declare function postApplyValidation(projectPath: string): ValidationResult;
|
|
23
|
+
export declare function rollbackApply(projectPath: string, checkpoint: SafetyCheckpoint, confirm?: ConfirmCallback): Promise<boolean>;
|
|
24
|
+
export declare function getGitStatus(projectPath: string): string;
|
|
25
|
+
//# sourceMappingURL=safety.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.d.ts","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH,MAAM,WAAW,gBAAgB;IAC/B,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAK9E,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,eAAyB,GACjC,gBAAgB,CA4ClB;AAMD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED,wBAAgB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,gBAAgB,CAsBzE;AAMD,wBAAsB,aAAa,CACjC,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,gBAAgB,EAC5B,OAAO,GAAE,eAAyB,GACjC,OAAO,CAAC,OAAO,CAAC,CAiDlB;AAMD,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAUxD"}
|
package/dist/safety.js
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply safety mechanisms — git stash before, validation after, rollback on failure.
|
|
3
|
+
*
|
|
4
|
+
* SECURITY: All git operations use execFileSync (not execSync) to prevent
|
|
5
|
+
* shell injection. Destructive operations require explicit confirmation.
|
|
6
|
+
*/
|
|
7
|
+
import { execFileSync } from "child_process";
|
|
8
|
+
import { resolve } from "path";
|
|
9
|
+
/** Default confirmation — always denies (safe default) */
|
|
10
|
+
const denyAll = () => false;
|
|
11
|
+
export function preApplySafety(projectPath, confirm = denyAll) {
|
|
12
|
+
const absPath = resolve(projectPath);
|
|
13
|
+
// Get current HEAD — using execFileSync (no shell)
|
|
14
|
+
let originalHead = "";
|
|
15
|
+
try {
|
|
16
|
+
originalHead = execFileSync("git", ["rev-parse", "HEAD"], {
|
|
17
|
+
cwd: absPath,
|
|
18
|
+
encoding: "utf-8",
|
|
19
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
20
|
+
}).trim();
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
// Not a git repo — skip safety
|
|
24
|
+
return { hadDirtyFiles: false, stashCreated: false, originalHead: "" };
|
|
25
|
+
}
|
|
26
|
+
// Check for dirty files
|
|
27
|
+
let gitStatus = "";
|
|
28
|
+
try {
|
|
29
|
+
gitStatus = execFileSync("git", ["status", "--porcelain"], {
|
|
30
|
+
cwd: absPath,
|
|
31
|
+
encoding: "utf-8",
|
|
32
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
33
|
+
}).trim();
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return { hadDirtyFiles: false, stashCreated: false, originalHead };
|
|
37
|
+
}
|
|
38
|
+
const hadDirtyFiles = gitStatus.length > 0;
|
|
39
|
+
if (hadDirtyFiles) {
|
|
40
|
+
try {
|
|
41
|
+
execFileSync("git", ["stash", "push", "-m", "sigil-pre-apply"], {
|
|
42
|
+
cwd: absPath,
|
|
43
|
+
encoding: "utf-8",
|
|
44
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
45
|
+
});
|
|
46
|
+
return { hadDirtyFiles, stashCreated: true, originalHead };
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return { hadDirtyFiles, stashCreated: false, originalHead };
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { hadDirtyFiles, stashCreated: false, originalHead };
|
|
53
|
+
}
|
|
54
|
+
export function postApplyValidation(projectPath) {
|
|
55
|
+
const absPath = resolve(projectPath);
|
|
56
|
+
try {
|
|
57
|
+
execFileSync("npx", ["tsc", "--noEmit"], {
|
|
58
|
+
cwd: absPath,
|
|
59
|
+
encoding: "utf-8",
|
|
60
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
61
|
+
timeout: 30000,
|
|
62
|
+
});
|
|
63
|
+
return { typesOk: true, errors: [] };
|
|
64
|
+
}
|
|
65
|
+
catch (err) {
|
|
66
|
+
const output = err.stdout ??
|
|
67
|
+
err.stderr ??
|
|
68
|
+
"";
|
|
69
|
+
const errors = output
|
|
70
|
+
.split("\n")
|
|
71
|
+
.filter((line) => line.includes("error TS"))
|
|
72
|
+
.slice(0, 10);
|
|
73
|
+
return { typesOk: false, errors };
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
// Rollback
|
|
78
|
+
// ---------------------------------------------------------------------------
|
|
79
|
+
export async function rollbackApply(projectPath, checkpoint, confirm = denyAll) {
|
|
80
|
+
const absPath = resolve(projectPath);
|
|
81
|
+
// Require confirmation before destructive rollback
|
|
82
|
+
const confirmed = await confirm("Apply produced type errors. Roll back all changes and restore previous state?");
|
|
83
|
+
if (!confirmed) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
// Discard apply changes — execFileSync, no shell
|
|
87
|
+
try {
|
|
88
|
+
execFileSync("git", ["checkout", "."], {
|
|
89
|
+
cwd: absPath,
|
|
90
|
+
encoding: "utf-8",
|
|
91
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Could not roll back
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
// Clean untracked files created by apply
|
|
99
|
+
try {
|
|
100
|
+
execFileSync("git", ["clean", "-fd"], {
|
|
101
|
+
cwd: absPath,
|
|
102
|
+
encoding: "utf-8",
|
|
103
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
catch {
|
|
107
|
+
// Non-fatal
|
|
108
|
+
}
|
|
109
|
+
// Restore stash if we created one
|
|
110
|
+
if (checkpoint.stashCreated) {
|
|
111
|
+
try {
|
|
112
|
+
execFileSync("git", ["stash", "pop"], {
|
|
113
|
+
cwd: absPath,
|
|
114
|
+
encoding: "utf-8",
|
|
115
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
// Stash pop failed — user must handle manually
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
}
|
|
124
|
+
// ---------------------------------------------------------------------------
|
|
125
|
+
// Git commit helper (for post-apply)
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
export function getGitStatus(projectPath) {
|
|
128
|
+
try {
|
|
129
|
+
return execFileSync("git", ["status", "--porcelain"], {
|
|
130
|
+
cwd: resolve(projectPath),
|
|
131
|
+
encoding: "utf-8",
|
|
132
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
133
|
+
}).trim();
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return "";
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=safety.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.js","sourceRoot":"","sources":["../src/safety.ts"],"names":[],"mappings":"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"}
|