logicstamp-context 0.1.1 → 0.2.1
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/LLM_CONTEXT.md +4 -3
- package/README.md +116 -19
- package/dist/cli/commands/compare.d.ts.map +1 -1
- package/dist/cli/commands/compare.js +17 -8
- package/dist/cli/commands/compare.js.map +1 -1
- package/dist/cli/commands/context/bundleFormatter.d.ts +20 -0
- package/dist/cli/commands/context/bundleFormatter.d.ts.map +1 -0
- package/dist/cli/commands/context/bundleFormatter.js +55 -0
- package/dist/cli/commands/context/bundleFormatter.js.map +1 -0
- package/dist/cli/commands/context/configManager.d.ts +23 -0
- package/dist/cli/commands/context/configManager.d.ts.map +1 -0
- package/dist/cli/commands/context/configManager.js +69 -0
- package/dist/cli/commands/context/configManager.js.map +1 -0
- package/dist/cli/commands/context/contractBuilder.d.ts +18 -0
- package/dist/cli/commands/context/contractBuilder.d.ts.map +1 -0
- package/dist/cli/commands/context/contractBuilder.js +72 -0
- package/dist/cli/commands/context/contractBuilder.js.map +1 -0
- package/dist/cli/commands/context/fileWriter.d.ts +38 -0
- package/dist/cli/commands/context/fileWriter.d.ts.map +1 -0
- package/dist/cli/commands/context/fileWriter.js +170 -0
- package/dist/cli/commands/context/fileWriter.js.map +1 -0
- package/dist/cli/commands/context/statsCalculator.d.ts +44 -0
- package/dist/cli/commands/context/statsCalculator.d.ts.map +1 -0
- package/dist/cli/commands/context/statsCalculator.js +150 -0
- package/dist/cli/commands/context/statsCalculator.js.map +1 -0
- package/dist/cli/commands/context/tokenEstimator.d.ts +76 -0
- package/dist/cli/commands/context/tokenEstimator.d.ts.map +1 -0
- package/dist/cli/commands/context/tokenEstimator.js +258 -0
- package/dist/cli/commands/context/tokenEstimator.js.map +1 -0
- package/dist/cli/commands/context.d.ts +1 -0
- package/dist/cli/commands/context.d.ts.map +1 -1
- package/dist/cli/commands/context.js +72 -399
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/commands/style.d.ts +11 -0
- package/dist/cli/commands/style.d.ts.map +1 -0
- package/dist/cli/commands/style.js +15 -0
- package/dist/cli/commands/style.js.map +1 -0
- package/dist/cli/handlers/cleanHandler.d.ts +5 -0
- package/dist/cli/handlers/cleanHandler.d.ts.map +1 -0
- package/dist/cli/handlers/cleanHandler.js +28 -0
- package/dist/cli/handlers/cleanHandler.js.map +1 -0
- package/dist/cli/handlers/compareHandler.d.ts +5 -0
- package/dist/cli/handlers/compareHandler.d.ts.map +1 -0
- package/dist/cli/handlers/compareHandler.js +332 -0
- package/dist/cli/handlers/compareHandler.js.map +1 -0
- package/dist/cli/handlers/contextHandler.d.ts +5 -0
- package/dist/cli/handlers/contextHandler.d.ts.map +1 -0
- package/dist/cli/handlers/contextHandler.js +24 -0
- package/dist/cli/handlers/contextHandler.js.map +1 -0
- package/dist/cli/handlers/initHandler.d.ts +6 -0
- package/dist/cli/handlers/initHandler.d.ts.map +1 -0
- package/dist/cli/handlers/initHandler.js +30 -0
- package/dist/cli/handlers/initHandler.js.map +1 -0
- package/dist/cli/handlers/styleHandler.d.ts +5 -0
- package/dist/cli/handlers/styleHandler.d.ts.map +1 -0
- package/dist/cli/handlers/styleHandler.js +30 -0
- package/dist/cli/handlers/styleHandler.js.map +1 -0
- package/dist/cli/handlers/validateHandler.d.ts +5 -0
- package/dist/cli/handlers/validateHandler.d.ts.map +1 -0
- package/dist/cli/handlers/validateHandler.js +23 -0
- package/dist/cli/handlers/validateHandler.js.map +1 -0
- package/dist/cli/parser/argumentParser.d.ts +44 -0
- package/dist/cli/parser/argumentParser.d.ts.map +1 -0
- package/dist/cli/parser/argumentParser.js +194 -0
- package/dist/cli/parser/argumentParser.js.map +1 -0
- package/dist/cli/parser/helpText.d.ts +11 -0
- package/dist/cli/parser/helpText.d.ts.map +1 -0
- package/dist/cli/parser/helpText.js +373 -0
- package/dist/cli/parser/helpText.js.map +1 -0
- package/dist/cli/stamp.js +14 -821
- package/dist/cli/stamp.js.map +1 -1
- package/dist/core/astParser/detectors.d.ts +24 -0
- package/dist/core/astParser/detectors.d.ts.map +1 -0
- package/dist/core/astParser/detectors.js +102 -0
- package/dist/core/astParser/detectors.js.map +1 -0
- package/dist/core/astParser/extractors/componentExtractor.d.ts +13 -0
- package/dist/core/astParser/extractors/componentExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/componentExtractor.js +41 -0
- package/dist/core/astParser/extractors/componentExtractor.js.map +1 -0
- package/dist/core/astParser/extractors/eventExtractor.d.ts +14 -0
- package/dist/core/astParser/extractors/eventExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/eventExtractor.js +49 -0
- package/dist/core/astParser/extractors/eventExtractor.js.map +1 -0
- package/dist/core/astParser/extractors/propExtractor.d.ts +14 -0
- package/dist/core/astParser/extractors/propExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/propExtractor.js +73 -0
- package/dist/core/astParser/extractors/propExtractor.js.map +1 -0
- package/dist/core/astParser/extractors/stateExtractor.d.ts +13 -0
- package/dist/core/astParser/extractors/stateExtractor.d.ts.map +1 -0
- package/dist/core/astParser/extractors/stateExtractor.js +66 -0
- package/dist/core/astParser/extractors/stateExtractor.js.map +1 -0
- package/dist/core/astParser.d.ts.map +1 -1
- package/dist/core/astParser.js +5 -307
- package/dist/core/astParser.js.map +1 -1
- package/dist/core/contractBuilder.d.ts +1 -0
- package/dist/core/contractBuilder.d.ts.map +1 -1
- package/dist/core/contractBuilder.js +1 -0
- package/dist/core/contractBuilder.js.map +1 -1
- package/dist/core/pack/builder.d.ts +35 -0
- package/dist/core/pack/builder.d.ts.map +1 -0
- package/dist/core/pack/builder.js +76 -0
- package/dist/core/pack/builder.js.map +1 -0
- package/dist/core/pack/collector.d.ts +20 -0
- package/dist/core/pack/collector.d.ts.map +1 -0
- package/dist/core/pack/collector.js +71 -0
- package/dist/core/pack/collector.js.map +1 -0
- package/dist/core/pack/loader.d.ts +23 -0
- package/dist/core/pack/loader.d.ts.map +1 -0
- package/dist/core/pack/loader.js +66 -0
- package/dist/core/pack/loader.js.map +1 -0
- package/dist/core/pack/resolver.d.ts +21 -0
- package/dist/core/pack/resolver.d.ts.map +1 -0
- package/dist/core/pack/resolver.js +79 -0
- package/dist/core/pack/resolver.js.map +1 -0
- package/dist/core/pack.d.ts +17 -27
- package/dist/core/pack.d.ts.map +1 -1
- package/dist/core/pack.js +18 -225
- package/dist/core/pack.js.map +1 -1
- package/dist/core/styleExtractor/index.d.ts +11 -0
- package/dist/core/styleExtractor/index.d.ts.map +1 -0
- package/dist/core/styleExtractor/index.js +11 -0
- package/dist/core/styleExtractor/index.js.map +1 -0
- package/dist/core/styleExtractor/layout.d.ts +14 -0
- package/dist/core/styleExtractor/layout.d.ts.map +1 -0
- package/dist/core/styleExtractor/layout.js +86 -0
- package/dist/core/styleExtractor/layout.js.map +1 -0
- package/dist/core/styleExtractor/motion.d.ts +20 -0
- package/dist/core/styleExtractor/motion.d.ts.map +1 -0
- package/dist/core/styleExtractor/motion.js +74 -0
- package/dist/core/styleExtractor/motion.js.map +1 -0
- package/dist/core/styleExtractor/scss.d.ts +30 -0
- package/dist/core/styleExtractor/scss.d.ts.map +1 -0
- package/dist/core/styleExtractor/scss.js +80 -0
- package/dist/core/styleExtractor/scss.js.map +1 -0
- package/dist/core/styleExtractor/styleExtractor.d.ts +11 -0
- package/dist/core/styleExtractor/styleExtractor.d.ts.map +1 -0
- package/dist/core/styleExtractor/styleExtractor.js +115 -0
- package/dist/core/styleExtractor/styleExtractor.js.map +1 -0
- package/dist/core/styleExtractor/styled.d.ts +13 -0
- package/dist/core/styleExtractor/styled.d.ts.map +1 -0
- package/dist/core/styleExtractor/styled.js +31 -0
- package/dist/core/styleExtractor/styled.js.map +1 -0
- package/dist/core/styleExtractor/tailwind.d.ts +16 -0
- package/dist/core/styleExtractor/tailwind.d.ts.map +1 -0
- package/dist/core/styleExtractor/tailwind.js +85 -0
- package/dist/core/styleExtractor/tailwind.js.map +1 -0
- package/dist/core/styleExtractor.d.ts +8 -0
- package/dist/core/styleExtractor.d.ts.map +1 -0
- package/dist/core/styleExtractor.js +8 -0
- package/dist/core/styleExtractor.js.map +1 -0
- package/dist/types/UIFContract.d.ts +71 -0
- package/dist/types/UIFContract.d.ts.map +1 -1
- package/dist/types/UIFContract.js.map +1 -1
- package/dist/utils/tokens.d.ts +18 -10
- package/dist/utils/tokens.d.ts.map +1 -1
- package/dist/utils/tokens.js +100 -10
- package/dist/utils/tokens.js.map +1 -1
- package/package.json +5 -1
- package/schema/logicstamp.context.schema.json +288 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader module - Load contracts, manifests, and source code
|
|
3
|
+
*/
|
|
4
|
+
import type { UIFContract } from '../../types/UIFContract.js';
|
|
5
|
+
import type { ProjectManifest } from '../manifest.js';
|
|
6
|
+
/**
|
|
7
|
+
* Load manifest from file
|
|
8
|
+
*/
|
|
9
|
+
export declare function loadManifest(basePath: string): Promise<ProjectManifest>;
|
|
10
|
+
/**
|
|
11
|
+
* Load a sidecar contract file
|
|
12
|
+
* Sidecar path is computed from the manifest key (project-relative): resolved from projectRoot + key + '.uif.json'
|
|
13
|
+
*/
|
|
14
|
+
export declare function loadContract(entryId: string, projectRoot: string): Promise<UIFContract | null>;
|
|
15
|
+
/**
|
|
16
|
+
* Extract code header (JSDoc @uif block) from source file
|
|
17
|
+
*/
|
|
18
|
+
export declare function extractCodeHeader(entryId: string, projectRoot: string): Promise<string | null>;
|
|
19
|
+
/**
|
|
20
|
+
* Read full source code
|
|
21
|
+
*/
|
|
22
|
+
export declare function readSourceCode(entryId: string, projectRoot: string): Promise<string | null>;
|
|
23
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/core/pack/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEtD;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAU7E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAYpG;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAepG;AAED;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOjG"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loader module - Load contracts, manifests, and source code
|
|
3
|
+
*/
|
|
4
|
+
import { readFile } from 'node:fs/promises';
|
|
5
|
+
import { join, resolve, isAbsolute } from 'node:path';
|
|
6
|
+
/**
|
|
7
|
+
* Load manifest from file
|
|
8
|
+
*/
|
|
9
|
+
export async function loadManifest(basePath) {
|
|
10
|
+
const manifestPath = join(basePath, 'logicstamp.manifest.json');
|
|
11
|
+
try {
|
|
12
|
+
const content = await readFile(manifestPath, 'utf8');
|
|
13
|
+
return JSON.parse(content);
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
throw new Error(`Failed to load manifest at ${manifestPath}: ${error.message}`);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Load a sidecar contract file
|
|
21
|
+
* Sidecar path is computed from the manifest key (project-relative): resolved from projectRoot + key + '.uif.json'
|
|
22
|
+
*/
|
|
23
|
+
export async function loadContract(entryId, projectRoot) {
|
|
24
|
+
// Resolve relative path from project root
|
|
25
|
+
const absolutePath = isAbsolute(entryId) ? entryId : resolve(projectRoot, entryId);
|
|
26
|
+
const sidecarPath = `${absolutePath}.uif.json`;
|
|
27
|
+
try {
|
|
28
|
+
const content = await readFile(sidecarPath, 'utf8');
|
|
29
|
+
return JSON.parse(content);
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
// Sidecar file doesn't exist or can't be read
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Extract code header (JSDoc @uif block) from source file
|
|
38
|
+
*/
|
|
39
|
+
export async function extractCodeHeader(entryId, projectRoot) {
|
|
40
|
+
try {
|
|
41
|
+
const absolutePath = isAbsolute(entryId) ? entryId : resolve(projectRoot, entryId);
|
|
42
|
+
const content = await readFile(absolutePath, 'utf8');
|
|
43
|
+
// Look for @uif JSDoc block
|
|
44
|
+
const headerMatch = content.match(/\/\*\*[\s\S]*?@uif[\s\S]*?\*\//);
|
|
45
|
+
if (headerMatch) {
|
|
46
|
+
return headerMatch[0];
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Read full source code
|
|
56
|
+
*/
|
|
57
|
+
export async function readSourceCode(entryId, projectRoot) {
|
|
58
|
+
try {
|
|
59
|
+
const absolutePath = isAbsolute(entryId) ? entryId : resolve(projectRoot, entryId);
|
|
60
|
+
return await readFile(absolutePath, 'utf8');
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/core/pack/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAItD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,QAAgB;IACjD,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,EAAE,0BAA0B,CAAC,CAAC;IAChE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAoB,CAAC;IAChD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,8BAA8B,YAAY,KAAM,KAAe,CAAC,OAAO,EAAE,CAC1E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAe,EAAE,WAAmB;IACrE,0CAA0C;IAC1C,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACnF,MAAM,WAAW,GAAG,GAAG,YAAY,WAAW,CAAC;IAE/C,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACpD,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,8CAA8C;QAC9C,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,OAAe,EAAE,WAAmB;IAC1E,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnF,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;QAErD,4BAA4B;QAC5B,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpE,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,WAAW,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe,EAAE,WAAmB;IACvE,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACnF,OAAO,MAAM,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IAC9C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolver module - Resolve component names and paths to manifest keys
|
|
3
|
+
*/
|
|
4
|
+
import type { ProjectManifest, ComponentNode } from '../manifest.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve input (path or name) to a manifest key
|
|
7
|
+
* This is the canonical resolution used by both pack and similar commands
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveKey(manifest: ProjectManifest, input: string): string | null;
|
|
10
|
+
/**
|
|
11
|
+
* Find a component node by name or path
|
|
12
|
+
* Returns the component node and the manifest key it was found under
|
|
13
|
+
*/
|
|
14
|
+
export declare function findComponentByName(manifest: ProjectManifest, nameOrPath: string): ComponentNode | null;
|
|
15
|
+
/**
|
|
16
|
+
* Resolve a dependency name to a manifest key
|
|
17
|
+
* Uses the canonical resolveKey() function for consistent resolution
|
|
18
|
+
* Prioritizes relative paths to avoid cross-directory conflicts
|
|
19
|
+
*/
|
|
20
|
+
export declare function resolveDependency(manifest: ProjectManifest, depName: string, parentId: string): string | null;
|
|
21
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../src/core/pack/resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAErE;;;GAGG;AACH,wBAAgB,UAAU,CACxB,QAAQ,EAAE,eAAe,EACzB,KAAK,EAAE,MAAM,GACZ,MAAM,GAAG,IAAI,CAkCf;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,eAAe,EACzB,UAAU,EAAE,MAAM,GACjB,aAAa,GAAG,IAAI,CAGtB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,eAAe,EACzB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CA6Bf"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolver module - Resolve component names and paths to manifest keys
|
|
3
|
+
*/
|
|
4
|
+
import { normalizeEntryId } from '../../utils/fsx.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve input (path or name) to a manifest key
|
|
7
|
+
* This is the canonical resolution used by both pack and similar commands
|
|
8
|
+
*/
|
|
9
|
+
export function resolveKey(manifest, input) {
|
|
10
|
+
const normalized = normalizeEntryId(input);
|
|
11
|
+
// Try exact match first (normalized key match)
|
|
12
|
+
if (manifest.components[normalized]) {
|
|
13
|
+
return normalized;
|
|
14
|
+
}
|
|
15
|
+
// Try to find by normalized key match
|
|
16
|
+
const entries = Object.entries(manifest.components);
|
|
17
|
+
for (const [key, node] of entries) {
|
|
18
|
+
if (normalizeEntryId(key) === normalized || normalizeEntryId(node.entryId) === normalized) {
|
|
19
|
+
return key; // Return the manifest key, not the node's entryId
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
// Look for name match (Button, LoginForm, etc.)
|
|
23
|
+
// Build name → [keys] index for ambiguous cases
|
|
24
|
+
const nameMatches = [];
|
|
25
|
+
for (const [key] of entries) {
|
|
26
|
+
const fileName = key.split(/[/\\]/).pop()?.replace(/\.(tsx?|jsx?)$/, '');
|
|
27
|
+
if (fileName === input || fileName === input.replace(/\.(tsx?|jsx?)$/, '')) {
|
|
28
|
+
nameMatches.push(key);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (nameMatches.length === 1) {
|
|
32
|
+
return nameMatches[0];
|
|
33
|
+
}
|
|
34
|
+
else if (nameMatches.length > 1) {
|
|
35
|
+
// Ambiguous - return first match but this should be handled by caller
|
|
36
|
+
return nameMatches[0];
|
|
37
|
+
}
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Find a component node by name or path
|
|
42
|
+
* Returns the component node and the manifest key it was found under
|
|
43
|
+
*/
|
|
44
|
+
export function findComponentByName(manifest, nameOrPath) {
|
|
45
|
+
const key = resolveKey(manifest, nameOrPath);
|
|
46
|
+
return key ? manifest.components[key] : null;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Resolve a dependency name to a manifest key
|
|
50
|
+
* Uses the canonical resolveKey() function for consistent resolution
|
|
51
|
+
* Prioritizes relative paths to avoid cross-directory conflicts
|
|
52
|
+
*/
|
|
53
|
+
export function resolveDependency(manifest, depName, parentId) {
|
|
54
|
+
// parentId is a manifest key (canonical identifier)
|
|
55
|
+
// First, try relative path resolution based on parent directory
|
|
56
|
+
// This ensures we resolve to components in the same directory tree first
|
|
57
|
+
// parentId is a manifest key (normalized path), extract directory
|
|
58
|
+
const parentDir = parentId.substring(0, parentId.lastIndexOf('/'));
|
|
59
|
+
const possiblePaths = [
|
|
60
|
+
`${parentDir}/${depName}.tsx`,
|
|
61
|
+
`${parentDir}/${depName}.ts`,
|
|
62
|
+
`${parentDir}/${depName}/index.tsx`,
|
|
63
|
+
`${parentDir}/${depName}/index.ts`,
|
|
64
|
+
];
|
|
65
|
+
for (const path of possiblePaths) {
|
|
66
|
+
const key = resolveKey(manifest, path);
|
|
67
|
+
if (key) {
|
|
68
|
+
return key; // Return manifest key (canonical identifier)
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Only fall back to global name search if relative paths didn't work
|
|
72
|
+
// This prevents cross-directory conflicts (e.g., tests/fixtures vs examples)
|
|
73
|
+
const key = resolveKey(manifest, depName);
|
|
74
|
+
if (key) {
|
|
75
|
+
return key; // Return manifest key (canonical identifier)
|
|
76
|
+
}
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../../src/core/pack/resolver.ts"],"names":[],"mappings":"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"}
|
package/dist/core/pack.d.ts
CHANGED
|
@@ -23,7 +23,9 @@
|
|
|
23
23
|
* file: uif:a70a7b698f5520bf49d74a91
|
|
24
24
|
*/
|
|
25
25
|
import type { UIFContract } from '../types/UIFContract.js';
|
|
26
|
-
import type { ProjectManifest
|
|
26
|
+
import type { ProjectManifest } from './manifest.js';
|
|
27
|
+
import type { MissingDependency } from './pack/collector.js';
|
|
28
|
+
import type { BundleNode } from './pack/builder.js';
|
|
27
29
|
/**
|
|
28
30
|
* Code inclusion mode for bundles
|
|
29
31
|
*/
|
|
@@ -48,20 +50,11 @@ export interface PackOptions {
|
|
|
48
50
|
/**
|
|
49
51
|
* A node in the bundle graph
|
|
50
52
|
*/
|
|
51
|
-
export
|
|
52
|
-
entryId: string;
|
|
53
|
-
contract: UIFContract;
|
|
54
|
-
codeHeader?: string | null;
|
|
55
|
-
code?: string | null;
|
|
56
|
-
}
|
|
53
|
+
export type { BundleNode } from './pack/builder.js';
|
|
57
54
|
/**
|
|
58
55
|
* Missing dependency information
|
|
59
56
|
*/
|
|
60
|
-
export
|
|
61
|
-
name: string;
|
|
62
|
-
reason: string;
|
|
63
|
-
referencedBy?: string;
|
|
64
|
-
}
|
|
57
|
+
export type { MissingDependency } from './pack/collector.js';
|
|
65
58
|
/**
|
|
66
59
|
* Complete bundle structure
|
|
67
60
|
*/
|
|
@@ -116,12 +109,12 @@ export interface LogicStampIndex {
|
|
|
116
109
|
/**
|
|
117
110
|
* Load manifest from file
|
|
118
111
|
*/
|
|
119
|
-
export
|
|
112
|
+
export { loadManifest } from './pack/loader.js';
|
|
120
113
|
/**
|
|
121
114
|
* Load a sidecar contract file
|
|
122
115
|
* Sidecar path is computed from the manifest key (project-relative): resolved from projectRoot + key + '.uif.json'
|
|
123
116
|
*/
|
|
124
|
-
export
|
|
117
|
+
export { loadContract } from './pack/loader.js';
|
|
125
118
|
/**
|
|
126
119
|
* Normalize a file path for cross-platform consistency
|
|
127
120
|
* Re-exports the canonical normalizeEntryId from utils/fsx
|
|
@@ -132,45 +125,42 @@ export { normalizeEntryId } from '../utils/fsx.js';
|
|
|
132
125
|
* Resolve input (path or name) to a manifest key
|
|
133
126
|
* This is the canonical resolution used by both pack and similar commands
|
|
134
127
|
*/
|
|
135
|
-
export
|
|
128
|
+
export { resolveKey } from './pack/resolver.js';
|
|
136
129
|
/**
|
|
137
130
|
* Find a component node by name or path
|
|
138
131
|
* Returns the component node and the manifest key it was found under
|
|
139
132
|
*/
|
|
140
|
-
export
|
|
133
|
+
export { findComponentByName } from './pack/resolver.js';
|
|
141
134
|
/**
|
|
142
135
|
* Resolve a dependency name to a manifest key
|
|
143
136
|
* Uses the canonical resolveKey() function for consistent resolution
|
|
144
137
|
* Prioritizes relative paths to avoid cross-directory conflicts
|
|
145
138
|
*/
|
|
146
|
-
export
|
|
139
|
+
export { resolveDependency } from './pack/resolver.js';
|
|
147
140
|
/**
|
|
148
141
|
* Perform BFS traversal to collect dependencies
|
|
149
142
|
*/
|
|
150
|
-
export
|
|
151
|
-
visited: Set<string>;
|
|
152
|
-
missing: MissingDependency[];
|
|
153
|
-
};
|
|
143
|
+
export { collectDependencies } from './pack/collector.js';
|
|
154
144
|
/**
|
|
155
145
|
* Extract code header (JSDoc @uif block) from source file
|
|
156
146
|
*/
|
|
157
|
-
export
|
|
147
|
+
export { extractCodeHeader } from './pack/loader.js';
|
|
158
148
|
/**
|
|
159
149
|
* Read full source code
|
|
160
150
|
*/
|
|
161
|
-
export
|
|
151
|
+
export { readSourceCode } from './pack/loader.js';
|
|
162
152
|
/**
|
|
163
153
|
* Build edges from nodes based on dependencies
|
|
164
154
|
*/
|
|
165
|
-
export
|
|
155
|
+
export { buildEdges } from './pack/builder.js';
|
|
166
156
|
/**
|
|
167
157
|
* Sort nodes deterministically for stable bundle hashes
|
|
168
158
|
*/
|
|
169
|
-
export
|
|
159
|
+
export { stableSort } from './pack/builder.js';
|
|
170
160
|
/**
|
|
171
161
|
* Compute bundle hash from nodes using stable hashing
|
|
172
162
|
*/
|
|
173
|
-
export
|
|
163
|
+
export { computeBundleHash } from './pack/builder.js';
|
|
174
164
|
/**
|
|
175
165
|
* Validate hash-lock: ensure contract hashes match current state
|
|
176
166
|
*
|
|
@@ -178,7 +168,7 @@ export declare function computeBundleHash(nodes: BundleNode[], depth: number): s
|
|
|
178
168
|
* (authoritative, not from header). fileHash() automatically strips @uif header block
|
|
179
169
|
* before hashing, so header updates won't cause hash churn.
|
|
180
170
|
*/
|
|
181
|
-
export
|
|
171
|
+
export { validateHashLock } from './pack/builder.js';
|
|
182
172
|
/**
|
|
183
173
|
* Main pack function - generates a bundle for a component
|
|
184
174
|
*/
|
package/dist/core/pack.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../src/core/pack.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;
|
|
1
|
+
{"version":3,"file":"pack.d.ts","sourceRoot":"","sources":["../../src/core/pack.ts"],"names":[],"mappings":"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"}
|
package/dist/core/pack.js
CHANGED
|
@@ -26,11 +26,14 @@
|
|
|
26
26
|
* Pack module - Generate LLM-ready context bundles for components
|
|
27
27
|
* Creates compact, hash-locked bundles with dependency graphs
|
|
28
28
|
*/
|
|
29
|
-
import {
|
|
30
|
-
import { join, resolve, isAbsolute } from 'node:path';
|
|
29
|
+
import { resolve, isAbsolute } from 'node:path';
|
|
31
30
|
import { normalizeEntryId } from '../utils/fsx.js';
|
|
32
|
-
import { bundleHash as computeBundleHashStable } from '../utils/hash.js';
|
|
33
31
|
import { createRequire } from 'node:module';
|
|
32
|
+
// Import from extracted modules
|
|
33
|
+
import { resolveKey } from './pack/resolver.js';
|
|
34
|
+
import { collectDependencies } from './pack/collector.js';
|
|
35
|
+
import { loadContract, readSourceCode, extractCodeHeader } from './pack/loader.js';
|
|
36
|
+
import { buildEdges, computeBundleHash, stableSort, validateHashLock } from './pack/builder.js';
|
|
34
37
|
// Load package.json to get version
|
|
35
38
|
const require = createRequire(import.meta.url);
|
|
36
39
|
const pkg = require('../../package.json');
|
|
@@ -38,33 +41,12 @@ const PACKAGE_VERSION = `${pkg.name}@${pkg.version}`;
|
|
|
38
41
|
/**
|
|
39
42
|
* Load manifest from file
|
|
40
43
|
*/
|
|
41
|
-
export
|
|
42
|
-
const manifestPath = join(basePath, 'logicstamp.manifest.json');
|
|
43
|
-
try {
|
|
44
|
-
const content = await readFile(manifestPath, 'utf8');
|
|
45
|
-
return JSON.parse(content);
|
|
46
|
-
}
|
|
47
|
-
catch (error) {
|
|
48
|
-
throw new Error(`Failed to load manifest at ${manifestPath}: ${error.message}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
44
|
+
export { loadManifest } from './pack/loader.js';
|
|
51
45
|
/**
|
|
52
46
|
* Load a sidecar contract file
|
|
53
47
|
* Sidecar path is computed from the manifest key (project-relative): resolved from projectRoot + key + '.uif.json'
|
|
54
48
|
*/
|
|
55
|
-
export
|
|
56
|
-
// Resolve relative path from project root
|
|
57
|
-
const absolutePath = isAbsolute(entryId) ? entryId : resolve(projectRoot, entryId);
|
|
58
|
-
const sidecarPath = `${absolutePath}.uif.json`;
|
|
59
|
-
try {
|
|
60
|
-
const content = await readFile(sidecarPath, 'utf8');
|
|
61
|
-
return JSON.parse(content);
|
|
62
|
-
}
|
|
63
|
-
catch (error) {
|
|
64
|
-
// Sidecar file doesn't exist or can't be read
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
49
|
+
export { loadContract } from './pack/loader.js';
|
|
68
50
|
/**
|
|
69
51
|
* Normalize a file path for cross-platform consistency
|
|
70
52
|
* Re-exports the canonical normalizeEntryId from utils/fsx
|
|
@@ -75,211 +57,42 @@ export { normalizeEntryId } from '../utils/fsx.js';
|
|
|
75
57
|
* Resolve input (path or name) to a manifest key
|
|
76
58
|
* This is the canonical resolution used by both pack and similar commands
|
|
77
59
|
*/
|
|
78
|
-
export
|
|
79
|
-
const normalized = normalizeEntryId(input);
|
|
80
|
-
// Try exact match first (normalized key match)
|
|
81
|
-
if (manifest.components[normalized]) {
|
|
82
|
-
return normalized;
|
|
83
|
-
}
|
|
84
|
-
// Try to find by normalized key match
|
|
85
|
-
const entries = Object.entries(manifest.components);
|
|
86
|
-
for (const [key, node] of entries) {
|
|
87
|
-
if (normalizeEntryId(key) === normalized || normalizeEntryId(node.entryId) === normalized) {
|
|
88
|
-
return key; // Return the manifest key, not the node's entryId
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
// Look for name match (Button, LoginForm, etc.)
|
|
92
|
-
// Build name → [keys] index for ambiguous cases
|
|
93
|
-
const nameMatches = [];
|
|
94
|
-
for (const [key] of entries) {
|
|
95
|
-
const fileName = key.split(/[/\\]/).pop()?.replace(/\.(tsx?|jsx?)$/, '');
|
|
96
|
-
if (fileName === input || fileName === input.replace(/\.(tsx?|jsx?)$/, '')) {
|
|
97
|
-
nameMatches.push(key);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
if (nameMatches.length === 1) {
|
|
101
|
-
return nameMatches[0];
|
|
102
|
-
}
|
|
103
|
-
else if (nameMatches.length > 1) {
|
|
104
|
-
// Ambiguous - return first match but this should be handled by caller
|
|
105
|
-
return nameMatches[0];
|
|
106
|
-
}
|
|
107
|
-
return null;
|
|
108
|
-
}
|
|
60
|
+
export { resolveKey } from './pack/resolver.js';
|
|
109
61
|
/**
|
|
110
62
|
* Find a component node by name or path
|
|
111
63
|
* Returns the component node and the manifest key it was found under
|
|
112
64
|
*/
|
|
113
|
-
export
|
|
114
|
-
const key = resolveKey(manifest, nameOrPath);
|
|
115
|
-
return key ? manifest.components[key] : null;
|
|
116
|
-
}
|
|
65
|
+
export { findComponentByName } from './pack/resolver.js';
|
|
117
66
|
/**
|
|
118
67
|
* Resolve a dependency name to a manifest key
|
|
119
68
|
* Uses the canonical resolveKey() function for consistent resolution
|
|
120
69
|
* Prioritizes relative paths to avoid cross-directory conflicts
|
|
121
70
|
*/
|
|
122
|
-
export
|
|
123
|
-
// parentId is a manifest key (canonical identifier)
|
|
124
|
-
// First, try relative path resolution based on parent directory
|
|
125
|
-
// This ensures we resolve to components in the same directory tree first
|
|
126
|
-
// parentId is a manifest key (normalized path), extract directory
|
|
127
|
-
const parentDir = parentId.substring(0, parentId.lastIndexOf('/'));
|
|
128
|
-
const possiblePaths = [
|
|
129
|
-
`${parentDir}/${depName}.tsx`,
|
|
130
|
-
`${parentDir}/${depName}.ts`,
|
|
131
|
-
`${parentDir}/${depName}/index.tsx`,
|
|
132
|
-
`${parentDir}/${depName}/index.ts`,
|
|
133
|
-
];
|
|
134
|
-
for (const path of possiblePaths) {
|
|
135
|
-
const key = resolveKey(manifest, path);
|
|
136
|
-
if (key) {
|
|
137
|
-
return key; // Return manifest key (canonical identifier)
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// Only fall back to global name search if relative paths didn't work
|
|
141
|
-
// This prevents cross-directory conflicts (e.g., tests/fixtures vs examples)
|
|
142
|
-
const key = resolveKey(manifest, depName);
|
|
143
|
-
if (key) {
|
|
144
|
-
return key; // Return manifest key (canonical identifier)
|
|
145
|
-
}
|
|
146
|
-
return null;
|
|
147
|
-
}
|
|
71
|
+
export { resolveDependency } from './pack/resolver.js';
|
|
148
72
|
/**
|
|
149
73
|
* Perform BFS traversal to collect dependencies
|
|
150
74
|
*/
|
|
151
|
-
export
|
|
152
|
-
const visited = new Set();
|
|
153
|
-
const missing = [];
|
|
154
|
-
const queue = [{ id: entryId, level: 0 }];
|
|
155
|
-
while (queue.length > 0) {
|
|
156
|
-
const current = queue.shift();
|
|
157
|
-
// Normalize the ID for lookup
|
|
158
|
-
const normalizedId = normalizeEntryId(current.id);
|
|
159
|
-
// Try to find component by normalized ID
|
|
160
|
-
let node = manifest.components[normalizedId];
|
|
161
|
-
let componentKey = normalizedId;
|
|
162
|
-
// If not found, try to find by matching normalized entryIds
|
|
163
|
-
if (!node) {
|
|
164
|
-
for (const [key, comp] of Object.entries(manifest.components)) {
|
|
165
|
-
if (normalizeEntryId(key) === normalizedId || normalizeEntryId(comp.entryId) === normalizedId) {
|
|
166
|
-
node = comp;
|
|
167
|
-
componentKey = key;
|
|
168
|
-
break;
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
// Skip if already visited or exceeded depth
|
|
173
|
-
if (visited.has(componentKey) || current.level > depth) {
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
// Check max nodes limit
|
|
177
|
-
if (visited.size >= maxNodes) {
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
180
|
-
if (!node) {
|
|
181
|
-
missing.push({
|
|
182
|
-
name: current.id,
|
|
183
|
-
reason: 'Component not found in manifest',
|
|
184
|
-
});
|
|
185
|
-
continue;
|
|
186
|
-
}
|
|
187
|
-
visited.add(componentKey);
|
|
188
|
-
// Only traverse deeper if we haven't reached depth limit
|
|
189
|
-
if (current.level < depth) {
|
|
190
|
-
// Add dependencies to queue
|
|
191
|
-
for (const dep of node.dependencies) {
|
|
192
|
-
const resolvedId = resolveDependency(manifest, dep, componentKey);
|
|
193
|
-
if (resolvedId) {
|
|
194
|
-
if (!visited.has(resolvedId)) {
|
|
195
|
-
queue.push({ id: resolvedId, level: current.level + 1 });
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
else {
|
|
199
|
-
// Track missing dependency
|
|
200
|
-
if (!missing.some((m) => m.name === dep)) {
|
|
201
|
-
missing.push({
|
|
202
|
-
name: dep,
|
|
203
|
-
reason: 'No contract found (third-party or not scanned)',
|
|
204
|
-
referencedBy: componentKey, // Use manifest key, not current.id
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return { visited, missing };
|
|
212
|
-
}
|
|
75
|
+
export { collectDependencies } from './pack/collector.js';
|
|
213
76
|
/**
|
|
214
77
|
* Extract code header (JSDoc @uif block) from source file
|
|
215
78
|
*/
|
|
216
|
-
export
|
|
217
|
-
try {
|
|
218
|
-
const absolutePath = isAbsolute(entryId) ? entryId : resolve(projectRoot, entryId);
|
|
219
|
-
const content = await readFile(absolutePath, 'utf8');
|
|
220
|
-
// Look for @uif JSDoc block
|
|
221
|
-
const headerMatch = content.match(/\/\*\*[\s\S]*?@uif[\s\S]*?\*\//);
|
|
222
|
-
if (headerMatch) {
|
|
223
|
-
return headerMatch[0];
|
|
224
|
-
}
|
|
225
|
-
return null;
|
|
226
|
-
}
|
|
227
|
-
catch (error) {
|
|
228
|
-
return null;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
79
|
+
export { extractCodeHeader } from './pack/loader.js';
|
|
231
80
|
/**
|
|
232
81
|
* Read full source code
|
|
233
82
|
*/
|
|
234
|
-
export
|
|
235
|
-
try {
|
|
236
|
-
const absolutePath = isAbsolute(entryId) ? entryId : resolve(projectRoot, entryId);
|
|
237
|
-
return await readFile(absolutePath, 'utf8');
|
|
238
|
-
}
|
|
239
|
-
catch (error) {
|
|
240
|
-
return null;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
83
|
+
export { readSourceCode } from './pack/loader.js';
|
|
243
84
|
/**
|
|
244
85
|
* Build edges from nodes based on dependencies
|
|
245
86
|
*/
|
|
246
|
-
export
|
|
247
|
-
const edges = [];
|
|
248
|
-
const nodeIds = new Set(nodes.map((n) => n.entryId));
|
|
249
|
-
for (const node of nodes) {
|
|
250
|
-
const componentNode = manifest.components[node.entryId];
|
|
251
|
-
if (!componentNode)
|
|
252
|
-
continue;
|
|
253
|
-
for (const dep of componentNode.dependencies) {
|
|
254
|
-
const resolvedId = resolveDependency(manifest, dep, node.entryId);
|
|
255
|
-
// Only add edge if both nodes are in the bundle
|
|
256
|
-
if (resolvedId && nodeIds.has(resolvedId)) {
|
|
257
|
-
edges.push([node.entryId, resolvedId]);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return edges;
|
|
262
|
-
}
|
|
87
|
+
export { buildEdges } from './pack/builder.js';
|
|
263
88
|
/**
|
|
264
89
|
* Sort nodes deterministically for stable bundle hashes
|
|
265
90
|
*/
|
|
266
|
-
export
|
|
267
|
-
return [...nodes].sort((a, b) => {
|
|
268
|
-
// Sort by entryId for determinism
|
|
269
|
-
return a.entryId.localeCompare(b.entryId);
|
|
270
|
-
});
|
|
271
|
-
}
|
|
91
|
+
export { stableSort } from './pack/builder.js';
|
|
272
92
|
/**
|
|
273
93
|
* Compute bundle hash from nodes using stable hashing
|
|
274
94
|
*/
|
|
275
|
-
export
|
|
276
|
-
// Use the stable bundleHash function from utils/hash
|
|
277
|
-
const nodeData = nodes.map(n => ({
|
|
278
|
-
entryId: n.entryId,
|
|
279
|
-
semanticHash: n.contract.semanticHash,
|
|
280
|
-
}));
|
|
281
|
-
return computeBundleHashStable(nodeData, depth, '0.1');
|
|
282
|
-
}
|
|
95
|
+
export { computeBundleHash } from './pack/builder.js';
|
|
283
96
|
/**
|
|
284
97
|
* Validate hash-lock: ensure contract hashes match current state
|
|
285
98
|
*
|
|
@@ -287,27 +100,7 @@ export function computeBundleHash(nodes, depth) {
|
|
|
287
100
|
* (authoritative, not from header). fileHash() automatically strips @uif header block
|
|
288
101
|
* before hashing, so header updates won't cause hash churn.
|
|
289
102
|
*/
|
|
290
|
-
export
|
|
291
|
-
try {
|
|
292
|
-
// Read the actual source file
|
|
293
|
-
const absolutePath = isAbsolute(entryId) ? entryId : resolve(projectRoot, entryId);
|
|
294
|
-
const sourceContent = await readFile(absolutePath, 'utf8');
|
|
295
|
-
// Recompute file hash (strips @uif header block automatically)
|
|
296
|
-
const { fileHash: computedFileHash } = await import('../utils/hash.js');
|
|
297
|
-
const actualFileHash = computedFileHash(sourceContent);
|
|
298
|
-
// Compare to sidecar contract.fileHash (authoritative, not header)
|
|
299
|
-
if (actualFileHash !== contract.fileHash) {
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
// Semantic hash should match (derived from structure + signature)
|
|
303
|
-
// If fileHash matches, semantic hash should also match since it's derived from the AST
|
|
304
|
-
return true;
|
|
305
|
-
}
|
|
306
|
-
catch (error) {
|
|
307
|
-
// If we can't read/parse the file, fail validation
|
|
308
|
-
return false;
|
|
309
|
-
}
|
|
310
|
-
}
|
|
103
|
+
export { validateHashLock } from './pack/builder.js';
|
|
311
104
|
/**
|
|
312
105
|
* Main pack function - generates a bundle for a component
|
|
313
106
|
*/
|