jops-core 1.0.14 → 1.0.15

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.
Files changed (3) hide show
  1. package/README.md +2 -0
  2. package/bin/init.js +76 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -560,6 +560,8 @@ t.terminate();
560
560
 
561
561
  `init` and `update` accept `--cordova`, `--capacitor` or `--web` to override the detected project type.
562
562
 
563
+ After each command the CLI checks npm for a newer jops-core and prints a notice if one is available (at most 1.5 s, silent when offline). `build` also warns if `lib/jops-core.min.js` doesn't match the installed version. Turn the check off with `--no-update-check` or `JOPS_NO_UPDATE_CHECK=1`; it is skipped automatically when `CI` is set.
564
+
563
565
  ---
564
566
 
565
567
  ## Source & Contributing
package/bin/init.js CHANGED
@@ -1,5 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from "fs";
3
+ import https from "https";
3
4
  import path from "path";
4
5
  import readline from "readline";
5
6
  import { fileURLToPath } from "url";
@@ -14,10 +15,64 @@ if (command !== "init" && command !== "build" && command !== "update") {
14
15
  console.log("");
15
16
  console.log("Options (init, update):");
16
17
  console.log(" --cordova | --capacitor | --web override the detected project type");
18
+ console.log("Options (all commands):");
19
+ console.log(" --no-update-check skip the check for a newer jops-core version");
17
20
  process.exit(0);
18
21
  }
19
22
 
20
23
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
24
+ const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf8"));
25
+
26
+ // ─── update check ────────────────────────────────────────────────────────────
27
+ // Started now, awaited at the end, so it runs in parallel with the command.
28
+ // Any failure (offline, timeout, Node without fetch) prints nothing.
29
+
30
+ const skipUpdateCheck =
31
+ process.env.CI ||
32
+ process.env.JOPS_NO_UPDATE_CHECK ||
33
+ process.env.NO_UPDATE_NOTIFIER ||
34
+ flags.includes("--no-update-check");
35
+
36
+ // https.get rather than fetch: destroying the request closes the socket at once,
37
+ // whereas an aborted fetch keeps the process alive until its 10 s connect timeout.
38
+ function fetchLatestVersion() {
39
+ return new Promise((resolve) => {
40
+ const req = https.get("https://registry.npmjs.org/jops-core/latest", (res) => {
41
+ if (res.statusCode !== 200) {
42
+ clearTimeout(timer);
43
+ res.resume();
44
+ return resolve(null);
45
+ }
46
+ let body = "";
47
+ res.setEncoding("utf8");
48
+ res.on("data", (chunk) => (body += chunk));
49
+ res.on("end", () => {
50
+ clearTimeout(timer);
51
+ try {
52
+ resolve(JSON.parse(body).version ?? null);
53
+ } catch {
54
+ resolve(null);
55
+ }
56
+ });
57
+ });
58
+ const timer = setTimeout(() => req.destroy(), 1500);
59
+ req.on("error", () => {
60
+ clearTimeout(timer);
61
+ resolve(null);
62
+ });
63
+ });
64
+ }
65
+
66
+ const latestVersion = skipUpdateCheck ? Promise.resolve(null) : fetchLatestVersion();
67
+
68
+ function isNewer(a, b) {
69
+ const pa = a.split(".").map(Number);
70
+ const pb = b.split(".").map(Number);
71
+ for (let i = 0; i < 3; i++) {
72
+ if ((pa[i] || 0) !== (pb[i] || 0)) return (pa[i] || 0) > (pb[i] || 0);
73
+ }
74
+ return false;
75
+ }
21
76
 
22
77
  // ─── project detection ───────────────────────────────────────────────────────
23
78
  // projectRoot: package.json, .vscode/ webRoot: index.html, lib/, src/
@@ -413,7 +468,6 @@ if (command === "update") {
413
468
 
414
469
  fs.copyFileSync(vendorSrc, vendorDest);
415
470
 
416
- const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "../package.json"), "utf8"));
417
471
  console.log(`[jops-core] Updated ${rel(vendorDest)} to v${pkg.version}`);
418
472
  }
419
473
 
@@ -446,8 +500,29 @@ if (command === "build") {
446
500
  }
447
501
  }
448
502
 
503
+ const vendored = path.join(webRoot, "lib", "jops-core.min.js");
504
+ const installed = path.join(__dirname, "../lib/jops-core.min.js");
505
+ if (fs.existsSync(vendored) && !fs.readFileSync(vendored).equals(fs.readFileSync(installed))) {
506
+ console.warn(`[jops-core] ${rel(vendored)} differs from the installed v${pkg.version} — run \`npx jops-core update\` before building.`);
507
+ }
508
+
449
509
  const distDir = path.join(webRoot, "dist");
450
510
  if (fs.existsSync(distDir)) fs.rmSync(distDir, { recursive: true, force: true });
451
511
  buildCopyDir(webRoot, distDir);
452
512
  console.log("[jops-core] Built → dist/");
453
513
  }
514
+
515
+ // ─── update notice ───────────────────────────────────────────────────────────
516
+
517
+ const latest = await latestVersion;
518
+ if (latest && isNewer(latest, pkg.version)) {
519
+ console.log("");
520
+ if (command === "update") {
521
+ console.log(`[jops-core] Copied v${pkg.version} from node_modules, but v${latest} is available.`);
522
+ console.log(" Run `npm i jops-core@latest` first, then `npx jops-core update` again.");
523
+ } else {
524
+ console.log(`[jops-core] Update available: ${pkg.version} → ${latest}`);
525
+ console.log(" npm i jops-core@latest && npx jops-core update");
526
+ }
527
+ console.log(" What's new: https://github.com/uidb-dev/jops-core/blob/main/CHANGELOG.md");
528
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jops-core",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "description": "A no-bundler, OOP-first SPA framework with Android-style view composition",
5
5
  "type": "module",
6
6
  "exports": "./lib/jops-core.min.js",