capdag 0.124.274 → 0.126.278

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/capdag.js +34 -38
  2. package/capdag.test.js +70 -31
  3. package/package.json +1 -1
package/capdag.js CHANGED
@@ -3903,12 +3903,8 @@ class CartridgeInfo {
3903
3903
  this.caps = (data.caps || []).map(c => new CartridgeCapSummary(c.urn, c.title, c.description || ''));
3904
3904
  this.categories = data.categories || [];
3905
3905
  this.tags = data.tags || [];
3906
- this.changelog = data.changelog || {};
3907
- // Distribution fields
3908
- this.platform = data.platform || '';
3909
- this.packageName = data.packageName || '';
3910
- this.packageSha256 = data.packageSha256 || '';
3911
- this.packageSize = data.packageSize || 0;
3906
+ // Versions with platform-specific builds
3907
+ this.versions = data.versions || {};
3912
3908
  this.availableVersions = data.availableVersions || [];
3913
3909
  }
3914
3910
 
@@ -3920,10 +3916,25 @@ class CartridgeInfo {
3920
3916
  }
3921
3917
 
3922
3918
  /**
3923
- * Check if package download info is available
3919
+ * Get the build for a specific platform from the latest version
3924
3920
  */
3925
- hasPackage() {
3926
- return this.packageName.length > 0 && this.packageSha256.length > 0;
3921
+ buildForPlatform(platform) {
3922
+ const latestVersionData = this.versions[this.version];
3923
+ if (!latestVersionData) return null;
3924
+ return (latestVersionData.builds || []).find(b => b.platform === platform) || null;
3925
+ }
3926
+
3927
+ /**
3928
+ * Get all platforms available across all versions
3929
+ */
3930
+ availablePlatforms() {
3931
+ const platforms = new Set();
3932
+ for (const versionData of Object.values(this.versions)) {
3933
+ for (const build of (versionData.builds || [])) {
3934
+ platforms.add(build.platform);
3935
+ }
3936
+ }
3937
+ return Array.from(platforms).sort();
3927
3938
  }
3928
3939
  }
3929
3940
 
@@ -4145,8 +4156,8 @@ class CartridgeRepoServer {
4145
4156
  if (!this.registry) {
4146
4157
  throw new Error('Registry is required');
4147
4158
  }
4148
- if (this.registry.schemaVersion !== '3.0') {
4149
- throw new Error(`Unsupported registry schema version: ${this.registry.schemaVersion}. Required: 3.0`);
4159
+ if (this.registry.schemaVersion !== '4.0') {
4160
+ throw new Error(`Unsupported registry schema version: ${this.registry.schemaVersion}. Required: 4.0`);
4150
4161
  }
4151
4162
  if (!this.registry.cartridges || typeof this.registry.cartridges !== 'object') {
4152
4163
  throw new Error('Registry must have cartridges object');
@@ -4157,11 +4168,17 @@ class CartridgeRepoServer {
4157
4168
  * Validate version data has all required fields
4158
4169
  */
4159
4170
  validateVersionData(id, version, versionData) {
4160
- if (!versionData.platform) {
4161
- throw new Error(`Cartridge ${id} v${version}: missing required field 'platform'`);
4171
+ if (!Array.isArray(versionData.builds) || versionData.builds.length === 0) {
4172
+ throw new Error(`Cartridge ${id} v${version}: no builds`);
4162
4173
  }
4163
- if (!versionData.package || !versionData.package.name) {
4164
- throw new Error(`Cartridge ${id} v${version}: missing required field 'package'`);
4174
+ for (let i = 0; i < versionData.builds.length; i++) {
4175
+ const build = versionData.builds[i];
4176
+ if (!build.platform) {
4177
+ throw new Error(`Cartridge ${id} v${version}: build[${i}] missing platform`);
4178
+ }
4179
+ if (!build.package || !build.package.name) {
4180
+ throw new Error(`Cartridge ${id} v${version}: build[${i}] (${build.platform}) missing package.name`);
4181
+ }
4165
4182
  }
4166
4183
  }
4167
4184
 
@@ -4182,19 +4199,6 @@ class CartridgeRepoServer {
4182
4199
  return 0;
4183
4200
  }
4184
4201
 
4185
- /**
4186
- * Build changelog map from versions
4187
- */
4188
- buildChangelogMap(versions) {
4189
- const changelog = {};
4190
- for (const [version, versionData] of Object.entries(versions)) {
4191
- if (versionData.changelog && Array.isArray(versionData.changelog)) {
4192
- changelog[version] = versionData.changelog;
4193
- }
4194
- }
4195
- return changelog;
4196
- }
4197
-
4198
4202
  /**
4199
4203
  * Transform registry to flat cartridge array
4200
4204
  */
@@ -4218,28 +4222,20 @@ class CartridgeRepoServer {
4218
4222
  return this.compareVersions(b, a);
4219
4223
  });
4220
4224
 
4221
- // Build flat cartridge object with latest version data
4222
- const packageUrl = `https://machinefabric.com/cartridges/packages/${versionData.package.name}`;
4223
4225
  cartridges.push({
4224
4226
  id,
4225
4227
  name: cartridge.name,
4226
4228
  version: latestVersion,
4227
4229
  description: cartridge.description,
4228
4230
  author: cartridge.author,
4229
- pageUrl: cartridge.pageUrl || packageUrl,
4231
+ pageUrl: cartridge.pageUrl || '',
4230
4232
  teamId: cartridge.teamId,
4231
4233
  signedAt: versionData.releaseDate,
4232
4234
  minAppVersion: versionData.minAppVersion || cartridge.minAppVersion,
4233
4235
  caps: cartridge.caps || [],
4234
4236
  categories: cartridge.categories,
4235
4237
  tags: cartridge.tags,
4236
- changelog: this.buildChangelogMap(cartridge.versions),
4237
- // Distribution fields
4238
- platform: versionData.platform,
4239
- packageName: versionData.package.name,
4240
- packageSha256: versionData.package.sha256,
4241
- packageSize: versionData.package.size,
4242
- // All available versions
4238
+ versions: cartridge.versions,
4243
4239
  availableVersions
4244
4240
  });
4245
4241
  }
package/capdag.test.js CHANGED
@@ -2013,7 +2013,7 @@ function testJS_mediaSpecConstruction() {
2013
2013
 
2014
2014
  // Sample registry for testing
2015
2015
  const sampleRegistry = {
2016
- schemaVersion: '3.0',
2016
+ schemaVersion: '4.0',
2017
2017
  lastUpdated: '2026-02-07T16:48:28Z',
2018
2018
  cartridges: {
2019
2019
  pdfcartridge: {
@@ -2043,12 +2043,14 @@ const sampleRegistry = {
2043
2043
  releaseDate: '2026-02-07T16:40:28Z',
2044
2044
  changelog: ['Initial release'],
2045
2045
  minAppVersion: '1.0.0',
2046
- platform: 'darwin-arm64',
2047
- package: {
2048
- name: 'pdfcartridge-0.81.5325.pkg',
2049
- sha256: '9b68724eb9220ecf01e8ed4f5f80c594fbac2239bc5bf675005ec882ecc5eba0',
2050
- size: 5187485
2051
- }
2046
+ builds: [{
2047
+ platform: 'darwin-arm64',
2048
+ package: {
2049
+ name: 'pdfcartridge-0.81.5325.pkg',
2050
+ sha256: '9b68724eb9220ecf01e8ed4f5f80c594fbac2239bc5bf675005ec882ecc5eba0',
2051
+ size: 5187485
2052
+ }
2053
+ }]
2052
2054
  }
2053
2055
  }
2054
2056
  },
@@ -2074,12 +2076,14 @@ const sampleRegistry = {
2074
2076
  releaseDate: '2026-02-07T17:44:00Z',
2075
2077
  changelog: ['First version'],
2076
2078
  minAppVersion: '1.0.0',
2077
- platform: 'darwin-arm64',
2078
- package: {
2079
- name: 'txtcartridge-0.54.6408.pkg',
2080
- sha256: 'abc123',
2081
- size: 821000
2082
- }
2079
+ builds: [{
2080
+ platform: 'darwin-arm64',
2081
+ package: {
2082
+ name: 'txtcartridge-0.54.6408.pkg',
2083
+ sha256: 'abc123',
2084
+ size: 821000
2085
+ }
2086
+ }]
2083
2087
  }
2084
2088
  }
2085
2089
  }
@@ -2095,9 +2099,16 @@ function test320_cartridgeInfoConstruction() {
2095
2099
  description: 'A test',
2096
2100
  teamId: 'TEAM123',
2097
2101
  signedAt: '2026-01-01',
2098
- packageName: 'test-1.0.0.pkg',
2099
- packageSha256: 'abc123',
2100
- caps: [{urn: 'cap:in="media:void";op=test;out="media:void"', title: 'Test', description: ''}]
2102
+ caps: [{urn: 'cap:in="media:void";op=test;out="media:void"', title: 'Test', description: ''}],
2103
+ versions: {
2104
+ '1.0.0': {
2105
+ releaseDate: '2026-01-01',
2106
+ changelog: ['Initial'],
2107
+ minAppVersion: '1.0.0',
2108
+ builds: [{platform: 'darwin-arm64', package: {name: 'test-1.0.0.pkg', sha256: 'abc123', size: 100}}]
2109
+ }
2110
+ },
2111
+ availableVersions: ['1.0.0']
2101
2112
  };
2102
2113
  const cartridge = new CartridgeInfo(data);
2103
2114
  assert(cartridge.id === 'testcartridge', 'ID should match');
@@ -2118,28 +2129,50 @@ function test321_cartridgeInfoIsSigned() {
2118
2129
  assert(unsigned2.isSigned() === false, 'Cartridge without signedAt should not be signed');
2119
2130
  }
2120
2131
 
2121
- // TEST322: Cartridge info has package check
2122
- function test322_cartridgeInfoHasPackage() {
2123
- const withPkg = new CartridgeInfo({id: 'test', packageName: 'test.pkg', packageSha256: 'abc', caps: []});
2124
- assert(withPkg.hasPackage() === true, 'Cartridge with package info should return true');
2132
+ // TEST322: Cartridge info build for platform and available platforms
2133
+ function test322_cartridgeInfoBuildForPlatform() {
2134
+ const withBuilds = new CartridgeInfo({
2135
+ id: 'test', version: '1.0.0', caps: [],
2136
+ versions: {
2137
+ '1.0.0': {
2138
+ builds: [
2139
+ {platform: 'darwin-arm64', package: {name: 'test-darwin.pkg', sha256: 'abc', size: 100}},
2140
+ {platform: 'linux-x86_64', package: {name: 'test-linux.pkg', sha256: 'def', size: 200}}
2141
+ ]
2142
+ }
2143
+ },
2144
+ availableVersions: ['1.0.0']
2145
+ });
2146
+ const darwinBuild = withBuilds.buildForPlatform('darwin-arm64');
2147
+ assert(darwinBuild !== null, 'Should find darwin-arm64 build');
2148
+ assert(darwinBuild.package.name === 'test-darwin.pkg', 'Should have correct package name');
2149
+
2150
+ const linuxBuild = withBuilds.buildForPlatform('linux-x86_64');
2151
+ assert(linuxBuild !== null, 'Should find linux-x86_64 build');
2152
+
2153
+ const missingBuild = withBuilds.buildForPlatform('windows-x86_64');
2154
+ assert(missingBuild === null, 'Should return null for missing platform');
2125
2155
 
2126
- const noPkg1 = new CartridgeInfo({id: 'test', packageName: '', packageSha256: 'abc', caps: []});
2127
- assert(noPkg1.hasPackage() === false, 'Cartridge without packageName should return false');
2156
+ const platforms = withBuilds.availablePlatforms();
2157
+ assert(platforms.length === 2, 'Should have 2 platforms');
2158
+ assert(platforms.includes('darwin-arm64'), 'Should include darwin-arm64');
2159
+ assert(platforms.includes('linux-x86_64'), 'Should include linux-x86_64');
2128
2160
 
2129
- const noPkg2 = new CartridgeInfo({id: 'test', packageName: 'test.pkg', packageSha256: '', caps: []});
2130
- assert(noPkg2.hasPackage() === false, 'Cartridge without packageSha256 should return false');
2161
+ const noBuilds = new CartridgeInfo({id: 'test', version: '1.0.0', caps: [], versions: {}, availableVersions: []});
2162
+ assert(noBuilds.buildForPlatform('darwin-arm64') === null, 'Should return null when no versions');
2163
+ assert(noBuilds.availablePlatforms().length === 0, 'Should have no platforms');
2131
2164
  }
2132
2165
 
2133
2166
  // TEST323: CartridgeRepoServer validate registry
2134
2167
  function test323_cartridgeRepoServerValidateRegistry() {
2135
2168
  // Valid registry
2136
2169
  const server = new CartridgeRepoServer(sampleRegistry);
2137
- assert(server.registry.schemaVersion === '3.0', 'Should accept valid registry');
2170
+ assert(server.registry.schemaVersion === '4.0', 'Should accept valid registry');
2138
2171
 
2139
2172
  // Invalid schema version
2140
2173
  let threw = false;
2141
2174
  try {
2142
- new CartridgeRepoServer({schemaVersion: '2.0', cartridges: {}});
2175
+ new CartridgeRepoServer({schemaVersion: '3.0', cartridges: {}});
2143
2176
  } catch (e) {
2144
2177
  threw = true;
2145
2178
  assert(e.message.includes('schema version'), 'Should reject wrong schema version');
@@ -2149,7 +2182,7 @@ function test323_cartridgeRepoServerValidateRegistry() {
2149
2182
  // Missing cartridges
2150
2183
  threw = false;
2151
2184
  try {
2152
- new CartridgeRepoServer({schemaVersion: '3.0'});
2185
+ new CartridgeRepoServer({schemaVersion: '4.0'});
2153
2186
  } catch (e) {
2154
2187
  threw = true;
2155
2188
  assert(e.message.includes('cartridges'), 'Should reject missing cartridges');
@@ -2170,8 +2203,14 @@ function test324_cartridgeRepoServerTransformToArray() {
2170
2203
  assert(pdf.version === '0.81.5325', 'Should have latest version');
2171
2204
  assert(pdf.teamId === 'P336JK947M', 'Should have teamId');
2172
2205
  assert(pdf.signedAt === '2026-02-07T16:40:28Z', 'Should have signedAt from releaseDate');
2173
- assert(pdf.packageName === 'pdfcartridge-0.81.5325.pkg', 'Should have package name');
2174
- assert(pdf.packageSha256 === '9b68724eb9220ecf01e8ed4f5f80c594fbac2239bc5bf675005ec882ecc5eba0', 'Should have package SHA256');
2206
+ assert(pdf.versions !== undefined, 'Should have versions');
2207
+ assert(pdf.versions['0.81.5325'] !== undefined, 'Should have version data');
2208
+ assert(pdf.versions['0.81.5325'].builds.length === 1, 'Should have 1 build');
2209
+ assert(pdf.versions['0.81.5325'].builds[0].platform === 'darwin-arm64', 'Should have correct platform');
2210
+ assert(pdf.versions['0.81.5325'].builds[0].package.name === 'pdfcartridge-0.81.5325.pkg', 'Should have package name');
2211
+ assert(pdf.versions['0.81.5325'].builds[0].package.sha256 === '9b68724eb9220ecf01e8ed4f5f80c594fbac2239bc5bf675005ec882ecc5eba0', 'Should have package SHA256');
2212
+ assert(Array.isArray(pdf.availableVersions), 'Should have availableVersions array');
2213
+ assert(pdf.availableVersions.includes('0.81.5325'), 'Should include latest version');
2175
2214
  assert(Array.isArray(pdf.caps), 'Should have caps array');
2176
2215
  assert(pdf.caps.length === 2, 'Should have 2 caps');
2177
2216
  }
@@ -2338,7 +2377,7 @@ function test335_cartridgeRepoServerClientIntegration() {
2338
2377
  const cartridge = client.getCartridge('pdfcartridge');
2339
2378
  assert(cartridge !== null, 'Client should find cartridge from server data');
2340
2379
  assert(cartridge.isSigned(), 'Cartridge should be signed');
2341
- assert(cartridge.hasPackage(), 'Cartridge should have package');
2380
+ assert(cartridge.buildForPlatform('darwin-arm64') !== null, 'Cartridge should have darwin-arm64 build');
2342
2381
 
2343
2382
  // Client can get suggestions
2344
2383
  const capUrn = 'cap:in="media:pdf";op=disbind;out="media:disbound-page;textable;list"';
@@ -5395,7 +5434,7 @@ async function runTests() {
5395
5434
  console.log('\n--- cartridge_repo ---');
5396
5435
  runTest('TEST320: cartridge_info_construction', test320_cartridgeInfoConstruction);
5397
5436
  runTest('TEST321: cartridge_info_is_signed', test321_cartridgeInfoIsSigned);
5398
- runTest('TEST322: cartridge_info_has_package', test322_cartridgeInfoHasPackage);
5437
+ runTest('TEST322: cartridge_info_build_for_platform', test322_cartridgeInfoBuildForPlatform);
5399
5438
  runTest('TEST323: cartridge_repo_server_validate_registry', test323_cartridgeRepoServerValidateRegistry);
5400
5439
  runTest('TEST324: cartridge_repo_server_transform_to_array', test324_cartridgeRepoServerTransformToArray);
5401
5440
  runTest('TEST325: cartridge_repo_server_get_cartridges', test325_cartridgeRepoServerGetCartridges);
package/package.json CHANGED
@@ -40,5 +40,5 @@
40
40
  "pretest": "npm run build:parser",
41
41
  "test": "node capdag.test.js"
42
42
  },
43
- "version": "0.124.274"
43
+ "version": "0.126.278"
44
44
  }