octwin-cli 0.1.6 → 0.1.7
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 +81 -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,67 @@ 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
|
+
/** Print a one-line upgrade notice (to stderr) when a newer octwin-cli is published.
|
|
181
|
+
* Skipped when not attached to a TTY (CI / piped) so it never adds noise to scripts.
|
|
182
|
+
* Never throws. */
|
|
183
|
+
async function notifyIfOutdated() {
|
|
184
|
+
if (!process.stdout.isTTY)
|
|
185
|
+
return;
|
|
186
|
+
try {
|
|
187
|
+
const latest = await latestPublishedVersion();
|
|
188
|
+
if (latest && isNewer(latest, VERSION)) {
|
|
189
|
+
console.error(`\n⬆ octwin-cli ${latest} is available (you have ${VERSION}).`);
|
|
190
|
+
console.error(' Upgrade: npm i -g octwin-cli@latest (or just use npx octwin-cli@latest)');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
catch { /* a version check must never break the CLI */ }
|
|
194
|
+
}
|
|
122
195
|
// ── commands ────────────────────────────────────────────────────────────────
|
|
123
196
|
function cmdInit(flags) {
|
|
124
197
|
const target = flags._[0] ?? die('usage: octwin init <dir> [--id my-pack]');
|
|
@@ -643,8 +716,9 @@ async function cmdChat(flags) {
|
|
|
643
716
|
}
|
|
644
717
|
}
|
|
645
718
|
function help() {
|
|
646
|
-
console.log(`octwin — Octwin external-pack developer CLI (by CEQUENS)
|
|
719
|
+
console.log(`octwin ${VERSION} — Octwin external-pack developer CLI (by CEQUENS)
|
|
647
720
|
|
|
721
|
+
octwin --version # print the CLI version (+ any upgrade notice)
|
|
648
722
|
octwin init <dir> [--id my-pack] [--description "..."] [--display-name "..."]
|
|
649
723
|
octwin validate [--dir .] [--remote] # --remote runs the platform's FULL schema check (all errors at once)
|
|
650
724
|
octwin login --url <platformUrl> --token oct_… # a deploy token from the console
|
|
@@ -698,6 +772,11 @@ async function main() {
|
|
|
698
772
|
case 'test':
|
|
699
773
|
await cmdValidate({ ...flags, remote: true });
|
|
700
774
|
break; // A6: `test` = the full remote validate, not a validate-clone
|
|
775
|
+
case '-v':
|
|
776
|
+
case '--version':
|
|
777
|
+
case 'version':
|
|
778
|
+
console.log(`octwin-cli ${VERSION}`);
|
|
779
|
+
break;
|
|
701
780
|
case undefined:
|
|
702
781
|
case 'help':
|
|
703
782
|
case '--help':
|
|
@@ -706,5 +785,6 @@ async function main() {
|
|
|
706
785
|
break;
|
|
707
786
|
default: die(`unknown command '${command}' — run \`octwin help\``);
|
|
708
787
|
}
|
|
788
|
+
await notifyIfOutdated(); // trailing, fail-silent, TTY-only "newer version available" notice
|
|
709
789
|
}
|
|
710
790
|
main().catch((err) => die(err?.message ?? String(err)));
|
package/package.json
CHANGED