capdag 0.145.321 → 0.148.329
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/build-browser.js +0 -5
- package/cap-graph-renderer.js +6 -6
- package/capdag.js +61 -14
- package/capdag.test.js +46 -26
- package/package.json +1 -1
package/build-browser.js
CHANGED
|
@@ -144,11 +144,6 @@ window.resolveMediaUrn = resolveMediaUrn;
|
|
|
144
144
|
window.buildExtensionIndex = buildExtensionIndex;
|
|
145
145
|
window.mediaUrnsForExtension = mediaUrnsForExtension;
|
|
146
146
|
window.getExtensionMappings = getExtensionMappings;
|
|
147
|
-
window.CapMatrixError = CapMatrixError;
|
|
148
|
-
window.CapMatrix = CapMatrix;
|
|
149
|
-
window.BestCapSetMatch = BestCapSetMatch;
|
|
150
|
-
window.CompositeCapSet = CompositeCapSet;
|
|
151
|
-
window.CapBlock = CapBlock;
|
|
152
147
|
window.CapGraphEdge = CapGraphEdge;
|
|
153
148
|
window.CapGraphStats = CapGraphStats;
|
|
154
149
|
window.CapGraph = CapGraph;
|
package/cap-graph-renderer.js
CHANGED
|
@@ -158,10 +158,10 @@ function layoutForMode(mode) {
|
|
|
158
158
|
algorithm: 'layered',
|
|
159
159
|
'elk.direction': 'RIGHT',
|
|
160
160
|
'elk.edgeRouting': 'POLYLINE',
|
|
161
|
-
'elk.layered.spacing.edgeEdgeBetweenLayers':
|
|
162
|
-
'elk.layered.spacing.edgeNodeBetweenLayers':
|
|
163
|
-
'elk.spacing.edgeEdge':
|
|
164
|
-
'elk.spacing.edgeNode':
|
|
161
|
+
'elk.layered.spacing.edgeEdgeBetweenLayers': 30,
|
|
162
|
+
'elk.layered.spacing.edgeNodeBetweenLayers': 40,
|
|
163
|
+
'elk.spacing.edgeEdge': 25,
|
|
164
|
+
'elk.spacing.edgeNode': 35,
|
|
165
165
|
'elk.layered.crossingMinimization.strategy': 'LAYER_SWEEP',
|
|
166
166
|
'elk.layered.nodePlacement.strategy': 'NETWORK_SIMPLEX',
|
|
167
167
|
'elk.layered.considerModelOrder.strategy': 'NODES_AND_EDGES',
|
|
@@ -169,8 +169,8 @@ function layoutForMode(mode) {
|
|
|
169
169
|
};
|
|
170
170
|
if (mode === 'browse') {
|
|
171
171
|
return Object.assign({}, base, {
|
|
172
|
-
'elk.layered.spacing.nodeNodeBetweenLayers':
|
|
173
|
-
'elk.spacing.nodeNode':
|
|
172
|
+
'elk.layered.spacing.nodeNodeBetweenLayers': 180,
|
|
173
|
+
'elk.spacing.nodeNode': 90,
|
|
174
174
|
});
|
|
175
175
|
}
|
|
176
176
|
if (mode === 'strand') {
|
package/capdag.js
CHANGED
|
@@ -3596,6 +3596,23 @@ class CartridgeCapSummary {
|
|
|
3596
3596
|
}
|
|
3597
3597
|
}
|
|
3598
3598
|
|
|
3599
|
+
/**
|
|
3600
|
+
* Cartridge cap group from registry
|
|
3601
|
+
*/
|
|
3602
|
+
class CartridgeCapGroup {
|
|
3603
|
+
constructor(data) {
|
|
3604
|
+
if (!data.name) throw new Error('CapGroup missing name');
|
|
3605
|
+
this.name = data.name;
|
|
3606
|
+
this.caps = (data.caps || []).map(c => new CartridgeCapSummary(c.urn, c.title, c.description || ''));
|
|
3607
|
+
this.adapter_urns = data.adapter_urns || [];
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
/** Flat caps in this group */
|
|
3611
|
+
allCaps() {
|
|
3612
|
+
return this.caps;
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
|
|
3599
3616
|
/**
|
|
3600
3617
|
* Cartridge information from registry
|
|
3601
3618
|
*/
|
|
@@ -3610,7 +3627,8 @@ class CartridgeInfo {
|
|
|
3610
3627
|
this.teamId = data.teamId || '';
|
|
3611
3628
|
this.signedAt = data.signedAt || '';
|
|
3612
3629
|
this.minAppVersion = data.minAppVersion || '';
|
|
3613
|
-
|
|
3630
|
+
if (!Array.isArray(data.cap_groups)) throw new Error(`CartridgeInfo ${data.id || '?'}: missing cap_groups array`);
|
|
3631
|
+
this.cap_groups = data.cap_groups.map(g => new CartridgeCapGroup(g));
|
|
3614
3632
|
this.categories = data.categories || [];
|
|
3615
3633
|
this.tags = data.tags || [];
|
|
3616
3634
|
// Versions with platform-specific builds
|
|
@@ -3618,6 +3636,21 @@ class CartridgeInfo {
|
|
|
3618
3636
|
this.availableVersions = data.availableVersions || [];
|
|
3619
3637
|
}
|
|
3620
3638
|
|
|
3639
|
+
/** All caps flattened across all cap_groups, deduplicated by URN */
|
|
3640
|
+
allCaps() {
|
|
3641
|
+
const seen = new Set();
|
|
3642
|
+
const result = [];
|
|
3643
|
+
for (const group of this.cap_groups) {
|
|
3644
|
+
for (const cap of group.caps) {
|
|
3645
|
+
if (!seen.has(cap.urn)) {
|
|
3646
|
+
seen.add(cap.urn);
|
|
3647
|
+
result.push(cap);
|
|
3648
|
+
}
|
|
3649
|
+
}
|
|
3650
|
+
}
|
|
3651
|
+
return result;
|
|
3652
|
+
}
|
|
3653
|
+
|
|
3621
3654
|
/**
|
|
3622
3655
|
* Check if cartridge is signed (has team_id and signed_at)
|
|
3623
3656
|
*/
|
|
@@ -3697,11 +3730,16 @@ class CartridgeRepoClient {
|
|
|
3697
3730
|
|
|
3698
3731
|
const data = await response.json();
|
|
3699
3732
|
|
|
3700
|
-
if (!data.cartridges ||
|
|
3701
|
-
throw new Error(`Invalid cartridge registry response from ${repoUrl}: missing cartridges
|
|
3733
|
+
if (!data.cartridges || typeof data.cartridges !== 'object') {
|
|
3734
|
+
throw new Error(`Invalid cartridge registry response from ${repoUrl}: missing cartridges object`);
|
|
3702
3735
|
}
|
|
3703
3736
|
|
|
3704
|
-
|
|
3737
|
+
// Registry stores cartridges as an object keyed by id; normalize to array.
|
|
3738
|
+
return Object.entries(data.cartridges).map(([id, c]) => new CartridgeInfo({
|
|
3739
|
+
...c,
|
|
3740
|
+
id,
|
|
3741
|
+
version: c.latestVersion
|
|
3742
|
+
}));
|
|
3705
3743
|
}
|
|
3706
3744
|
|
|
3707
3745
|
/**
|
|
@@ -3713,7 +3751,7 @@ class CartridgeRepoClient {
|
|
|
3713
3751
|
for (const cartridge of cartridges) {
|
|
3714
3752
|
cache.cartridges.set(cartridge.id, cartridge);
|
|
3715
3753
|
|
|
3716
|
-
for (const cap of cartridge.
|
|
3754
|
+
for (const cap of cartridge.allCaps()) {
|
|
3717
3755
|
if (!cache.capToCartridges.has(cap.urn)) {
|
|
3718
3756
|
cache.capToCartridges.set(cap.urn, []);
|
|
3719
3757
|
}
|
|
@@ -3773,7 +3811,7 @@ class CartridgeRepoClient {
|
|
|
3773
3811
|
const cartridge = cache.cartridges.get(cartridgeId);
|
|
3774
3812
|
if (!cartridge) continue;
|
|
3775
3813
|
|
|
3776
|
-
const capInfo = cartridge.
|
|
3814
|
+
const capInfo = cartridge.allCaps().find(c => c.urn === capUrn);
|
|
3777
3815
|
if (!capInfo) continue;
|
|
3778
3816
|
|
|
3779
3817
|
const pageUrl = cartridge.pageUrl || cache.repoUrl;
|
|
@@ -3889,6 +3927,9 @@ class CartridgeRepoServer {
|
|
|
3889
3927
|
if (!build.package || !build.package.name) {
|
|
3890
3928
|
throw new Error(`Cartridge ${id} v${version}: build[${i}] (${build.platform}) missing package.name`);
|
|
3891
3929
|
}
|
|
3930
|
+
if (!build.package.url) {
|
|
3931
|
+
throw new Error(`Cartridge ${id} v${version}: build[${i}] (${build.platform}) missing package.url`);
|
|
3932
|
+
}
|
|
3892
3933
|
}
|
|
3893
3934
|
}
|
|
3894
3935
|
|
|
@@ -3942,7 +3983,10 @@ class CartridgeRepoServer {
|
|
|
3942
3983
|
teamId: cartridge.teamId,
|
|
3943
3984
|
signedAt: versionData.releaseDate,
|
|
3944
3985
|
minAppVersion: versionData.minAppVersion || cartridge.minAppVersion,
|
|
3945
|
-
|
|
3986
|
+
cap_groups: (() => {
|
|
3987
|
+
if (!Array.isArray(cartridge.cap_groups)) throw new Error(`Cartridge ${id}: missing cap_groups array`);
|
|
3988
|
+
return cartridge.cap_groups;
|
|
3989
|
+
})(),
|
|
3946
3990
|
categories: cartridge.categories,
|
|
3947
3991
|
tags: cartridge.tags,
|
|
3948
3992
|
versions: cartridge.versions,
|
|
@@ -3977,12 +4021,13 @@ class CartridgeRepoServer {
|
|
|
3977
4021
|
const cartridges = this.transformToCartridgeArray();
|
|
3978
4022
|
const lowerQuery = query.toLowerCase();
|
|
3979
4023
|
|
|
3980
|
-
return cartridges.filter(p =>
|
|
3981
|
-
p.
|
|
3982
|
-
p.
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
4024
|
+
return cartridges.filter(p => {
|
|
4025
|
+
const allCaps = (p.cap_groups || []).flatMap(g => g.caps || []);
|
|
4026
|
+
return p.name.toLowerCase().includes(lowerQuery) ||
|
|
4027
|
+
p.description.toLowerCase().includes(lowerQuery) ||
|
|
4028
|
+
p.tags.some(t => t.toLowerCase().includes(lowerQuery)) ||
|
|
4029
|
+
allCaps.some(c => c.urn.toLowerCase().includes(lowerQuery) || c.title.toLowerCase().includes(lowerQuery));
|
|
4030
|
+
});
|
|
3986
4031
|
}
|
|
3987
4032
|
|
|
3988
4033
|
/**
|
|
@@ -3998,7 +4043,9 @@ class CartridgeRepoServer {
|
|
|
3998
4043
|
*/
|
|
3999
4044
|
getCartridgesByCap(capUrn) {
|
|
4000
4045
|
const cartridges = this.transformToCartridgeArray();
|
|
4001
|
-
return cartridges.filter(p =>
|
|
4046
|
+
return cartridges.filter(p =>
|
|
4047
|
+
(p.cap_groups || []).some(g => (g.caps || []).some(c => c.urn === capUrn))
|
|
4048
|
+
);
|
|
4002
4049
|
}
|
|
4003
4050
|
}
|
|
4004
4051
|
|
package/capdag.test.js
CHANGED
|
@@ -1651,16 +1651,22 @@ const sampleRegistry = {
|
|
|
1651
1651
|
minAppVersion: '1.0.0',
|
|
1652
1652
|
categories: ['document'],
|
|
1653
1653
|
tags: ['pdf', 'extractor'],
|
|
1654
|
-
|
|
1654
|
+
cap_groups: [
|
|
1655
1655
|
{
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1656
|
+
name: 'pdf-processing',
|
|
1657
|
+
adapter_urns: ['media:pdf'],
|
|
1658
|
+
caps: [
|
|
1659
|
+
{
|
|
1660
|
+
urn: 'cap:in="media:pdf";op=disbind;out="media:disbound-page;textable;list"',
|
|
1661
|
+
title: 'Disbind PDF',
|
|
1662
|
+
description: 'Extract pages'
|
|
1663
|
+
},
|
|
1664
|
+
{
|
|
1665
|
+
urn: 'cap:in="media:pdf";op=extract_metadata;out="media:file-metadata;textable;record"',
|
|
1666
|
+
title: 'Extract Metadata',
|
|
1667
|
+
description: 'Get PDF metadata'
|
|
1668
|
+
}
|
|
1669
|
+
]
|
|
1664
1670
|
}
|
|
1665
1671
|
],
|
|
1666
1672
|
latestVersion: '0.81.5325',
|
|
@@ -1673,6 +1679,7 @@ const sampleRegistry = {
|
|
|
1673
1679
|
platform: 'darwin-arm64',
|
|
1674
1680
|
package: {
|
|
1675
1681
|
name: 'pdfcartridge-0.81.5325.pkg',
|
|
1682
|
+
url: 'https://cartridges.machinefabric.com/pdfcartridge/0.81.5325/pdfcartridge-0.81.5325.pkg',
|
|
1676
1683
|
sha256: '9b68724eb9220ecf01e8ed4f5f80c594fbac2239bc5bf675005ec882ecc5eba0',
|
|
1677
1684
|
size: 5187485
|
|
1678
1685
|
}
|
|
@@ -1689,11 +1696,17 @@ const sampleRegistry = {
|
|
|
1689
1696
|
minAppVersion: '1.0.0',
|
|
1690
1697
|
categories: ['text'],
|
|
1691
1698
|
tags: ['txt', 'text'],
|
|
1692
|
-
|
|
1699
|
+
cap_groups: [
|
|
1693
1700
|
{
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1701
|
+
name: 'text-processing',
|
|
1702
|
+
adapter_urns: ['media:txt;textable'],
|
|
1703
|
+
caps: [
|
|
1704
|
+
{
|
|
1705
|
+
urn: 'cap:in="media:txt;textable";op=disbind;out="media:disbound-page;textable;list"',
|
|
1706
|
+
title: 'Disbind Text',
|
|
1707
|
+
description: 'Extract text pages'
|
|
1708
|
+
}
|
|
1709
|
+
]
|
|
1697
1710
|
}
|
|
1698
1711
|
],
|
|
1699
1712
|
latestVersion: '0.54.6408',
|
|
@@ -1706,6 +1719,7 @@ const sampleRegistry = {
|
|
|
1706
1719
|
platform: 'darwin-arm64',
|
|
1707
1720
|
package: {
|
|
1708
1721
|
name: 'txtcartridge-0.54.6408.pkg',
|
|
1722
|
+
url: 'https://cartridges.machinefabric.com/txtcartridge/0.54.6408/txtcartridge-0.54.6408.pkg',
|
|
1709
1723
|
sha256: 'abc123',
|
|
1710
1724
|
size: 821000
|
|
1711
1725
|
}
|
|
@@ -1725,13 +1739,17 @@ function test320_cartridgeInfoConstruction() {
|
|
|
1725
1739
|
description: 'A test',
|
|
1726
1740
|
teamId: 'TEAM123',
|
|
1727
1741
|
signedAt: '2026-01-01',
|
|
1728
|
-
|
|
1742
|
+
cap_groups: [{
|
|
1743
|
+
name: 'test-group',
|
|
1744
|
+
adapter_urns: ['media:void'],
|
|
1745
|
+
caps: [{urn: 'cap:in="media:void";op=test;out="media:void"', title: 'Test', description: ''}]
|
|
1746
|
+
}],
|
|
1729
1747
|
versions: {
|
|
1730
1748
|
'1.0.0': {
|
|
1731
1749
|
releaseDate: '2026-01-01',
|
|
1732
1750
|
changelog: ['Initial'],
|
|
1733
1751
|
minAppVersion: '1.0.0',
|
|
1734
|
-
builds: [{platform: 'darwin-arm64', package: {name: 'test-1.0.0.pkg', sha256: 'abc123', size: 100}}]
|
|
1752
|
+
builds: [{platform: 'darwin-arm64', package: {name: 'test-1.0.0.pkg', url: 'https://cartridges.machinefabric.com/testcartridge/1.0.0/test-1.0.0.pkg', sha256: 'abc123', size: 100}}]
|
|
1735
1753
|
}
|
|
1736
1754
|
},
|
|
1737
1755
|
availableVersions: ['1.0.0']
|
|
@@ -1739,31 +1757,32 @@ function test320_cartridgeInfoConstruction() {
|
|
|
1739
1757
|
const cartridge = new CartridgeInfo(data);
|
|
1740
1758
|
assert(cartridge.id === 'testcartridge', 'ID should match');
|
|
1741
1759
|
assert(cartridge.teamId === 'TEAM123', 'Team ID should match');
|
|
1742
|
-
assert(cartridge.
|
|
1743
|
-
assert(cartridge.caps[0].urn === 'cap:in="media:void";op=test;out="media:void"', 'Cap URN should match');
|
|
1760
|
+
assert(cartridge.cap_groups.length === 1, 'Should have 1 cap_group');
|
|
1761
|
+
assert(cartridge.cap_groups[0].caps[0].urn === 'cap:in="media:void";op=test;out="media:void"', 'Cap URN should match');
|
|
1762
|
+
assert(cartridge.allCaps().length === 1, 'allCaps() should return 1 cap');
|
|
1744
1763
|
}
|
|
1745
1764
|
|
|
1746
1765
|
// TEST321: CartridgeInfo.is_signed() returns true when signature is present
|
|
1747
1766
|
function test321_cartridgeInfoIsSigned() {
|
|
1748
|
-
const signed = new CartridgeInfo({id: 'test', teamId: 'TEAM', signedAt: '2026-01-01',
|
|
1767
|
+
const signed = new CartridgeInfo({id: 'test', teamId: 'TEAM', signedAt: '2026-01-01', cap_groups: []});
|
|
1749
1768
|
assert(signed.isSigned() === true, 'Cartridge with teamId and signedAt should be signed');
|
|
1750
1769
|
|
|
1751
|
-
const unsigned1 = new CartridgeInfo({id: 'test', teamId: '', signedAt: '2026-01-01',
|
|
1770
|
+
const unsigned1 = new CartridgeInfo({id: 'test', teamId: '', signedAt: '2026-01-01', cap_groups: []});
|
|
1752
1771
|
assert(unsigned1.isSigned() === false, 'Cartridge without teamId should not be signed');
|
|
1753
1772
|
|
|
1754
|
-
const unsigned2 = new CartridgeInfo({id: 'test', teamId: 'TEAM', signedAt: '',
|
|
1773
|
+
const unsigned2 = new CartridgeInfo({id: 'test', teamId: 'TEAM', signedAt: '', cap_groups: []});
|
|
1755
1774
|
assert(unsigned2.isSigned() === false, 'Cartridge without signedAt should not be signed');
|
|
1756
1775
|
}
|
|
1757
1776
|
|
|
1758
1777
|
// TEST322: CartridgeInfo.build_for_platform() returns the build matching the current platform
|
|
1759
1778
|
function test322_cartridgeInfoBuildForPlatform() {
|
|
1760
1779
|
const withBuilds = new CartridgeInfo({
|
|
1761
|
-
id: 'test', version: '1.0.0',
|
|
1780
|
+
id: 'test', version: '1.0.0', cap_groups: [],
|
|
1762
1781
|
versions: {
|
|
1763
1782
|
'1.0.0': {
|
|
1764
1783
|
builds: [
|
|
1765
|
-
{platform: 'darwin-arm64', package: {name: 'test-darwin.pkg', sha256: 'abc', size: 100}},
|
|
1766
|
-
{platform: 'linux-x86_64', package: {name: 'test-linux.pkg', sha256: 'def', size: 200}}
|
|
1784
|
+
{platform: 'darwin-arm64', package: {name: 'test-darwin.pkg', url: 'https://cartridges.machinefabric.com/test/1.0.0/test-darwin.pkg', sha256: 'abc', size: 100}},
|
|
1785
|
+
{platform: 'linux-x86_64', package: {name: 'test-linux.pkg', url: 'https://cartridges.machinefabric.com/test/1.0.0/test-linux.pkg', sha256: 'def', size: 200}}
|
|
1767
1786
|
]
|
|
1768
1787
|
}
|
|
1769
1788
|
},
|
|
@@ -1784,7 +1803,7 @@ function test322_cartridgeInfoBuildForPlatform() {
|
|
|
1784
1803
|
assert(platforms.includes('darwin-arm64'), 'Should include darwin-arm64');
|
|
1785
1804
|
assert(platforms.includes('linux-x86_64'), 'Should include linux-x86_64');
|
|
1786
1805
|
|
|
1787
|
-
const noBuilds = new CartridgeInfo({id: 'test', version: '1.0.0',
|
|
1806
|
+
const noBuilds = new CartridgeInfo({id: 'test', version: '1.0.0', cap_groups: [], versions: {}, availableVersions: []});
|
|
1788
1807
|
assert(noBuilds.buildForPlatform('darwin-arm64') === null, 'Should return null when no versions');
|
|
1789
1808
|
assert(noBuilds.availablePlatforms().length === 0, 'Should have no platforms');
|
|
1790
1809
|
}
|
|
@@ -1837,8 +1856,9 @@ function test324_cartridgeRepoServerTransformToArray() {
|
|
|
1837
1856
|
assert(pdf.versions['0.81.5325'].builds[0].package.sha256 === '9b68724eb9220ecf01e8ed4f5f80c594fbac2239bc5bf675005ec882ecc5eba0', 'Should have package SHA256');
|
|
1838
1857
|
assert(Array.isArray(pdf.availableVersions), 'Should have availableVersions array');
|
|
1839
1858
|
assert(pdf.availableVersions.includes('0.81.5325'), 'Should include latest version');
|
|
1840
|
-
assert(Array.isArray(pdf.
|
|
1841
|
-
assert(pdf.
|
|
1859
|
+
assert(Array.isArray(pdf.cap_groups), 'Should have cap_groups array');
|
|
1860
|
+
assert(pdf.cap_groups.length === 1, 'Should have 1 cap_group');
|
|
1861
|
+
assert(pdf.cap_groups[0].caps.length === 2, 'Should have 2 caps in the group');
|
|
1842
1862
|
}
|
|
1843
1863
|
|
|
1844
1864
|
// TEST325: CartridgeRepoServer.get_cartridges() returns all parsed cartridges
|
package/package.json
CHANGED