@dhruv2mars/mdv 0.0.3 → 0.0.6

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.
@@ -0,0 +1,28 @@
1
+ export function assetNameFor(platform = process.platform, arch = process.arch) {
2
+ const ext = platform === 'win32' ? '.exe' : '';
3
+ return `mdv-${platform}-${arch}${ext}`;
4
+ }
5
+
6
+ export function findAssetUrl(release, asset) {
7
+ if (!release || !Array.isArray(release.assets)) return null;
8
+ const match = release.assets.find((item) => item?.name === asset);
9
+ if (!match) return null;
10
+ return match.browser_download_url || null;
11
+ }
12
+
13
+ export async function resolveReleaseAssetUrl({ version, asset, getRelease }) {
14
+ const tag = `tags/v${version}`;
15
+ try {
16
+ const tagged = await getRelease(tag);
17
+ const taggedUrl = findAssetUrl(tagged, asset);
18
+ if (taggedUrl) return taggedUrl;
19
+ } catch {}
20
+
21
+ try {
22
+ const latest = await getRelease('latest');
23
+ const latestUrl = findAssetUrl(latest, asset);
24
+ if (latestUrl) return latestUrl;
25
+ } catch {}
26
+
27
+ return null;
28
+ }
package/bin/install.js CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  existsSync,
7
7
  mkdirSync,
8
8
  readFileSync,
9
+ rmSync,
9
10
  renameSync
10
11
  } from 'node:fs';
11
12
  import { homedir } from 'node:os';
@@ -13,6 +14,7 @@ import { join } from 'node:path';
13
14
  import https from 'node:https';
14
15
  import { spawnSync } from 'node:child_process';
15
16
  import { fileURLToPath } from 'node:url';
17
+ import { assetNameFor, resolveReleaseAssetUrl } from './install-lib.js';
16
18
 
17
19
  const REPO = 'Dhruv2mars/mdv';
18
20
 
@@ -27,22 +29,18 @@ if (existsSync(dest)) process.exit(0);
27
29
  mkdirSync(binDir, { recursive: true });
28
30
 
29
31
  const version = pkgVersion();
30
- const asset = assetName();
32
+ const asset = assetNameFor();
31
33
  const url = `https://github.com/${REPO}/releases/download/v${version}/${asset}`;
32
34
  const tmp = `${dest}.tmp-${Date.now()}`;
33
35
 
34
36
  try {
35
37
  console.error(`mdv: download ${asset} v${version}`);
36
- await download(url, tmp);
38
+ await downloadWithFallback(url, version, asset, tmp);
37
39
  if (process.platform !== 'win32') chmodSync(tmp, 0o755);
38
40
  renameSync(tmp, dest);
39
41
  process.exit(0);
40
42
  } catch (err) {
41
- try {
42
- if (existsSync(tmp)) {
43
- // best-effort cleanup; ignore
44
- }
45
- } catch {}
43
+ try { rmSync(tmp, { force: true }); } catch {}
46
44
 
47
45
  console.error(`mdv: download failed (${String(err)})`);
48
46
 
@@ -66,13 +64,6 @@ function pkgVersion() {
66
64
  }
67
65
  }
68
66
 
69
- function assetName() {
70
- const platform = process.platform;
71
- const arch = process.arch;
72
- const ext = platform === 'win32' ? '.exe' : '';
73
- return `mdv-${platform}-${arch}${ext}`;
74
- }
75
-
76
67
  function download(url, outPath) {
77
68
  return new Promise((resolve, reject) => {
78
69
  const req = https.get(
@@ -102,6 +93,67 @@ function download(url, outPath) {
102
93
  });
103
94
  }
104
95
 
96
+ async function downloadWithFallback(primaryUrl, version, asset, outPath) {
97
+ try {
98
+ await download(primaryUrl, outPath);
99
+ return;
100
+ } catch (primaryErr) {
101
+ const fallbackUrl = await resolveReleaseAssetUrl({
102
+ version,
103
+ asset,
104
+ getRelease: getRelease
105
+ });
106
+
107
+ if (!fallbackUrl || fallbackUrl === primaryUrl) {
108
+ throw primaryErr;
109
+ }
110
+
111
+ console.error(`mdv: fallback download ${fallbackUrl}`);
112
+ await download(fallbackUrl, outPath);
113
+ }
114
+ }
115
+
116
+ async function getRelease(kind) {
117
+ const base = `https://api.github.com/repos/${REPO}/releases`;
118
+ return requestJson(`${base}/${kind}`);
119
+ }
120
+
121
+ function requestJson(url) {
122
+ return new Promise((resolve, reject) => {
123
+ const headers = {
124
+ 'User-Agent': 'mdv-installer',
125
+ Accept: 'application/vnd.github+json'
126
+ };
127
+
128
+ if (process.env.GITHUB_TOKEN) {
129
+ headers.Authorization = `Bearer ${process.env.GITHUB_TOKEN}`;
130
+ }
131
+
132
+ const req = https.get(url, { headers }, (res) => {
133
+ let data = '';
134
+ res.setEncoding('utf8');
135
+ res.on('data', (chunk) => {
136
+ data += chunk;
137
+ });
138
+ res.on('end', () => {
139
+ if ((res.statusCode || 500) >= 400) {
140
+ const err = new Error(`http ${res.statusCode}`);
141
+ err.status = res.statusCode;
142
+ reject(err);
143
+ return;
144
+ }
145
+ try {
146
+ resolve(JSON.parse(data || '{}'));
147
+ } catch (err) {
148
+ reject(err);
149
+ }
150
+ });
151
+ });
152
+
153
+ req.on('error', reject);
154
+ });
155
+ }
156
+
105
157
  function cargoInstallFallback() {
106
158
  const probe = spawnSync('cargo', ['--version'], { stdio: 'ignore' });
107
159
  if (probe.status !== 0) return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhruv2mars/mdv",
3
- "version": "0.0.3",
3
+ "version": "0.0.6",
4
4
  "description": "Terminal-first markdown visualizer/editor",
5
5
  "type": "module",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  "mdv": "node bin/mdv.js",
14
14
  "postinstall": "node bin/install.js",
15
15
  "selftest": "node bin/selftest.js",
16
- "lint": "node --check bin/mdv.js && node --check bin/install.js && node --check bin/selftest.js",
16
+ "lint": "node --check bin/mdv.js && node --check bin/install.js && node --check bin/install-lib.js && node --check bin/selftest.js",
17
17
  "test": "node scripts/test.js"
18
18
  },
19
19
  "keywords": [
@@ -26,7 +26,8 @@
26
26
  "homepage": "https://github.com/Dhruv2mars/mdv#readme",
27
27
  "repository": {
28
28
  "type": "git",
29
- "url": "git+https://github.com/Dhruv2mars/mdv.git"
29
+ "url": "git+https://github.com/Dhruv2mars/mdv.git",
30
+ "directory": "packages/cli"
30
31
  },
31
32
  "bugs": {
32
33
  "url": "https://github.com/Dhruv2mars/mdv/issues"