quizmill 0.2.6 → 0.2.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.
Files changed (2) hide show
  1. package/bin/quizmill.js +54 -29
  2. package/package.json +1 -1
package/bin/quizmill.js CHANGED
@@ -24,6 +24,10 @@ const ENGINE_REPO = 'https://github.com/quizmill/quizmill.git';
24
24
  const HOME = process.env.QUIZMILL_HOME || path.join(os.homedir(), '.quizmill');
25
25
  const ENGINE = process.env.QUIZMILL_ENGINE || path.join(HOME, 'engine');
26
26
  const CLI_VERSION = require('../package.json').version;
27
+ // The engine ref this CLI builds with: its own release tag, so the CLI and
28
+ // engine stay in lockstep (a dev build — the 0.0.0-dev sentinel — tracks main).
29
+ const ENGINE_REF = CLI_VERSION === '0.0.0-dev' ? 'main' : `v${CLI_VERSION}`;
30
+ const REF_MARKER = path.join(ENGINE, '.quizmill-engine-ref');
27
31
 
28
32
  const log = (s) => console.log(s);
29
33
  const die = (s) => {
@@ -35,14 +39,45 @@ function run(cmd, args, opts = {}) {
35
39
  execFileSync(cmd, args, { stdio: 'inherit', ...opts });
36
40
  }
37
41
 
42
+ /** Fetch a ref (tag or branch) into the cache and hard-reset onto it. */
43
+ function fetchRef(ref) {
44
+ run('git', ['fetch', '--depth', '1', 'origin', ref], { cwd: ENGINE });
45
+ run('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: ENGINE });
46
+ fs.writeFileSync(REF_MARKER, ref);
47
+ // package.json can differ between versions — force a clean reinstall.
48
+ fs.rmSync(path.join(ENGINE, 'node_modules'), { recursive: true, force: true });
49
+ }
50
+
38
51
  function ensureEngine() {
39
52
  if (!fs.existsSync(path.join(ENGINE, 'package.json'))) {
40
- log(`… first run: fetching the quizmill engine into ${ENGINE}`);
53
+ log(`… fetching the quizmill engine (${ENGINE_REF}) into ${ENGINE}`);
41
54
  fs.mkdirSync(path.dirname(ENGINE), { recursive: true });
42
- run('git', ['clone', '--depth', '1', ENGINE_REPO, ENGINE]);
55
+ try {
56
+ run('git', ['clone', '--depth', '1', '--branch', ENGINE_REF, ENGINE_REPO, ENGINE]);
57
+ fs.writeFileSync(REF_MARKER, ENGINE_REF);
58
+ } catch {
59
+ // The tag may not be published yet (a just-released CLI) — use main.
60
+ fs.rmSync(ENGINE, { recursive: true, force: true });
61
+ run('git', ['clone', '--depth', '1', '--branch', 'main', ENGINE_REPO, ENGINE]);
62
+ fs.writeFileSync(REF_MARKER, 'main');
63
+ }
64
+ } else if (!process.env.QUIZMILL_ENGINE) {
65
+ // Keep the cached engine in lockstep with this CLI version — so
66
+ // `npx quizmill@latest build` always uses the matching engine.
67
+ const current = fs.existsSync(REF_MARKER)
68
+ ? fs.readFileSync(REF_MARKER, 'utf8').trim()
69
+ : '';
70
+ if (current !== ENGINE_REF) {
71
+ log(`… aligning engine to ${ENGINE_REF}`);
72
+ try {
73
+ fetchRef(ENGINE_REF);
74
+ } catch {
75
+ log(' (offline or ref missing — using the cached engine as-is)');
76
+ }
77
+ }
43
78
  }
44
79
  if (!fs.existsSync(path.join(ENGINE, 'node_modules'))) {
45
- log('… installing engine dependencies (first run only)');
80
+ log('… installing engine dependencies');
46
81
  run('npm', ['install', '--no-fund', '--no-audit'], { cwd: ENGINE });
47
82
  }
48
83
  }
@@ -58,12 +93,11 @@ function engineSha() {
58
93
  function engineNpm(args) {
59
94
  ensureEngine();
60
95
  const env = { ...process.env };
61
- // The cached engine is a shallow, tagless clone, so its own
62
- // `git describe` can't resolve a release tag the in-app version would
63
- // fall back to the 0.0.0-dev sentinel. Stamp the build with the CLI's
64
- // version instead (the CLI is published in lockstep with the engine).
65
- // Skipped when QUIZMILL_ENGINE points at a real checkout (let its git
66
- // tags win) or when the caller set the version explicitly.
96
+ // Stamp the build with the CLI version, which always matches the pinned
97
+ // engine ref robust even if the cache fell back to main (no tag, so the
98
+ // engine's own git-describe would land on the 0.0.0-dev sentinel).
99
+ // Skipped under QUIZMILL_ENGINE (let a real checkout's git tags win) or
100
+ // when the caller set the version explicitly.
67
101
  if (!process.env.QUIZMILL_ENGINE && !env.NEXT_PUBLIC_APP_VERSION) {
68
102
  env.NEXT_PUBLIC_APP_VERSION = CLI_VERSION;
69
103
  }
@@ -170,28 +204,19 @@ function cmdValidate(arg) {
170
204
  }
171
205
 
172
206
  function cmdUpgrade() {
173
- ensureEngine();
174
207
  if (process.env.QUIZMILL_ENGINE) {
175
- log('QUIZMILL_ENGINE points at your own checkout — its update is up to you.');
176
- } else {
177
- const before = engineSha();
178
- try {
179
- // The cache is a depth-1 shallow clone, so `git pull --ff-only` can't
180
- // fast-forward across the grafted history once main advances. Fetch
181
- // the latest main and hard-reset onto it — the cache holds no local
182
- // commits worth keeping (gitignored content/ and out/ are untouched).
183
- run('git', ['fetch', '--depth', '1', 'origin', 'main'], { cwd: ENGINE });
184
- run('git', ['reset', '--hard', 'FETCH_HEAD'], { cwd: ENGINE });
185
- } catch {
186
- log('… update failed — re-cloning the engine fresh');
187
- fs.rmSync(ENGINE, { recursive: true, force: true });
188
- ensureEngine();
189
- }
190
- const after = engineSha();
191
- log(before === after ? `engine already current (${after})` : `engine ${before} → ${after}`);
208
+ ensureEngine();
209
+ log(`✓ quizmill ${CLI_VERSION} using QUIZMILL_ENGINE (${engineSha()})`);
210
+ return;
192
211
  }
193
- run('npm', ['install', '--no-fund', '--no-audit'], { cwd: ENGINE });
194
- log(`✓ quizmill ${CLI_VERSION} ready engine deps installed`);
212
+ // Force a re-align to this CLI's engine ref (blank the marker so
213
+ // ensureEngine re-fetches even if it thinks it's already current).
214
+ const before = engineSha();
215
+ if (fs.existsSync(REF_MARKER)) fs.writeFileSync(REF_MARKER, '');
216
+ ensureEngine();
217
+ const after = engineSha();
218
+ log(before === after ? `engine already current (${after})` : `engine ${before} → ${after}`);
219
+ log(`✓ quizmill ${CLI_VERSION} — engine at ${ENGINE_REF}`);
195
220
  }
196
221
 
197
222
  const HELP = `quizmill — the mill that grinds questions into knowledge
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quizmill",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "description": "Turn a folder of JSON into an installable, offline-first practice app. The mill that grinds questions into knowledge.",
5
5
  "bin": {
6
6
  "quizmill": "bin/quizmill.js"