octwin-cli 0.1.6 → 0.1.8
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/dist/index.js +92 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* tenant. Standalone: no platform checkout, no build step for the developer —
|
|
8
8
|
* `npx octwin-cli <cmd>` (published as `octwin-cli`, command `octwin`).
|
|
9
9
|
*
|
|
10
|
+
* octwin --version | -v # print the CLI version (+ any upgrade notice)
|
|
10
11
|
* octwin init <dir> [--id my-pack] [--description "..."] [--display-name "..."]
|
|
11
12
|
* octwin validate [--dir .] [--remote] # --remote → the platform's FULL schema check, all errors at once
|
|
12
13
|
* octwin login --url <platformUrl> --token oct_…
|
|
@@ -37,6 +38,17 @@ import { validatePackBundle } from './lib/validate.js';
|
|
|
37
38
|
// level under the package root), so `../templates/starter` resolves for the
|
|
38
39
|
// built CLI and `tsx` dev alike.
|
|
39
40
|
const TEMPLATE_DIR = resolve(dirname(fileURLToPath(import.meta.url)), '..', 'templates', 'starter');
|
|
41
|
+
/** This CLI's version — read from its own package.json (one level up from dist/,
|
|
42
|
+
* always shipped in the npm tarball). Falls back to '0.0.0' if unreadable. */
|
|
43
|
+
const VERSION = (() => {
|
|
44
|
+
try {
|
|
45
|
+
const pkg = JSON.parse(readFileSync(resolve(dirname(fileURLToPath(import.meta.url)), '..', 'package.json'), 'utf8'));
|
|
46
|
+
return typeof pkg?.version === 'string' ? pkg.version : '0.0.0';
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return '0.0.0';
|
|
50
|
+
}
|
|
51
|
+
})();
|
|
40
52
|
function parseFlags(argv) {
|
|
41
53
|
const f = { _: [] };
|
|
42
54
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -119,6 +131,78 @@ function writeCreds(map) {
|
|
|
119
131
|
mkdirSync(join(homedir(), '.octwin'), { recursive: true });
|
|
120
132
|
writeFileSync(credsPath(), JSON.stringify(map, null, 2), 'utf8');
|
|
121
133
|
}
|
|
134
|
+
// ── update check (daily, fail-silent, TTY-only) ──────────────────────────────
|
|
135
|
+
function updateCachePath() { return join(homedir(), '.octwin', 'update-check.json'); }
|
|
136
|
+
/** True when semver `a` is strictly greater than `b` (simple x.y.z compare). */
|
|
137
|
+
function isNewer(a, b) {
|
|
138
|
+
const pa = a.split('.').map(n => parseInt(n, 10));
|
|
139
|
+
const pb = b.split('.').map(n => parseInt(n, 10));
|
|
140
|
+
for (let i = 0; i < 3; i++) {
|
|
141
|
+
const x = pa[i] ?? 0, y = pb[i] ?? 0;
|
|
142
|
+
if (Number.isNaN(x) || Number.isNaN(y))
|
|
143
|
+
return false;
|
|
144
|
+
if (x !== y)
|
|
145
|
+
return x > y;
|
|
146
|
+
}
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
/** The latest published `octwin-cli` version, cached for a day. Fail-silent:
|
|
150
|
+
* returns null on any error / offline — a version check must never break a command. */
|
|
151
|
+
async function latestPublishedVersion() {
|
|
152
|
+
const DAY = 24 * 60 * 60 * 1000;
|
|
153
|
+
try {
|
|
154
|
+
const cache = JSON.parse(readFileSync(updateCachePath(), 'utf8'));
|
|
155
|
+
if (cache.latest && typeof cache.checkedAt === 'number' && Date.now() - cache.checkedAt < DAY)
|
|
156
|
+
return cache.latest;
|
|
157
|
+
}
|
|
158
|
+
catch { /* no / stale cache → fetch below */ }
|
|
159
|
+
try {
|
|
160
|
+
const ctrl = new AbortController();
|
|
161
|
+
const timer = setTimeout(() => ctrl.abort(), 1500);
|
|
162
|
+
const res = await fetch('https://registry.npmjs.org/octwin-cli/latest', { signal: ctrl.signal });
|
|
163
|
+
clearTimeout(timer);
|
|
164
|
+
if (!res.ok)
|
|
165
|
+
return null;
|
|
166
|
+
const latest = (await res.json()).version;
|
|
167
|
+
if (typeof latest !== 'string')
|
|
168
|
+
return null;
|
|
169
|
+
try {
|
|
170
|
+
mkdirSync(join(homedir(), '.octwin'), { recursive: true });
|
|
171
|
+
writeFileSync(updateCachePath(), JSON.stringify({ checkedAt: Date.now(), latest }), 'utf8');
|
|
172
|
+
}
|
|
173
|
+
catch { /* cache is best-effort */ }
|
|
174
|
+
return latest;
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
/** True when running via `npx` — the CLI's own file lives in npx's cache dir, or npm
|
|
181
|
+
* ran it as `npm exec`. Under npx there is no persistent install to upgrade
|
|
182
|
+
* (`@latest` already resolves the newest), so an upgrade notice would be
|
|
183
|
+
* misleading — stay silent. The notice is for a GLOBAL install (`npm i -g`). */
|
|
184
|
+
function isNpx() {
|
|
185
|
+
try {
|
|
186
|
+
return fileURLToPath(import.meta.url).includes('_npx') || process.env.npm_command === 'exec';
|
|
187
|
+
}
|
|
188
|
+
catch {
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/** Print a one-line upgrade notice (to stderr) when a newer octwin-cli is published.
|
|
193
|
+
* Skipped when piped/CI (not a TTY) or run via npx (nothing to upgrade). Never throws. */
|
|
194
|
+
async function notifyIfOutdated() {
|
|
195
|
+
if (!process.stdout.isTTY || isNpx())
|
|
196
|
+
return;
|
|
197
|
+
try {
|
|
198
|
+
const latest = await latestPublishedVersion();
|
|
199
|
+
if (latest && isNewer(latest, VERSION)) {
|
|
200
|
+
console.error(`\n⬆ octwin-cli ${latest} is available (you have ${VERSION}).`);
|
|
201
|
+
console.error(' Upgrade: npm i -g octwin-cli@latest (or just use npx octwin-cli@latest)');
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
catch { /* a version check must never break the CLI */ }
|
|
205
|
+
}
|
|
122
206
|
// ── commands ────────────────────────────────────────────────────────────────
|
|
123
207
|
function cmdInit(flags) {
|
|
124
208
|
const target = flags._[0] ?? die('usage: octwin init <dir> [--id my-pack]');
|
|
@@ -643,8 +727,9 @@ async function cmdChat(flags) {
|
|
|
643
727
|
}
|
|
644
728
|
}
|
|
645
729
|
function help() {
|
|
646
|
-
console.log(`octwin — Octwin external-pack developer CLI (by CEQUENS)
|
|
730
|
+
console.log(`octwin ${VERSION} — Octwin external-pack developer CLI (by CEQUENS)
|
|
647
731
|
|
|
732
|
+
octwin --version # print the CLI version (+ any upgrade notice)
|
|
648
733
|
octwin init <dir> [--id my-pack] [--description "..."] [--display-name "..."]
|
|
649
734
|
octwin validate [--dir .] [--remote] # --remote runs the platform's FULL schema check (all errors at once)
|
|
650
735
|
octwin login --url <platformUrl> --token oct_… # a deploy token from the console
|
|
@@ -698,6 +783,11 @@ async function main() {
|
|
|
698
783
|
case 'test':
|
|
699
784
|
await cmdValidate({ ...flags, remote: true });
|
|
700
785
|
break; // A6: `test` = the full remote validate, not a validate-clone
|
|
786
|
+
case '-v':
|
|
787
|
+
case '--version':
|
|
788
|
+
case 'version':
|
|
789
|
+
console.log(`octwin-cli ${VERSION}`);
|
|
790
|
+
break;
|
|
701
791
|
case undefined:
|
|
702
792
|
case 'help':
|
|
703
793
|
case '--help':
|
|
@@ -706,5 +796,6 @@ async function main() {
|
|
|
706
796
|
break;
|
|
707
797
|
default: die(`unknown command '${command}' — run \`octwin help\``);
|
|
708
798
|
}
|
|
799
|
+
await notifyIfOutdated(); // trailing, fail-silent, TTY-only "newer version available" notice
|
|
709
800
|
}
|
|
710
801
|
main().catch((err) => die(err?.message ?? String(err)));
|
package/package.json
CHANGED