@studio-foundation/cli 0.11.1 → 0.12.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.
Files changed (126) hide show
  1. package/README.md +33 -30
  2. package/dist/commands/init.d.ts +7 -3
  3. package/dist/commands/init.d.ts.map +1 -1
  4. package/dist/commands/init.js +17 -21
  5. package/dist/commands/init.js.map +1 -1
  6. package/dist/commands/integrations.d.ts.map +1 -1
  7. package/dist/commands/integrations.js +20 -28
  8. package/dist/commands/integrations.js.map +1 -1
  9. package/dist/commands/marketplace.d.ts +17 -0
  10. package/dist/commands/marketplace.d.ts.map +1 -0
  11. package/dist/commands/marketplace.js +132 -0
  12. package/dist/commands/marketplace.js.map +1 -0
  13. package/dist/commands/plugin.d.ts +8 -0
  14. package/dist/commands/plugin.d.ts.map +1 -0
  15. package/dist/commands/plugin.js +42 -0
  16. package/dist/commands/plugin.js.map +1 -0
  17. package/dist/commands/registry/audit.d.ts +2 -1
  18. package/dist/commands/registry/audit.d.ts.map +1 -1
  19. package/dist/commands/registry/audit.js +32 -22
  20. package/dist/commands/registry/audit.js.map +1 -1
  21. package/dist/commands/registry/index.d.ts.map +1 -1
  22. package/dist/commands/registry/index.js +4 -3
  23. package/dist/commands/registry/index.js.map +1 -1
  24. package/dist/commands/registry/install.d.ts +4 -2
  25. package/dist/commands/registry/install.d.ts.map +1 -1
  26. package/dist/commands/registry/install.js +132 -73
  27. package/dist/commands/registry/install.js.map +1 -1
  28. package/dist/commands/registry/remove.d.ts.map +1 -1
  29. package/dist/commands/registry/remove.js +11 -25
  30. package/dist/commands/registry/remove.js.map +1 -1
  31. package/dist/commands/registry/search.d.ts +1 -1
  32. package/dist/commands/registry/search.d.ts.map +1 -1
  33. package/dist/commands/registry/search.js +33 -17
  34. package/dist/commands/registry/search.js.map +1 -1
  35. package/dist/commands/registry/sync.d.ts +1 -0
  36. package/dist/commands/registry/sync.d.ts.map +1 -1
  37. package/dist/commands/registry/sync.js +46 -12
  38. package/dist/commands/registry/sync.js.map +1 -1
  39. package/dist/commands/registry/update.d.ts +14 -2
  40. package/dist/commands/registry/update.d.ts.map +1 -1
  41. package/dist/commands/registry/update.js +70 -18
  42. package/dist/commands/registry/update.js.map +1 -1
  43. package/dist/commands/templates.d.ts.map +1 -1
  44. package/dist/commands/templates.js +13 -16
  45. package/dist/commands/templates.js.map +1 -1
  46. package/dist/commands/tools.d.ts.map +1 -1
  47. package/dist/commands/tools.js +6 -2
  48. package/dist/commands/tools.js.map +1 -1
  49. package/dist/commands/upgrade.d.ts +3 -0
  50. package/dist/commands/upgrade.d.ts.map +1 -0
  51. package/dist/commands/upgrade.js +79 -0
  52. package/dist/commands/upgrade.js.map +1 -0
  53. package/dist/generated/bundled-assets.d.ts +1 -1
  54. package/dist/generated/bundled-assets.d.ts.map +1 -1
  55. package/dist/generated/bundled-assets.js +77 -2
  56. package/dist/generated/bundled-assets.js.map +1 -1
  57. package/dist/index.js +9 -0
  58. package/dist/index.js.map +1 -1
  59. package/dist/output/map-progress.d.ts +11 -1
  60. package/dist/output/map-progress.d.ts.map +1 -1
  61. package/dist/output/map-progress.js +43 -4
  62. package/dist/output/map-progress.js.map +1 -1
  63. package/dist/output/progress.d.ts.map +1 -1
  64. package/dist/output/progress.js +1 -1
  65. package/dist/output/progress.js.map +1 -1
  66. package/dist/registry/cache.d.ts +1 -1
  67. package/dist/registry/cache.d.ts.map +1 -1
  68. package/dist/registry/cache.js +3 -2
  69. package/dist/registry/cache.js.map +1 -1
  70. package/dist/registry/client.d.ts +20 -11
  71. package/dist/registry/client.d.ts.map +1 -1
  72. package/dist/registry/client.js +145 -45
  73. package/dist/registry/client.js.map +1 -1
  74. package/dist/registry/constraints.d.ts +17 -0
  75. package/dist/registry/constraints.d.ts.map +1 -0
  76. package/dist/registry/constraints.js +30 -0
  77. package/dist/registry/constraints.js.map +1 -0
  78. package/dist/registry/dependency-spec.d.ts +15 -0
  79. package/dist/registry/dependency-spec.d.ts.map +1 -0
  80. package/dist/registry/dependency-spec.js +17 -0
  81. package/dist/registry/dependency-spec.js.map +1 -0
  82. package/dist/registry/git-source.d.ts +16 -0
  83. package/dist/registry/git-source.d.ts.map +1 -0
  84. package/dist/registry/git-source.js +92 -0
  85. package/dist/registry/git-source.js.map +1 -0
  86. package/dist/registry/legacy-paths.d.ts +3 -0
  87. package/dist/registry/legacy-paths.d.ts.map +1 -0
  88. package/dist/registry/legacy-paths.js +31 -0
  89. package/dist/registry/legacy-paths.js.map +1 -0
  90. package/dist/registry/lockfile.d.ts +5 -1
  91. package/dist/registry/lockfile.d.ts.map +1 -1
  92. package/dist/registry/lockfile.js +28 -7
  93. package/dist/registry/lockfile.js.map +1 -1
  94. package/dist/registry/marketplaces.d.ts +23 -0
  95. package/dist/registry/marketplaces.d.ts.map +1 -0
  96. package/dist/registry/marketplaces.js +83 -0
  97. package/dist/registry/marketplaces.js.map +1 -0
  98. package/dist/registry/registry-index.d.ts +36 -0
  99. package/dist/registry/registry-index.d.ts.map +1 -0
  100. package/dist/registry/registry-index.js +57 -0
  101. package/dist/registry/registry-index.js.map +1 -0
  102. package/dist/registry/resolver.d.ts +15 -3
  103. package/dist/registry/resolver.d.ts.map +1 -1
  104. package/dist/registry/resolver.js +82 -72
  105. package/dist/registry/resolver.js.map +1 -1
  106. package/dist/registry/seed.d.ts +10 -0
  107. package/dist/registry/seed.d.ts.map +1 -0
  108. package/dist/registry/seed.js +25 -0
  109. package/dist/registry/seed.js.map +1 -0
  110. package/dist/registry/types.d.ts +66 -7
  111. package/dist/registry/types.d.ts.map +1 -1
  112. package/dist/registry/types.js +28 -8
  113. package/dist/registry/types.js.map +1 -1
  114. package/dist/registry/verify.d.ts +15 -0
  115. package/dist/registry/verify.d.ts.map +1 -0
  116. package/dist/registry/verify.js +86 -0
  117. package/dist/registry/verify.js.map +1 -0
  118. package/dist/upgrade.d.ts +28 -0
  119. package/dist/upgrade.d.ts.map +1 -0
  120. package/dist/upgrade.js +64 -0
  121. package/dist/upgrade.js.map +1 -0
  122. package/dist/version-guard.d.ts +3 -1
  123. package/dist/version-guard.d.ts.map +1 -1
  124. package/dist/version-guard.js +8 -2
  125. package/dist/version-guard.js.map +1 -1
  126. package/package.json +12 -12
@@ -1,86 +1,96 @@
1
- /** Extract all dependency names (regardless of whether they're in the index) for cycle detection. */
2
- function depNames(deps, kind) {
3
- const names = [];
4
- for (const [, spec] of Object.entries(deps)) {
5
- const arr = spec[kind] ?? [];
6
- names.push(...arr);
1
+ import { parseDependencySpec } from './dependency-spec.js';
2
+ import { selectVersion } from './constraints.js';
3
+ import { candidatesFor } from './registry-index.js';
4
+ /** Parsed dependency entries of one kind, tagged with the category they came from. */
5
+ function specsOf(deps, kind) {
6
+ const out = [];
7
+ for (const [category, entry] of Object.entries(deps)) {
8
+ const names = entry[kind] ?? [];
9
+ for (const raw of names) {
10
+ out.push({ spec: parseDependencySpec(raw), category });
11
+ }
7
12
  }
8
- return names;
13
+ return out;
9
14
  }
10
- function flattenDeps(deps, kind, index, requiredBy) {
11
- const nodes = [];
12
- for (const [category, spec] of Object.entries(deps)) {
13
- const names = spec[kind] ?? [];
14
- for (const name of names) {
15
- const entry = index.packages.find(p => p.name === name);
16
- if (entry) {
17
- nodes.push({ name, type: entry.type });
18
- }
19
- else if (kind === 'required') {
20
- // Fail loud, before install: a required dep absent from the index would
21
- // otherwise install "successfully" and then crash at run time.
22
- throw new Error(`Missing required dependency '${name}' (${category}) of package '${requiredBy}': ` +
23
- `not found in the registry index. Run 'studio registry sync' or check the package name.`);
24
- }
25
- // A missing recommended dependency is optional — skipped, not fatal.
26
- }
15
+ /**
16
+ * Which marketplace a dependency resolves against: the one it names, or the
17
+ * dependent's own. A marketplace the user has not registered is refused rather
18
+ * than added silently — `studio marketplace add` is a deliberate act (ADR 0001).
19
+ */
20
+ function marketplaceOf(spec, requiredBy, options) {
21
+ if (!spec.marketplace)
22
+ return options.marketplace;
23
+ if (!options.registered.includes(spec.marketplace)) {
24
+ throw new Error(`Dependency '${spec.raw}' of package '${requiredBy}' names marketplace ` +
25
+ `'${spec.marketplace}', which is not registered. Run: studio marketplace add <url> ` +
26
+ `--name ${spec.marketplace}`);
27
27
  }
28
- return nodes;
28
+ return spec.marketplace;
29
29
  }
30
- export async function resolveDependencies(rootPackageName, meta, index, _lockfile, fetchMeta) {
31
- const resolved = new Map();
30
+ export async function resolveDependencies(rootPackageName, meta, packages, _lockfile, fetchMeta, options) {
31
+ const constraints = new Map();
32
+ const targets = new Map();
33
+ const order = [];
32
34
  const visiting = new Set();
33
- // Track the root package so cycles back to it are detected
34
- visiting.add(rootPackageName);
35
- async function visit(name, pkgMeta) {
36
- if (visiting.has(name)) {
37
- throw new Error(`Circular dependency detected: ${name} is part of a cycle`);
38
- }
39
- if (resolved.has(name))
35
+ async function visit(name, marketplace, pkgMeta) {
36
+ if (!pkgMeta.dependencies)
40
37
  return;
41
- visiting.add(name);
42
- if (pkgMeta.dependencies) {
43
- // Check for cycles on all required names (even those not in index)
44
- for (const depName of depNames(pkgMeta.dependencies, 'required')) {
45
- if (visiting.has(depName)) {
46
- throw new Error(`Circular dependency detected: ${depName} is part of a cycle`);
47
- }
38
+ const selfKey = `${marketplace}:${name}`;
39
+ visiting.add(selfKey);
40
+ for (const { spec, category } of specsOf(pkgMeta.dependencies, 'required')) {
41
+ const depMarketplace = marketplaceOf(spec, name, { ...options, marketplace });
42
+ const key = `${depMarketplace}:${spec.name}`;
43
+ if (visiting.has(key)) {
44
+ throw new Error(`Circular dependency detected: ${spec.name} is part of a cycle`);
48
45
  }
49
- const requiredNodes = flattenDeps(pkgMeta.dependencies, 'required', index, name);
50
- for (const node of requiredNodes) {
51
- if (!resolved.has(node.name)) {
52
- const subMeta = await fetchMeta(node.name);
53
- await visit(node.name, subMeta);
54
- if (!resolved.has(node.name)) {
55
- resolved.set(node.name, node);
56
- }
57
- }
46
+ if (candidatesFor(packages, spec.name, depMarketplace).length === 0) {
47
+ // Fail loud, before install: a required dep absent from the index would
48
+ // otherwise install "successfully" and then crash at run time.
49
+ throw new Error(`Missing required dependency '${spec.name}' (${category}) of package '${name}': ` +
50
+ `not found in marketplace '${depMarketplace}'. Run 'studio registry sync' or check the package name.`);
58
51
  }
59
- }
60
- visiting.delete(name);
61
- }
62
- if (meta.dependencies) {
63
- // Check for cycles at the first level too (root → dep that cycles back to root)
64
- for (const depName of depNames(meta.dependencies, 'required')) {
65
- if (visiting.has(depName)) {
66
- throw new Error(`Circular dependency detected: ${depName} is part of a cycle`);
52
+ const known = constraints.get(key);
53
+ if (known) {
54
+ known.push({ range: spec.range, requiredBy: name });
67
55
  }
68
- }
69
- const firstLevelRequired = flattenDeps(meta.dependencies, 'required', index, rootPackageName);
70
- for (const node of firstLevelRequired) {
71
- const subMeta = await fetchMeta(node.name);
72
- await visit(node.name, subMeta);
73
- if (!resolved.has(node.name)) {
74
- resolved.set(node.name, node);
56
+ else {
57
+ constraints.set(key, [{ range: spec.range, requiredBy: name }]);
58
+ targets.set(key, { name: spec.name, marketplace: depMarketplace });
59
+ order.push(key);
60
+ await visit(spec.name, depMarketplace, await fetchMeta(spec.name, depMarketplace));
75
61
  }
76
62
  }
63
+ visiting.delete(selfKey);
64
+ }
65
+ await visit(rootPackageName, options.marketplace, meta);
66
+ const required = order.map((key) => {
67
+ const { name, marketplace } = targets.get(key);
68
+ const candidates = candidatesFor(packages, name, marketplace);
69
+ const nodeConstraints = constraints.get(key);
70
+ return {
71
+ name,
72
+ marketplace,
73
+ type: candidates[0].type,
74
+ version: selectVersion(name, nodeConstraints, candidates),
75
+ constraints: nodeConstraints,
76
+ };
77
+ });
78
+ const recommended = [];
79
+ for (const { spec } of meta.dependencies ? specsOf(meta.dependencies, 'recommended') : []) {
80
+ const depMarketplace = marketplaceOf(spec, rootPackageName, options);
81
+ const candidates = candidatesFor(packages, spec.name, depMarketplace);
82
+ // A missing recommended dependency is optional — skipped, not fatal.
83
+ if (candidates.length === 0)
84
+ continue;
85
+ const nodeConstraints = [{ range: spec.range, requiredBy: rootPackageName }];
86
+ recommended.push({
87
+ name: spec.name,
88
+ marketplace: depMarketplace,
89
+ type: candidates[0].type,
90
+ version: selectVersion(spec.name, nodeConstraints, candidates),
91
+ constraints: nodeConstraints,
92
+ });
77
93
  }
78
- const recommended = meta.dependencies
79
- ? flattenDeps(meta.dependencies, 'recommended', index, rootPackageName)
80
- : [];
81
- return {
82
- required: Array.from(resolved.values()),
83
- recommended,
84
- };
94
+ return { required, recommended };
85
95
  }
86
96
  //# sourceMappingURL=resolver.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/registry/resolver.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"resolver.js","sourceRoot":"","sources":["../../src/registry/resolver.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAuB,MAAM,sBAAsB,CAAC;AAChF,OAAO,EAAE,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AAClE,OAAO,EAAE,aAAa,EAAuB,MAAM,qBAAqB,CAAC;AAyBzE,sFAAsF;AACtF,SAAS,OAAO,CACd,IAAyB,EACzB,IAAgC;IAEhC,MAAM,GAAG,GAAsD,EAAE,CAAC;IAClE,KAAK,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACrD,MAAM,KAAK,GAAc,KAAkC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACxE,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,CAAC,GAAG,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;QACzD,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAoB,EAAE,UAAkB,EAAE,OAAuB;IACtF,IAAI,CAAC,IAAI,CAAC,WAAW;QAAE,OAAO,OAAO,CAAC,WAAW,CAAC;IAClD,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CACb,eAAe,IAAI,CAAC,GAAG,iBAAiB,UAAU,sBAAsB;YACxE,IAAI,IAAI,CAAC,WAAW,gEAAgE;YACpF,UAAU,IAAI,CAAC,WAAW,EAAE,CAC7B,CAAC;IACJ,CAAC;IACD,OAAO,IAAI,CAAC,WAAW,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,eAAuB,EACvB,IAAqB,EACrB,QAA0B,EAC1B,SAAmB,EACnB,SAA0B,EAC1B,OAAuB;IAEvB,MAAM,WAAW,GAAG,IAAI,GAAG,EAAwB,CAAC;IACpD,MAAM,OAAO,GAAG,IAAI,GAAG,EAAiD,CAAC;IACzE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IAEnC,KAAK,UAAU,KAAK,CAAC,IAAY,EAAE,WAAmB,EAAE,OAAwB;QAC9E,IAAI,CAAC,OAAO,CAAC,YAAY;YAAE,OAAO;QAClC,MAAM,OAAO,GAAG,GAAG,WAAW,IAAI,IAAI,EAAE,CAAC;QACzC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAEtB,KAAK,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,UAAU,CAAC,EAAE,CAAC;YAC3E,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YAC9E,MAAM,GAAG,GAAG,GAAG,cAAc,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YAC7C,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACtB,MAAM,IAAI,KAAK,CAAC,iCAAiC,IAAI,CAAC,IAAI,qBAAqB,CAAC,CAAC;YACnF,CAAC;YACD,IAAI,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACpE,wEAAwE;gBACxE,+DAA+D;gBAC/D,MAAM,IAAI,KAAK,CACb,gCAAgC,IAAI,CAAC,IAAI,MAAM,QAAQ,iBAAiB,IAAI,KAAK;oBACjF,6BAA6B,cAAc,0DAA0D,CACtG,CAAC;YACJ,CAAC;YAED,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,KAAK,EAAE,CAAC;gBACV,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;YACtD,CAAC;iBAAM,CAAC;gBACN,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBAChE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,cAAc,EAAE,CAAC,CAAC;gBACnE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAChB,MAAM,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC;YACrF,CAAC;QACH,CAAC;QAED,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAED,MAAM,KAAK,CAAC,eAAe,EAAE,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAqB,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE;QACnD,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAChD,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC;QAC9D,MAAM,eAAe,GAAG,WAAW,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC9C,OAAO;YACL,IAAI;YACJ,WAAW;YACX,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAmB;YACvC,OAAO,EAAE,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,CAAC;YACzD,WAAW,EAAE,eAAe;SAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,WAAW,GAAqB,EAAE,CAAC;IACzC,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;QAC1F,MAAM,cAAc,GAAG,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,OAAO,CAAC,CAAC;QACrE,MAAM,UAAU,GAAG,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;QACtE,qEAAqE;QACrE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QACtC,MAAM,eAAe,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,UAAU,EAAE,eAAe,EAAE,CAAC,CAAC;QAC7E,WAAW,CAAC,IAAI,CAAC;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,WAAW,EAAE,cAAc;YAC3B,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAmB;YACvC,OAAO,EAAE,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,CAAC;YAC9D,WAAW,EAAE,eAAe;SAC7B,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,10 @@
1
+ import type { RegistryIndex } from './types.js';
2
+ export declare function seedIndex(): RegistryIndex | null;
3
+ /** The seeded copy of one marketplace file, addressed as the registry addresses it. */
4
+ export declare function seedFile(path: string): string | null;
5
+ /** Every seeded file under `dir`, with paths relative to `dir`, sorted. */
6
+ export declare function seedFiles(dir: string): Array<{
7
+ path: string;
8
+ content: string;
9
+ }>;
10
+ //# sourceMappingURL=seed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.d.ts","sourceRoot":"","sources":["../../src/registry/seed.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAUhD,wBAAgB,SAAS,IAAI,aAAa,GAAG,IAAI,CAGhD;AAED,uFAAuF;AACvF,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpD;AAED,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAM/E"}
@@ -0,0 +1,25 @@
1
+ import { BUNDLED_ASSETS } from '../generated/bundled-assets.js';
2
+ /**
3
+ * The pre-fetched marketplace snapshot bundled with the CLI, used when the live
4
+ * registry is unreachable. It mirrors the marketplace layout verbatim, so every
5
+ * lookup is a path lookup — the kernel never names a package. Refresh it with
6
+ * `node scripts/refresh-seed.mjs`.
7
+ */
8
+ const SEED_PREFIX = 'seed/';
9
+ export function seedIndex() {
10
+ const raw = BUNDLED_ASSETS[`${SEED_PREFIX}index.json`];
11
+ return raw ? JSON.parse(raw) : null;
12
+ }
13
+ /** The seeded copy of one marketplace file, addressed as the registry addresses it. */
14
+ export function seedFile(path) {
15
+ return BUNDLED_ASSETS[`${SEED_PREFIX}${path}`] ?? null;
16
+ }
17
+ /** Every seeded file under `dir`, with paths relative to `dir`, sorted. */
18
+ export function seedFiles(dir) {
19
+ const prefix = `${SEED_PREFIX}${dir}/`;
20
+ return Object.keys(BUNDLED_ASSETS)
21
+ .filter((key) => key.startsWith(prefix))
22
+ .sort()
23
+ .map((key) => ({ path: key.slice(prefix.length), content: BUNDLED_ASSETS[key] }));
24
+ }
25
+ //# sourceMappingURL=seed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"seed.js","sourceRoot":"","sources":["../../src/registry/seed.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAGhE;;;;;GAKG;AACH,MAAM,WAAW,GAAG,OAAO,CAAC;AAE5B,MAAM,UAAU,SAAS;IACvB,MAAM,GAAG,GAAG,cAAc,CAAC,GAAG,WAAW,YAAY,CAAC,CAAC;IACvD,OAAO,GAAG,CAAC,CAAC,CAAE,IAAI,CAAC,KAAK,CAAC,GAAG,CAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC;AAED,uFAAuF;AACvF,MAAM,UAAU,QAAQ,CAAC,IAAY;IACnC,OAAO,cAAc,CAAC,GAAG,WAAW,GAAG,IAAI,EAAE,CAAC,IAAI,IAAI,CAAC;AACzD,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,MAAM,GAAG,GAAG,WAAW,GAAG,GAAG,GAAG,CAAC;IACvC,OAAO,MAAM,CAAC,IAAI,CAAC,cAAc,CAAC;SAC/B,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;SACvC,IAAI,EAAE;SACN,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AACtF,CAAC"}
@@ -1,4 +1,35 @@
1
- export type PackageType = 'tool' | 'template' | 'pipeline' | 'integration' | 'agent' | 'plugin' | 'skill';
1
+ /**
2
+ * Two packaging types, each defined by its install verb (ADR 0002). What used to
3
+ * be a type — tool, agent, skill… — is a content kind carried inside a plugin.
4
+ */
5
+ export type PackageType = 'template' | 'plugin';
6
+ /** What a plugin delivers into `.studio/`. */
7
+ export type ContentKind = 'tool' | 'agent' | 'skill' | 'integration' | 'pipeline' | 'contract' | 'input';
8
+ /** A plugin's declared contents, by kind. Search reads it; install verifies nothing against it. */
9
+ export type PackageProvides = Partial<Record<`${ContentKind}s`, string[]>>;
10
+ /**
11
+ * Where a package's payload lives: `path` is the package directory in the
12
+ * marketplace repo, never derived from `name` — the two may diverge. Payload
13
+ * filenames are discovered by listing that directory.
14
+ */
15
+ export interface LocalSource {
16
+ type: 'local';
17
+ path: string;
18
+ }
19
+ /**
20
+ * A payload hosted outside the marketplace repo (ADR 0001). `sha` is the commit
21
+ * actually installed; `ref` is what it is checked against, so an upstream push
22
+ * that moves the tag fails the install instead of silently changing the payload.
23
+ */
24
+ export interface GitSource {
25
+ type: 'git';
26
+ url: string;
27
+ /** Package directory inside the repo. Absent means the repository root. */
28
+ path?: string;
29
+ ref: string;
30
+ sha: string;
31
+ }
32
+ export type PackageSource = LocalSource | GitSource;
2
33
  export interface PackageEntry {
3
34
  name: string;
4
35
  type: PackageType;
@@ -9,13 +40,24 @@ export interface PackageEntry {
9
40
  tags: string[];
10
41
  studio_version: string | null;
11
42
  downloads: number;
43
+ provides?: PackageProvides;
44
+ source: PackageSource;
12
45
  }
13
46
  export interface RegistryIndex {
14
47
  generated_at: string;
15
48
  version: string;
16
49
  packages: PackageEntry[];
17
50
  }
51
+ /**
52
+ * Every category resolves identically — by name, through the same index. `plugins`
53
+ * is the form ADR 0002 settles on; the others are the pre-migration spelling and
54
+ * keep working. Entries are `[marketplace:]name[@range]`.
55
+ */
18
56
  export interface PackageDependencies {
57
+ plugins?: {
58
+ required?: string[];
59
+ recommended?: string[];
60
+ };
19
61
  tools?: {
20
62
  required?: string[];
21
63
  recommended?: string[];
@@ -37,23 +79,40 @@ export interface PackageDependencies {
37
79
  recommended?: string[];
38
80
  };
39
81
  }
40
- export interface PackageMetadata extends PackageEntry {
82
+ export interface PackageMetadata extends Omit<PackageEntry, 'source'> {
41
83
  requires_binaries?: string[];
42
84
  dependencies?: PackageDependencies;
43
85
  }
44
86
  export interface LockfileEntry {
87
+ /** `template` or `plugin`, or one of the pre-migration types on an older lockfile. */
88
+ type: string;
89
+ /** Marketplace it came from. Absent on entries written before marketplaces existed. */
90
+ marketplace?: string;
45
91
  version: string;
46
- type: PackageType;
47
92
  installed_at: string;
48
93
  sha256: string;
94
+ /** What the package wrote, relative to `.studio/`. Absent on pre-migration entries. */
95
+ files?: string[];
49
96
  required_by?: string[];
97
+ /**
98
+ * Range declared by each dependent, e.g. `{ "software": ">=1.2.0" }`. Without it
99
+ * an update has no way to tell "newest" from "newest my dependents accept".
100
+ * Only dependents that declared a range appear.
101
+ */
102
+ constraints?: Record<string, string>;
50
103
  }
51
104
  export interface Lockfile {
52
105
  installed: Record<string, LockfileEntry>;
53
106
  }
54
- /** Where packages get installed relative to the project's .studio/ dir */
55
- export declare const INSTALL_DIRS: Record<PackageType, string>;
107
+ /** Where each content kind lands, relative to the project's `.studio/` dir. */
108
+ export declare const CONTENT_DIRS: Record<ContentKind, string>;
109
+ /**
110
+ * Payload filename suffix → content kind. The suffix is the only thing that
111
+ * decides where a plugin's file lands; `provides` is a declaration, not authority.
112
+ */
113
+ export declare const CONTENT_EXTENSIONS: Record<string, ContentKind>;
114
+ export declare function contentKindOf(filename: string): ContentKind | null;
115
+ /** Where an installed template's payload lands, relative to `.studio/`. */
116
+ export declare const TEMPLATE_DIR = "projects";
56
117
  export declare const REGISTRY_REPO = "studio-foundation/studio-community";
57
- export declare const REGISTRY_RAW_BASE = "https://raw.githubusercontent.com/studio-foundation/studio-community/main";
58
- export declare const REGISTRY_API_BASE = "https://api.github.com/repos/studio-foundation/studio-community";
59
118
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,UAAU,GACV,UAAU,GACV,aAAa,GACb,OAAO,GACP,QAAQ,GACR,OAAO,CAAC;AAEZ,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAM;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,MAAM,CAAC,EAAK;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,MAAM,CAAC,EAAK;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;IAC5D,SAAS,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;CAC7D;AAED,MAAM,WAAW,eAAgB,SAAQ,YAAY;IACnD,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7B,YAAY,CAAC,EAAE,mBAAmB,CAAC;CACpC;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,WAAW,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CAC1C;AAED,0EAA0E;AAC1E,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,WAAW,EAAE,MAAM,CAQpD,CAAC;AAEF,eAAO,MAAM,aAAa,uCAAuC,CAAC;AAClE,eAAO,MAAM,iBAAiB,8EAA4D,CAAC;AAC3F,eAAO,MAAM,iBAAiB,oEAAkD,CAAC"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"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"}
@@ -1,14 +1,34 @@
1
- /** Where packages get installed relative to the project's .studio/ dir */
2
- export const INSTALL_DIRS = {
1
+ /** Where each content kind lands, relative to the project's `.studio/` dir. */
2
+ export const CONTENT_DIRS = {
3
3
  tool: 'tools',
4
- template: 'projects',
5
- pipeline: 'pipelines',
6
- integration: 'integrations',
7
4
  agent: 'agents',
8
- plugin: 'plugins',
9
5
  skill: 'skills',
6
+ integration: 'integrations',
7
+ pipeline: 'pipelines',
8
+ contract: 'contracts',
9
+ input: 'inputs',
10
+ };
11
+ /**
12
+ * Payload filename suffix → content kind. The suffix is the only thing that
13
+ * decides where a plugin's file lands; `provides` is a declaration, not authority.
14
+ */
15
+ export const CONTENT_EXTENSIONS = {
16
+ '.tool.yaml': 'tool',
17
+ '.agent.yaml': 'agent',
18
+ '.skill.md': 'skill',
19
+ '.integration.yaml': 'integration',
20
+ '.pipeline.yaml': 'pipeline',
21
+ '.contract.yaml': 'contract',
22
+ '.input.yaml': 'input',
10
23
  };
24
+ export function contentKindOf(filename) {
25
+ for (const [ext, kind] of Object.entries(CONTENT_EXTENSIONS)) {
26
+ if (filename.endsWith(ext))
27
+ return kind;
28
+ }
29
+ return null;
30
+ }
31
+ /** Where an installed template's payload lands, relative to `.studio/`. */
32
+ export const TEMPLATE_DIR = 'projects';
11
33
  export const REGISTRY_REPO = 'studio-foundation/studio-community';
12
- export const REGISTRY_RAW_BASE = `https://raw.githubusercontent.com/${REGISTRY_REPO}/main`;
13
- export const REGISTRY_API_BASE = `https://api.github.com/repos/${REGISTRY_REPO}`;
14
34
  //# sourceMappingURL=types.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAoDA,0EAA0E;AAC1E,MAAM,CAAC,MAAM,YAAY,GAAgC;IACvD,IAAI,EAAE,OAAO;IACb,QAAQ,EAAE,UAAU;IACpB,QAAQ,EAAE,WAAW;IACrB,WAAW,EAAE,cAAc;IAC3B,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,SAAS;IACjB,KAAK,EAAE,QAAQ;CAChB,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,oCAAoC,CAAC;AAClE,MAAM,CAAC,MAAM,iBAAiB,GAAG,qCAAqC,aAAa,OAAO,CAAC;AAC3F,MAAM,CAAC,MAAM,iBAAiB,GAAG,gCAAgC,aAAa,EAAE,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/registry/types.ts"],"names":[],"mappings":"AAoGA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,YAAY,GAAgC;IACvD,IAAI,EAAE,OAAO;IACb,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,QAAQ;IACf,WAAW,EAAE,cAAc;IAC3B,QAAQ,EAAE,WAAW;IACrB,QAAQ,EAAE,WAAW;IACrB,KAAK,EAAE,QAAQ;CAChB,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAgC;IAC7D,YAAY,EAAE,MAAM;IACpB,aAAa,EAAE,OAAO;IACtB,WAAW,EAAE,OAAO;IACpB,mBAAmB,EAAE,aAAa;IAClC,gBAAgB,EAAE,UAAU;IAC5B,gBAAgB,EAAE,UAAU;IAC5B,aAAa,EAAE,OAAO;CACvB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAC7D,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IAC1C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,2EAA2E;AAC3E,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,CAAC;AAEvC,MAAM,CAAC,MAAM,aAAa,GAAG,oCAAoC,CAAC"}
@@ -0,0 +1,15 @@
1
+ import { type PackageProvides } from './types.js';
2
+ import type { PayloadFile } from './client.js';
3
+ export interface VerifiableEntry {
4
+ name: string;
5
+ license: string;
6
+ provides?: PackageProvides;
7
+ }
8
+ /**
9
+ * Assert a fetched payload against what its index entry claims. Only meaningful
10
+ * for sources hosted outside the marketplace repo, where review sees a URL and
11
+ * never the files (ADR 0001).
12
+ */
13
+ export declare function verifyPayload(files: PayloadFile[], entry: VerifiableEntry): string[];
14
+ export declare function assertPayload(files: PayloadFile[], entry: VerifiableEntry): void;
15
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/registry/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqC,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AACrF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAsE/C,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,eAAe,CAAC;CAC5B;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,eAAe,GAAG,MAAM,EAAE,CAKpF;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAQhF"}
@@ -0,0 +1,86 @@
1
+ import { CONTENT_EXTENSIONS, contentKindOf } from './types.js';
2
+ /**
3
+ * Enough of each license's text to tell it apart from the others. A payload may
4
+ * ship any wording it likes as long as it is the license the entry declares —
5
+ * the index says what users are agreeing to, and review only ever sees the index.
6
+ */
7
+ const LICENSE_SIGNATURES = {
8
+ 'MIT': /MIT License|Permission is hereby granted, free of charge/i,
9
+ 'ISC': /ISC License|Permission to use, copy, modify, and\/or distribute/i,
10
+ 'Apache-2.0': /Apache License[\s\S]{0,80}Version 2\.0/i,
11
+ 'AGPL-3.0': /GNU AFFERO GENERAL PUBLIC LICENSE[\s\S]{0,80}Version 3/i,
12
+ 'GPL-3.0': /GNU GENERAL PUBLIC LICENSE[\s\S]{0,80}Version 3/i,
13
+ 'LGPL-3.0': /GNU LESSER GENERAL PUBLIC LICENSE[\s\S]{0,80}Version 3/i,
14
+ 'MPL-2.0': /Mozilla Public License Version 2\.0/i,
15
+ 'BSD-3-Clause': /Redistribution and use in source and binary forms[\s\S]*?Neither the name/i,
16
+ 'BSD-2-Clause': /Redistribution and use in source and binary forms/i,
17
+ };
18
+ const LICENSE_FILE = /^LICEN[SC]E(\.[\w-]+)?$/i;
19
+ function baseName(path) {
20
+ return path.slice(path.lastIndexOf('/') + 1);
21
+ }
22
+ /** `coder.agent.yaml` → `coder`, the name `provides` lists it under. */
23
+ function payloadName(filename) {
24
+ for (const ext of Object.keys(CONTENT_EXTENSIONS)) {
25
+ if (filename.endsWith(ext))
26
+ return filename.slice(0, -ext.length);
27
+ }
28
+ return null;
29
+ }
30
+ function checkLicense(files, license) {
31
+ const file = files.find((f) => LICENSE_FILE.test(baseName(f.path)));
32
+ if (!file)
33
+ return [`declares license '${license}' but ships no LICENSE file`];
34
+ const spdx = license.replace(/-(only|or-later)$/, '');
35
+ const signature = LICENSE_SIGNATURES[spdx];
36
+ if (!signature)
37
+ return [];
38
+ return signature.test(file.content)
39
+ ? []
40
+ : [`ships a LICENSE file that is not '${license}'`];
41
+ }
42
+ function checkProvides(files, provides) {
43
+ const actual = {};
44
+ for (const file of files) {
45
+ const filename = baseName(file.path);
46
+ const kind = contentKindOf(filename);
47
+ const name = payloadName(filename);
48
+ if (!kind || !name)
49
+ continue;
50
+ (actual[`${kind}s`] ??= new Set()).add(name);
51
+ }
52
+ const problems = [];
53
+ for (const [kind, names] of Object.entries(provides)) {
54
+ for (const name of names ?? []) {
55
+ if (!actual[kind]?.has(name))
56
+ problems.push(`declares ${kind} '${name}', absent from the payload`);
57
+ }
58
+ }
59
+ for (const [kind, names] of Object.entries(actual)) {
60
+ const declared = new Set(provides[kind] ?? []);
61
+ for (const name of names) {
62
+ if (!declared.has(name))
63
+ problems.push(`ships undeclared ${kind.replace(/s$/, '')} '${name}'`);
64
+ }
65
+ }
66
+ return problems;
67
+ }
68
+ /**
69
+ * Assert a fetched payload against what its index entry claims. Only meaningful
70
+ * for sources hosted outside the marketplace repo, where review sees a URL and
71
+ * never the files (ADR 0001).
72
+ */
73
+ export function verifyPayload(files, entry) {
74
+ return [
75
+ ...checkLicense(files, entry.license),
76
+ ...(entry.provides ? checkProvides(files, entry.provides) : []),
77
+ ];
78
+ }
79
+ export function assertPayload(files, entry) {
80
+ const problems = verifyPayload(files, entry);
81
+ if (problems.length > 0) {
82
+ throw new Error(`Package '${entry.name}' does not match its registry entry:\n` +
83
+ problems.map((p) => ` - ${p}`).join('\n'));
84
+ }
85
+ }
86
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/registry/verify.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAwB,MAAM,YAAY,CAAC;AAGrF;;;;GAIG;AACH,MAAM,kBAAkB,GAA2B;IACjD,KAAK,EAAE,2DAA2D;IAClE,KAAK,EAAE,kEAAkE;IACzE,YAAY,EAAE,yCAAyC;IACvD,UAAU,EAAE,yDAAyD;IACrE,SAAS,EAAE,kDAAkD;IAC7D,UAAU,EAAE,yDAAyD;IACrE,SAAS,EAAE,sCAAsC;IACjD,cAAc,EAAE,4EAA4E;IAC5F,cAAc,EAAE,oDAAoD;CACrE,CAAC;AAEF,MAAM,YAAY,GAAG,0BAA0B,CAAC;AAEhD,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/C,CAAC;AAED,wEAAwE;AACxE,SAAS,WAAW,CAAC,QAAgB;IACnC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC;QAClD,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC;YAAE,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACpE,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,YAAY,CAAC,KAAoB,EAAE,OAAe;IACzD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACpE,IAAI,CAAC,IAAI;QAAE,OAAO,CAAC,qBAAqB,OAAO,6BAA6B,CAAC,CAAC;IAE9E,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,kBAAkB,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC1B,OAAO,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QACjC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,CAAC,qCAAqC,OAAO,GAAG,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,aAAa,CAAC,KAAoB,EAAE,QAAyB;IACpE,MAAM,MAAM,GAAgC,EAAE,CAAC;IAC/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QACrC,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI;YAAE,SAAS;QAC7B,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACrD,KAAK,MAAM,IAAI,IAAI,KAAK,IAAI,EAAE,EAAE,CAAC;YAC/B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,IAAI,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,YAAY,IAAI,KAAK,IAAI,4BAA4B,CAAC,CAAC;QACrG,CAAC;IACH,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,IAA6B,CAAC,IAAI,EAAE,CAAC,CAAC;QACxE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC;gBAAE,QAAQ,CAAC,IAAI,CAAC,oBAAoB,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC;QACjG,CAAC;IACH,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAQD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,KAAoB,EAAE,KAAsB;IACxE,OAAO;QACL,GAAG,YAAY,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;QACrC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;KAChE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAoB,EAAE,KAAsB;IACxE,MAAM,QAAQ,GAAG,aAAa,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC7C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,YAAY,KAAK,CAAC,IAAI,wCAAwC;YAC9D,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC3C,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ export declare const REPO = "studio-foundation/studio";
2
+ /**
3
+ * How the running Studio got onto this machine. Only a standalone binary can be
4
+ * replaced in place — an npm install is owned by npm, and overwriting a file it
5
+ * tracks breaks the next `npm i -g`.
6
+ */
7
+ export type Install = {
8
+ kind: 'binary';
9
+ path: string;
10
+ } | {
11
+ kind: 'npm';
12
+ };
13
+ /**
14
+ * The npm install resolves through `cli/bin/studio.mjs`, which either runs under Node
15
+ * (JS build) or spawns the binary from a `@studio-foundation/cli-<platform>` package
16
+ * inside `node_modules`. Neither is ours to overwrite.
17
+ */
18
+ export declare function detectInstall(execPath?: string): Install;
19
+ /**
20
+ * The release asset suffix for this machine, or null when no binary ships for it.
21
+ * Mirrors the platform table in scripts/platforms.mjs.
22
+ */
23
+ export declare function platformKey(platform?: string, arch?: string, isMusl?: () => boolean): string | null;
24
+ export declare function assetName(platform: string): string;
25
+ /** The sha256 listed for `asset` in a `sha256sum`-format manifest, or null. */
26
+ export declare function checksumFor(manifest: string, asset: string): string | null;
27
+ export declare function resolveLatestTag(fetchImpl?: typeof fetch): Promise<string>;
28
+ //# sourceMappingURL=upgrade.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../src/upgrade.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,IAAI,6BAA6B,CAAC;AAE/C;;;;GAIG;AACH,MAAM,MAAM,OAAO,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,KAAK,CAAA;CAAE,CAAC;AAEzE;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,GAAE,MAAyB,GAAG,OAAO,CAM1E;AAED;;;GAGG;AACH,wBAAgB,WAAW,CACzB,QAAQ,GAAE,MAAyB,EACnC,IAAI,GAAE,MAAqB,EAC3B,MAAM,GAAE,MAAM,OAAsB,GACnC,MAAM,GAAG,IAAI,CAMf;AAYD,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,+EAA+E;AAC/E,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM1E;AAED,wBAAsB,gBAAgB,CAAC,SAAS,GAAE,OAAO,KAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAQvF"}
@@ -0,0 +1,64 @@
1
+ import { existsSync } from 'node:fs';
2
+ export const REPO = 'studio-foundation/studio';
3
+ /**
4
+ * The npm install resolves through `cli/bin/studio.mjs`, which either runs under Node
5
+ * (JS build) or spawns the binary from a `@studio-foundation/cli-<platform>` package
6
+ * inside `node_modules`. Neither is ours to overwrite.
7
+ */
8
+ export function detectInstall(execPath = process.execPath) {
9
+ const segments = execPath.split(/[/\\]/);
10
+ const name = segments[segments.length - 1];
11
+ if (name !== 'studio' && name !== 'studio.exe')
12
+ return { kind: 'npm' };
13
+ if (segments.includes('node_modules'))
14
+ return { kind: 'npm' };
15
+ return { kind: 'binary', path: execPath };
16
+ }
17
+ /**
18
+ * The release asset suffix for this machine, or null when no binary ships for it.
19
+ * Mirrors the platform table in scripts/platforms.mjs.
20
+ */
21
+ export function platformKey(platform = process.platform, arch = process.arch, isMusl = muslDetected) {
22
+ if (arch !== 'x64' && arch !== 'arm64')
23
+ return null;
24
+ if (platform === 'darwin')
25
+ return `darwin-${arch}`;
26
+ if (platform === 'win32')
27
+ return arch === 'x64' ? 'win-x64' : null;
28
+ if (platform === 'linux')
29
+ return `linux-${arch}${isMusl() ? '-musl' : ''}`;
30
+ return null;
31
+ }
32
+ /**
33
+ * Positive musl detection — the loader file only exists on a musl system. Probing for
34
+ * glibc instead is what shipped the wrong binary to Fedora once, and `process.report`
35
+ * is not available inside the Bun-compiled binary this runs in.
36
+ */
37
+ function muslDetected() {
38
+ const suffix = process.arch === 'arm64' ? 'aarch64' : 'x86_64';
39
+ return existsSync(`/lib/ld-musl-${suffix}.so.1`);
40
+ }
41
+ export function assetName(platform) {
42
+ return platform.startsWith('win-') ? `studio-${platform}.exe` : `studio-${platform}`;
43
+ }
44
+ /** The sha256 listed for `asset` in a `sha256sum`-format manifest, or null. */
45
+ export function checksumFor(manifest, asset) {
46
+ for (const line of manifest.split('\n')) {
47
+ const [hash, name] = line.trim().split(/\s+/);
48
+ if (name === asset && hash)
49
+ return hash;
50
+ }
51
+ return null;
52
+ }
53
+ export async function resolveLatestTag(fetchImpl = fetch) {
54
+ const res = await fetchImpl(`https://api.github.com/repos/${REPO}/releases/latest`, {
55
+ headers: { accept: 'application/vnd.github+json' },
56
+ });
57
+ if (!res.ok)
58
+ throw new Error(`could not resolve the latest release (HTTP ${res.status})`);
59
+ const { tag_name: tag } = (await res.json());
60
+ if (!tag)
61
+ throw new Error('the latest release has no tag');
62
+ return tag;
63
+ }
64
+ //# sourceMappingURL=upgrade.js.map