@phreshos/cli 0.1.13 → 0.1.14

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.
@@ -4,16 +4,6 @@ import { mkdtemp, readFile, rm } from "node:fs/promises";
4
4
  import { tmpdir } from "node:os";
5
5
  import { dirname, isAbsolute, join, relative, resolve } from "node:path";
6
6
  import AdmZip from "adm-zip";
7
- const officialPrograms = {
8
- phresh: {
9
- identity: "phresh-program",
10
- repository: "PhreshOS/phresh-program"
11
- },
12
- setup: {
13
- identity: "setup",
14
- repository: "PhreshOS/setup-program"
15
- }
16
- };
17
7
  /** Resolve, verify, and unpack one official production Program release. */
18
8
  export async function prepareOfficialProgram(name, fetcher = fetch) {
19
9
  const release = await resolveOfficialProgramRelease(name, fetcher);
@@ -34,10 +24,8 @@ export async function prepareOfficialProgram(name, fetcher = fetch) {
34
24
  }
35
25
  }
36
26
  export async function resolveOfficialProgramRelease(name, fetcher = fetch) {
37
- const official = officialPrograms[name];
38
- if (!official)
39
- throw new Error(`No official Program is named "${name}"`);
40
- const response = await fetcher(`https://api.github.com/repos/${official.repository}/releases?per_page=100`, {
27
+ const requested = programName(name);
28
+ const response = await fetcher(`https://api.github.com/repos/PhreshOS/${requested}-program/releases?per_page=100`, {
41
29
  headers: {
42
30
  Accept: "application/vnd.github+json",
43
31
  "User-Agent": "@phreshos/cli"
@@ -46,26 +34,24 @@ export async function resolveOfficialProgramRelease(name, fetcher = fetch) {
46
34
  });
47
35
  if (!response.ok)
48
36
  throw new Error(`The ${name} release list could not be read (${response.status} ${response.statusText})`);
49
- return selectProgramRelease(official.identity, await response.json());
37
+ return selectProgramRelease(await response.json());
50
38
  }
51
- export function selectProgramRelease(identity, value) {
39
+ export function selectProgramRelease(value) {
52
40
  if (!Array.isArray(value))
53
- throw new Error(`The ${identity} release list is invalid`);
41
+ throw new Error("The Program release list is invalid");
54
42
  const releases = value.flatMap(function (item) {
55
43
  if (!record(item) || item.draft === true || item.prerelease === true || typeof item.tag_name !== "string" || !Array.isArray(item.assets))
56
44
  return [];
57
45
  const version = parseVersion(item.tag_name);
58
46
  if (!version)
59
47
  return [];
60
- const archiveName = `${identity}@${version}.zip`;
61
- const archive = asset(item.assets, archiveName);
62
- const checksum = asset(item.assets, `${archiveName}.sha256`);
63
- return archive && checksum ? [{ identity, version, archive, checksum }] : [];
48
+ const files = programAssets(item.assets, version);
49
+ return files ? [{ version, ...files }] : [];
64
50
  });
65
51
  releases.sort((left, right) => compare(right.version, left.version));
66
52
  const selected = releases[0];
67
53
  if (!selected)
68
- throw new Error(`No stable ${identity} Program release is available`);
54
+ throw new Error("No stable Program release is available");
69
55
  return selected;
70
56
  }
71
57
  export async function downloadProgramRelease(release, fetcher = fetch) {
@@ -150,6 +136,27 @@ function asset(assets, name) {
150
136
  const found = assets.find(item => record(item) && item.name === name && typeof item.browser_download_url === "string");
151
137
  return record(found) && typeof found.browser_download_url === "string" ? found.browser_download_url : undefined;
152
138
  }
139
+ function programAssets(assets, version) {
140
+ const suffix = `@${version}.zip`;
141
+ const archives = assets.flatMap(function (item) {
142
+ if (!record(item) || typeof item.name !== "string" || typeof item.browser_download_url !== "string" || !item.name.endsWith(suffix))
143
+ return [];
144
+ const identity = item.name.slice(0, -suffix.length);
145
+ if (!validProgramName(identity))
146
+ return [];
147
+ const checksum = asset(assets, `${item.name}.sha256`);
148
+ return checksum ? [{ identity, archive: item.browser_download_url, checksum }] : [];
149
+ });
150
+ return archives.length === 1 ? archives[0] : undefined;
151
+ }
152
+ function programName(name) {
153
+ if (!validProgramName(name))
154
+ throw new Error(`The official Program name "${name}" is invalid`);
155
+ return name;
156
+ }
157
+ function validProgramName(name) {
158
+ return name.length <= 64 && /^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(name);
159
+ }
153
160
  function parseVersion(tag) {
154
161
  const match = /^v(\d+)\.(\d+)\.(\d+)$/.exec(tag);
155
162
  return match ? tag.slice(1) : undefined;
package/dist/style.js CHANGED
@@ -19,7 +19,6 @@ export function column(label) {
19
19
  return label.length < 12 ? label.padEnd(12) : `${label} `;
20
20
  }
21
21
  export function heading(title, note) {
22
- console.log("");
23
22
  section(title, note);
24
23
  console.log("");
25
24
  }
@@ -16,7 +16,7 @@
16
16
  "react-dom": "^19.2.8"
17
17
  },
18
18
  "devDependencies": {
19
- "@phreshos/cli": "^0.1.13",
19
+ "@phreshos/cli": "^0.1.14",
20
20
  "@types/node": "^26.2.0",
21
21
  "@types/react": "^19.2.18",
22
22
  "@types/react-dom": "^19.2.4",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@phreshos/cli",
3
3
  "type": "module",
4
- "version": "0.1.13",
4
+ "version": "0.1.14",
5
5
  "description": "The Phresh command-line interface for Program projects and system management.",
6
6
  "engines": {
7
7
  "node": ">=20.10"