ezi 1.0.0 → 2.0.1
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/README.md +59 -0
- package/dist/index.js +352 -1
- package/package.json +32 -16
package/README.md
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# ezi — `npx ezi` launcher for ezicode
|
|
2
|
+
|
|
3
|
+
Zero-dependency TypeScript CLI. It detects OS/arch, downloads the matching
|
|
4
|
+
native `ezicode` binary from GitHub Releases on first run, caches it, and
|
|
5
|
+
launches the editor detached. No `npm install` required by users.
|
|
6
|
+
|
|
7
|
+
## Mono-repo layout
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
ezicode/ # Rust workspace (cargo members: app)
|
|
11
|
+
├── app/ # native editor (ezicode binary)
|
|
12
|
+
├── ezi-cli/ # npm launcher (this folder, NOT a cargo member)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Cargo ignores `ezi-cli/` (`members = ["app"]` in root `Cargo.toml:2`), npm
|
|
16
|
+
ignores the Rust side. One repo, two package managers.
|
|
17
|
+
|
|
18
|
+
## Develop
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
cd ezi-cli
|
|
22
|
+
npm install
|
|
23
|
+
npm run build # tsc -> dist/index.js
|
|
24
|
+
node ./dist/index.js --help
|
|
25
|
+
EZI_VERBOSE=1 node ./dist/index.js . # downloads real binary, opens editor
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Publish
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cd ezi-cli
|
|
32
|
+
npm run build
|
|
33
|
+
npm publish # package `ezi`, bin `ezi` -> dist/index.js
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Users then run:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npx -y ezi@latest . # first run downloads ~30-60MB binary to cache, opens editor
|
|
40
|
+
ezi . # after npm i -g ezi
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Version resolution (no republish needed for editor releases):
|
|
44
|
+
|
|
45
|
+
1. `EZI_VERSION=0.1.2` pins that release, no network.
|
|
46
|
+
2. Unset (or `EZI_VERSION=latest`, just `npx ezi`) checks
|
|
47
|
+
`api.github.com/repos/<owner>/<repo>/releases/latest` on every run.
|
|
48
|
+
Same tag reuses the cached binary (no download); new tag downloads once
|
|
49
|
+
to `<cache>/vX.Y.Z/`. Offline / API failure reuses the last-seen tag,
|
|
50
|
+
else the compiled-in default near `app/Cargo.toml`.
|
|
51
|
+
|
|
52
|
+
Only republish `ezi` for launcher bugfixes. Skip the lookup with
|
|
53
|
+
`EZI_NO_UPDATE_CHECK=1`. Optional `EZI_GITHUB_TOKEN` raises API rate limits.
|
|
54
|
+
|
|
55
|
+
## Cache
|
|
56
|
+
|
|
57
|
+
- Linux/macOS: `~/.cache/ezi/v<version>/` (or `$XDG_CACHE_HOME`) + `latest.json` tag cache
|
|
58
|
+
- Windows: `%LOCALAPPDATA%/ezi/cache/v<version>/`
|
|
59
|
+
- Override: `EZI_CACHE`, `EZI_VERSION`, `EZI_REPO`, `EZI_NO_UPDATE_CHECK=1`
|
package/dist/index.js
CHANGED
|
@@ -1 +1,352 @@
|
|
|
1
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
/**
|
|
4
|
+
* ezi — zero-install launcher for the ezicode native editor.
|
|
5
|
+
*
|
|
6
|
+
* Usage:
|
|
7
|
+
* npx ezi [file|dir] [args...] open editor (downloads binary on first run)
|
|
8
|
+
* npx ezi --help show help
|
|
9
|
+
* npx ezi --version launcher + editor version
|
|
10
|
+
*
|
|
11
|
+
* Env overrides:
|
|
12
|
+
* EZI_VERSION pinned version without `v`, `latest`, or unset (default: auto-detect)
|
|
13
|
+
* EZI_REPO `owner/repo` (default: olovalabs/ezicode)
|
|
14
|
+
* EZI_CACHE cache dir override
|
|
15
|
+
* EZI_NO_UPDATE_CHECK set to 1 to skip GitHub lookup, use fallback immediately
|
|
16
|
+
* EZI_GITHUB_TOKEN optional token to raise api.github.com rate limits
|
|
17
|
+
*
|
|
18
|
+
* Design: zero npm dependencies (node builtins only) so the published
|
|
19
|
+
* package stays ~5KB. Platform binaries come from GitHub Releases:
|
|
20
|
+
* linux x64 -> ezicode-x86_64-unknown-linux-gnu.tar.gz
|
|
21
|
+
* mac arm64 -> ezicode-aarch64-apple-darwin.tar.gz
|
|
22
|
+
* win x64 -> ezicode-x86_64-pc-windows-msvc.exe (standalone, no unzip)
|
|
23
|
+
*/
|
|
24
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
27
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
28
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
29
|
+
}
|
|
30
|
+
Object.defineProperty(o, k2, desc);
|
|
31
|
+
}) : (function(o, m, k, k2) {
|
|
32
|
+
if (k2 === undefined) k2 = k;
|
|
33
|
+
o[k2] = m[k];
|
|
34
|
+
}));
|
|
35
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
36
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
37
|
+
}) : function(o, v) {
|
|
38
|
+
o["default"] = v;
|
|
39
|
+
});
|
|
40
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
41
|
+
var ownKeys = function(o) {
|
|
42
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
43
|
+
var ar = [];
|
|
44
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
45
|
+
return ar;
|
|
46
|
+
};
|
|
47
|
+
return ownKeys(o);
|
|
48
|
+
};
|
|
49
|
+
return function (mod) {
|
|
50
|
+
if (mod && mod.__esModule) return mod;
|
|
51
|
+
var result = {};
|
|
52
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
53
|
+
__setModuleDefault(result, mod);
|
|
54
|
+
return result;
|
|
55
|
+
};
|
|
56
|
+
})();
|
|
57
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
58
|
+
const fs = __importStar(require("node:fs"));
|
|
59
|
+
const https = __importStar(require("node:https"));
|
|
60
|
+
const os = __importStar(require("node:os"));
|
|
61
|
+
const path = __importStar(require("node:path"));
|
|
62
|
+
const node_child_process_1 = require("node:child_process");
|
|
63
|
+
const LAUNCHER_VERSION = "2.0.1"; // npm package version
|
|
64
|
+
const FALLBACK_EDITOR_VERSION = "0.1.3"; // used when offline / API fails; keep near app/Cargo.toml
|
|
65
|
+
const REPO = process.env.EZI_REPO || "olovalabs/ezicode";
|
|
66
|
+
function resolveTarget() {
|
|
67
|
+
const platform = process.platform;
|
|
68
|
+
const arch = process.arch;
|
|
69
|
+
if (platform === "linux" && arch === "x64") {
|
|
70
|
+
const t = "x86_64-unknown-linux-gnu";
|
|
71
|
+
return { kind: "targz", asset: `ezicode-${t}.tar.gz`, binRel: `ezicode-${t}/ezicode` };
|
|
72
|
+
}
|
|
73
|
+
if (platform === "darwin" && arch === "arm64") {
|
|
74
|
+
const t = "aarch64-apple-darwin";
|
|
75
|
+
return { kind: "targz", asset: `ezicode-${t}.tar.gz`, binRel: `ezicode-${t}/ezicode` };
|
|
76
|
+
}
|
|
77
|
+
if (platform === "win32" && arch === "x64") {
|
|
78
|
+
// Standalone exe on the release — no zip extraction needed.
|
|
79
|
+
return { kind: "exe", asset: "ezicode-x86_64-pc-windows-msvc.exe" };
|
|
80
|
+
}
|
|
81
|
+
throw new Error(`ezi: unsupported platform ${platform}/${arch}. ` +
|
|
82
|
+
`Prebuilt binaries exist for linux-x64, darwin-arm64, win32-x64 only. ` +
|
|
83
|
+
`Build from source: https://github.com/${REPO}`);
|
|
84
|
+
}
|
|
85
|
+
function baseCacheDir() {
|
|
86
|
+
if (process.env.EZI_CACHE)
|
|
87
|
+
return process.env.EZI_CACHE;
|
|
88
|
+
if (process.platform === "win32") {
|
|
89
|
+
const base = process.env.LOCALAPPDATA || path.join(os.homedir(), "AppData", "Local");
|
|
90
|
+
return path.join(base, "ezi", "cache");
|
|
91
|
+
}
|
|
92
|
+
const xdg = process.env.XDG_CACHE_HOME || path.join(os.homedir(), ".cache");
|
|
93
|
+
return path.join(xdg, "ezi");
|
|
94
|
+
}
|
|
95
|
+
function cacheDirFor(tag) {
|
|
96
|
+
return path.join(baseCacheDir(), tag);
|
|
97
|
+
}
|
|
98
|
+
function latestCacheFile() {
|
|
99
|
+
return path.join(baseCacheDir(), "latest.json");
|
|
100
|
+
}
|
|
101
|
+
function normalizeTag(raw) {
|
|
102
|
+
const t = raw.trim();
|
|
103
|
+
return t.startsWith("v") ? t : `v${t}`;
|
|
104
|
+
}
|
|
105
|
+
function fetchLatestTag(verbose) {
|
|
106
|
+
return new Promise((resolve) => {
|
|
107
|
+
const headers = {
|
|
108
|
+
"User-Agent": "ezi-launcher",
|
|
109
|
+
Accept: "application/vnd.github+json",
|
|
110
|
+
};
|
|
111
|
+
if (process.env.EZI_GITHUB_TOKEN) {
|
|
112
|
+
headers.Authorization = `Bearer ${process.env.EZI_GITHUB_TOKEN}`;
|
|
113
|
+
}
|
|
114
|
+
const req = https.get(`https://api.github.com/repos/${REPO}/releases/latest`, { headers, timeout: 5000 }, (res) => {
|
|
115
|
+
const status = res.statusCode || 0;
|
|
116
|
+
if (status !== 200) {
|
|
117
|
+
if (verbose)
|
|
118
|
+
console.log(`ezi: release lookup failed (http ${status}), using fallback`);
|
|
119
|
+
res.resume();
|
|
120
|
+
resolve(null);
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
let body = "";
|
|
124
|
+
res.setEncoding("utf8");
|
|
125
|
+
res.on("data", (chunk) => {
|
|
126
|
+
body += chunk;
|
|
127
|
+
// Guard against unexpectedly large payloads.
|
|
128
|
+
if (body.length > 256 * 1024) {
|
|
129
|
+
res.destroy();
|
|
130
|
+
resolve(null);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
res.on("end", () => {
|
|
134
|
+
try {
|
|
135
|
+
const json = JSON.parse(body);
|
|
136
|
+
if (typeof json.tag_name === "string" && json.tag_name.trim()) {
|
|
137
|
+
resolve(normalizeTag(json.tag_name));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
resolve(null);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
resolve(null);
|
|
145
|
+
}
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
req.on("timeout", () => {
|
|
149
|
+
if (verbose)
|
|
150
|
+
console.log("ezi: release lookup timed out, using fallback");
|
|
151
|
+
req.destroy();
|
|
152
|
+
resolve(null);
|
|
153
|
+
});
|
|
154
|
+
req.on("error", (err) => {
|
|
155
|
+
if (verbose)
|
|
156
|
+
console.log(`ezi: release lookup error (${err.message}), using fallback`);
|
|
157
|
+
resolve(null);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
function readLastSeenTag(verbose) {
|
|
162
|
+
try {
|
|
163
|
+
const raw = fs.readFileSync(latestCacheFile(), "utf8");
|
|
164
|
+
const cached = JSON.parse(raw);
|
|
165
|
+
if (typeof cached.tag !== "string" || !cached.tag)
|
|
166
|
+
return null;
|
|
167
|
+
if (verbose)
|
|
168
|
+
console.log(`ezi: last seen ${cached.tag}`);
|
|
169
|
+
return cached.tag;
|
|
170
|
+
}
|
|
171
|
+
catch {
|
|
172
|
+
return null;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function writeCachedTag(tag) {
|
|
176
|
+
try {
|
|
177
|
+
fs.mkdirSync(baseCacheDir(), { recursive: true });
|
|
178
|
+
fs.writeFileSync(latestCacheFile(), JSON.stringify({ tag, checkedAt: Date.now() }), "utf8");
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// Cache is best-effort; a read-only homedir must not break launches.
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Resolve which editor release to run:
|
|
186
|
+
* EZI_VERSION=<x.y.z|vX.Y.Z> -> that pin, no network.
|
|
187
|
+
* EZI_VERSION=latest (or unset) -> check GitHub every run; same tag reuses
|
|
188
|
+
* cached binary (no download), new tag downloads once, offline reuses last seen.
|
|
189
|
+
* EZI_NO_UPDATE_CHECK=1 -> skip network, use last seen or fallback.
|
|
190
|
+
*/
|
|
191
|
+
async function resolveTag(verbose) {
|
|
192
|
+
const pinned = (process.env.EZI_VERSION || "").trim();
|
|
193
|
+
if (pinned && pinned.toLowerCase() !== "latest") {
|
|
194
|
+
return normalizeTag(pinned);
|
|
195
|
+
}
|
|
196
|
+
if (process.env.EZI_NO_UPDATE_CHECK === "1") {
|
|
197
|
+
const last = readLastSeenTag(verbose);
|
|
198
|
+
if (last)
|
|
199
|
+
return last;
|
|
200
|
+
if (verbose)
|
|
201
|
+
console.log("ezi: update check disabled, using fallback");
|
|
202
|
+
return `v${FALLBACK_EDITOR_VERSION}`;
|
|
203
|
+
}
|
|
204
|
+
// Always check: cheap API call (~200ms). Same version -> cached binary, no download.
|
|
205
|
+
const latest = await fetchLatestTag(verbose);
|
|
206
|
+
if (latest) {
|
|
207
|
+
const prev = readLastSeenTag(false);
|
|
208
|
+
if (prev !== latest && verbose)
|
|
209
|
+
console.log(`ezi: new release ${latest} (was ${prev || "none"})`);
|
|
210
|
+
else if (verbose)
|
|
211
|
+
console.log(`ezi: latest is ${latest}, reusing cache`);
|
|
212
|
+
writeCachedTag(latest);
|
|
213
|
+
return latest;
|
|
214
|
+
}
|
|
215
|
+
// Offline/API failure: reuse last seen tag so repeat launches keep working.
|
|
216
|
+
const stale = readLastSeenTag(verbose);
|
|
217
|
+
if (stale)
|
|
218
|
+
return stale;
|
|
219
|
+
return `v${FALLBACK_EDITOR_VERSION}`;
|
|
220
|
+
}
|
|
221
|
+
function download(url, dest, redirects = 5) {
|
|
222
|
+
return new Promise((resolve, reject) => {
|
|
223
|
+
const req = https.get(url, { headers: { "User-Agent": "ezi-launcher" } }, (res) => {
|
|
224
|
+
const status = res.statusCode || 0;
|
|
225
|
+
if (status >= 300 && status < 400 && res.headers.location) {
|
|
226
|
+
if (redirects === 0) {
|
|
227
|
+
reject(new Error(`ezi: too many redirects downloading ${url}`));
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
res.resume();
|
|
231
|
+
download(res.headers.location, dest, redirects - 1).then(resolve, reject);
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
234
|
+
if (status !== 200) {
|
|
235
|
+
res.resume();
|
|
236
|
+
reject(new Error(`ezi: download failed (${status}) for ${url}`));
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
const out = fs.createWriteStream(dest);
|
|
240
|
+
res.pipe(out);
|
|
241
|
+
out.on("finish", () => out.close(() => resolve()));
|
|
242
|
+
out.on("error", (err) => {
|
|
243
|
+
fs.rmSync(dest, { force: true });
|
|
244
|
+
reject(err);
|
|
245
|
+
});
|
|
246
|
+
});
|
|
247
|
+
req.on("error", reject);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
function extractTargz(archive, destDir) {
|
|
251
|
+
return new Promise((resolve, reject) => {
|
|
252
|
+
// System tar exists on linux + macOS runners and images. Zero-dep by design.
|
|
253
|
+
(0, node_child_process_1.execFile)("tar", ["-xzf", archive, "-C", destDir], (err, _stdout, stderr) => {
|
|
254
|
+
if (err) {
|
|
255
|
+
reject(new Error(`ezi: failed to extract ${archive}: ${stderr || err.message}`));
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
resolve();
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
async function ensureBinary(tag, verbose) {
|
|
263
|
+
const target = resolveTarget();
|
|
264
|
+
const dir = cacheDirFor(tag);
|
|
265
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
266
|
+
if (target.kind === "exe") {
|
|
267
|
+
const bin = path.join(dir, "ezicode.exe");
|
|
268
|
+
if (fs.existsSync(bin))
|
|
269
|
+
return bin;
|
|
270
|
+
const url = `https://github.com/${REPO}/releases/download/${tag}/${target.asset}`;
|
|
271
|
+
const tmp = bin + ".download";
|
|
272
|
+
if (verbose)
|
|
273
|
+
console.log(`ezi: downloading ${url}`);
|
|
274
|
+
await download(url, tmp);
|
|
275
|
+
fs.renameSync(tmp, bin);
|
|
276
|
+
return bin;
|
|
277
|
+
}
|
|
278
|
+
const bin = path.join(dir, target.binRel);
|
|
279
|
+
if (fs.existsSync(bin)) {
|
|
280
|
+
fs.chmodSync(bin, 0o755);
|
|
281
|
+
return bin;
|
|
282
|
+
}
|
|
283
|
+
const url = `https://github.com/${REPO}/releases/download/${tag}/${target.asset}`;
|
|
284
|
+
const archive = path.join(dir, target.asset);
|
|
285
|
+
if (!fs.existsSync(archive)) {
|
|
286
|
+
if (verbose)
|
|
287
|
+
console.log(`ezi: downloading ${url}`);
|
|
288
|
+
await download(url, archive);
|
|
289
|
+
}
|
|
290
|
+
if (verbose)
|
|
291
|
+
console.log(`ezi: extracting ${target.asset}`);
|
|
292
|
+
await extractTargz(archive, dir);
|
|
293
|
+
if (!fs.existsSync(bin))
|
|
294
|
+
throw new Error(`ezi: binary not found after extract: ${bin}`);
|
|
295
|
+
fs.chmodSync(bin, 0o755);
|
|
296
|
+
return bin;
|
|
297
|
+
}
|
|
298
|
+
function printHelp(fallbackTag) {
|
|
299
|
+
console.log(`ezi ${LAUNCHER_VERSION} — launcher for ezicode (https://github.com/${REPO})
|
|
300
|
+
|
|
301
|
+
Usage:
|
|
302
|
+
ezi [file|dir] [editor-args...] open in ezicode (downloads binary first run)
|
|
303
|
+
ezi --help this help
|
|
304
|
+
ezi --version launcher version
|
|
305
|
+
ezi --where print cached binary path
|
|
306
|
+
ezi --clean remove cached binaries
|
|
307
|
+
|
|
308
|
+
Env:
|
|
309
|
+
EZI_VERSION pin release (e.g. 0.1.3), "latest", or unset for auto-detect (default ${fallbackTag})
|
|
310
|
+
EZI_REPO owner/repo (default ${REPO})
|
|
311
|
+
EZI_CACHE cache dir override
|
|
312
|
+
EZI_NO_UPDATE_CHECK=1 skip GitHub lookup, use cache/fallback
|
|
313
|
+
`);
|
|
314
|
+
}
|
|
315
|
+
async function main() {
|
|
316
|
+
const args = process.argv.slice(2);
|
|
317
|
+
const verbose = args.includes("--verbose") || !!process.env.EZI_VERBOSE;
|
|
318
|
+
const passthrough = args.filter((a) => a !== "--verbose");
|
|
319
|
+
if (passthrough.includes("--help") || passthrough.includes("-h")) {
|
|
320
|
+
printHelp(`v${FALLBACK_EDITOR_VERSION}`);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const tag = await resolveTag(verbose);
|
|
324
|
+
if (passthrough.includes("--version") || passthrough.includes("-V")) {
|
|
325
|
+
console.log(`ezi ${LAUNCHER_VERSION} (editor ${tag} @ ${REPO})`);
|
|
326
|
+
return;
|
|
327
|
+
}
|
|
328
|
+
if (passthrough.includes("--clean")) {
|
|
329
|
+
fs.rmSync(baseCacheDir(), { recursive: true, force: true });
|
|
330
|
+
console.log("ezi: cache cleared");
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const bin = await ensureBinary(tag, verbose);
|
|
334
|
+
if (passthrough.includes("--where")) {
|
|
335
|
+
console.log(bin);
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
// Launch detached so `npx ezi` returns immediately while the GUI stays open.
|
|
339
|
+
// stdio ignored: the editor owns its own window, not the terminal.
|
|
340
|
+
const child = (0, node_child_process_1.spawn)(bin, passthrough, {
|
|
341
|
+
detached: true,
|
|
342
|
+
stdio: "ignore",
|
|
343
|
+
windowsHide: true,
|
|
344
|
+
});
|
|
345
|
+
child.unref();
|
|
346
|
+
if (verbose)
|
|
347
|
+
console.log(`ezi: launched ${bin}`);
|
|
348
|
+
}
|
|
349
|
+
main().catch((err) => {
|
|
350
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
351
|
+
process.exit(1);
|
|
352
|
+
});
|
package/package.json
CHANGED
|
@@ -1,16 +1,32 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "ezi",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "ezi",
|
|
3
|
+
"version": "2.0.1",
|
|
4
|
+
"description": "Launch ezicode editor with npx — zero-install native binary launcher",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/olovalabs/ezicode.git",
|
|
9
|
+
"directory": "ezi-cli"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/olovalabs/ezicode",
|
|
12
|
+
"keywords": ["ezicode", "ezi", "editor", "ide", "cli", "launcher"],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=18"
|
|
15
|
+
},
|
|
16
|
+
"bin": {
|
|
17
|
+
"ezi": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"files": ["dist/"],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "tsc",
|
|
22
|
+
"dev": "tsc --watch",
|
|
23
|
+
"start": "node ./dist/index.js",
|
|
24
|
+
"prepublishOnly": "npm run build",
|
|
25
|
+
"typecheck": "tsc --noEmit"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^22.7.0",
|
|
30
|
+
"typescript": "^5.6.0"
|
|
31
|
+
}
|
|
32
|
+
}
|