atris 3.25.2 → 3.27.0
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 +2 -0
- package/bin/atris.js +56 -13
- package/commands/activate.js +24 -0
- package/commands/brain.js +4 -2
- package/commands/card.js +121 -0
- package/commands/clarity.js +125 -0
- package/commands/deck.js +184 -0
- package/commands/moves.js +156 -0
- package/commands/reel.js +128 -0
- package/commands/run.js +34 -1
- package/commands/signup.js +101 -0
- package/commands/site.js +48 -0
- package/commands/slop.js +307 -0
- package/commands/task.js +23 -5
- package/commands/theme.js +217 -0
- package/lib/card.js +120 -0
- package/lib/clarity.js +97 -0
- package/lib/deck-from-md.js +110 -0
- package/lib/html-render.js +257 -0
- package/lib/memory-view.js +95 -0
- package/lib/next-moves.js +362 -0
- package/lib/reel.js +52 -0
- package/lib/site.js +114 -0
- package/lib/slides-deck.js +237 -0
- package/lib/task-proof.js +35 -0
- package/lib/theme.js +264 -0
- package/package.json +1 -1
- package/utils/update-check.js +77 -24
package/utils/update-check.js
CHANGED
|
@@ -2,7 +2,7 @@ const https = require('https');
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
|
-
const { spawnSync } = require('child_process');
|
|
5
|
+
const { spawn, spawnSync } = require('child_process');
|
|
6
6
|
|
|
7
7
|
const PACKAGE_NAME = 'atris';
|
|
8
8
|
const CHECK_INTERVAL_MS = 60 * 60 * 1000; // 1 hour
|
|
@@ -34,6 +34,8 @@ function getCacheData() {
|
|
|
34
34
|
return {
|
|
35
35
|
lastCheck: data.lastCheck ? new Date(data.lastCheck) : null,
|
|
36
36
|
latestVersion: data.latestVersion || null,
|
|
37
|
+
lastAutoUpdate: data.lastAutoUpdate ? new Date(data.lastAutoUpdate) : null,
|
|
38
|
+
lastAutoUpdateVersion: data.lastAutoUpdateVersion || null,
|
|
37
39
|
};
|
|
38
40
|
}
|
|
39
41
|
} catch (error) {
|
|
@@ -52,7 +54,11 @@ function saveCacheData(latestVersion) {
|
|
|
52
54
|
if (!fs.existsSync(ATRIS_DIR)) {
|
|
53
55
|
fs.mkdirSync(ATRIS_DIR, { recursive: true });
|
|
54
56
|
}
|
|
57
|
+
const existing = fs.existsSync(CACHE_FILE)
|
|
58
|
+
? JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'))
|
|
59
|
+
: {};
|
|
55
60
|
const data = {
|
|
61
|
+
...existing,
|
|
56
62
|
lastCheck: new Date().toISOString(),
|
|
57
63
|
latestVersion: latestVersion,
|
|
58
64
|
};
|
|
@@ -62,6 +68,34 @@ function saveCacheData(latestVersion) {
|
|
|
62
68
|
}
|
|
63
69
|
}
|
|
64
70
|
|
|
71
|
+
function markAutoUpdateStarted(latestVersion) {
|
|
72
|
+
try {
|
|
73
|
+
if (!fs.existsSync(ATRIS_DIR)) {
|
|
74
|
+
fs.mkdirSync(ATRIS_DIR, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
const existing = fs.existsSync(CACHE_FILE)
|
|
77
|
+
? JSON.parse(fs.readFileSync(CACHE_FILE, 'utf8'))
|
|
78
|
+
: {};
|
|
79
|
+
fs.writeFileSync(CACHE_FILE, JSON.stringify({
|
|
80
|
+
...existing,
|
|
81
|
+
lastAutoUpdate: new Date().toISOString(),
|
|
82
|
+
lastAutoUpdateVersion: latestVersion,
|
|
83
|
+
}, null, 2));
|
|
84
|
+
} catch (error) {
|
|
85
|
+
// Ignore cache write errors
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function autoUpdateRecentlyStarted(latestVersion, now = new Date()) {
|
|
90
|
+
const cache = getCacheData();
|
|
91
|
+
return Boolean(
|
|
92
|
+
latestVersion &&
|
|
93
|
+
cache.lastAutoUpdate &&
|
|
94
|
+
cache.lastAutoUpdateVersion === latestVersion &&
|
|
95
|
+
now - cache.lastAutoUpdate < CHECK_INTERVAL_MS
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
65
99
|
/**
|
|
66
100
|
* Fetch the latest version of atris from npm registry.
|
|
67
101
|
* @returns {Promise<string>} Latest version string
|
|
@@ -189,7 +223,7 @@ function showUpdateNotification(updateInfo) {
|
|
|
189
223
|
// Single yellow warning line — non-intrusive
|
|
190
224
|
const yellow = '\x1b[33m';
|
|
191
225
|
const reset = '\x1b[0m';
|
|
192
|
-
console.log(`${yellow}Update available: ${updateInfo.installed} → ${updateInfo.latest}. Run:
|
|
226
|
+
console.log(`${yellow}Update available: ${updateInfo.installed} → ${updateInfo.latest}. Run: atris upgrade${reset}`);
|
|
193
227
|
}
|
|
194
228
|
|
|
195
229
|
function inspectInstallGitState(packageRoot = path.join(__dirname, '..')) {
|
|
@@ -237,37 +271,55 @@ function formatInstallGitWarning(state) {
|
|
|
237
271
|
if (state.detached) flags.push(`detached HEAD${state.head ? ` ${state.head}` : ''}`);
|
|
238
272
|
if (state.dirty) flags.push(`dirty worktree (${state.dirtyCount} file${state.dirtyCount === 1 ? '' : 's'})`);
|
|
239
273
|
return `WARNING: Atris is running from a ${flags.join(' + ')} at ${state.root}.\n` +
|
|
240
|
-
'npm
|
|
274
|
+
'npm install -g atris@latest may not change the code currently on PATH; resolve that checkout before trusting upgrade status.';
|
|
241
275
|
}
|
|
242
276
|
|
|
243
|
-
function
|
|
277
|
+
function normalizeAutoUpdateMode(env = process.env) {
|
|
278
|
+
const raw = String(env.ATRIS_AUTO_UPDATE || '').trim().toLowerCase();
|
|
279
|
+
if (['0', 'false', 'no', 'off', 'notify'].includes(raw)) return 'off';
|
|
280
|
+
if (['1', 'true', 'yes', 'on', 'force'].includes(raw)) return 'force';
|
|
281
|
+
return 'auto';
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function shouldAutoUpdate(updateInfo, state, env = process.env) {
|
|
244
285
|
if (!updateInfo || !updateInfo.needsUpdate) return false;
|
|
245
286
|
|
|
246
|
-
const
|
|
287
|
+
const mode = normalizeAutoUpdateMode(env);
|
|
288
|
+
if (mode === 'off') return false;
|
|
289
|
+
if (mode === 'force') return true;
|
|
247
290
|
|
|
248
|
-
|
|
249
|
-
|
|
291
|
+
// Packaged npm installs are not git repositories. Git checkouts may be linked
|
|
292
|
+
// dev installs, where a global npm install would not update the code on PATH.
|
|
293
|
+
return !(state && state.isGitRepo);
|
|
294
|
+
}
|
|
250
295
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
} catch (e) {
|
|
262
|
-
// Sync failed — not critical
|
|
263
|
-
}
|
|
296
|
+
function autoUpdate(updateInfo, options = {}) {
|
|
297
|
+
if (!updateInfo || !updateInfo.needsUpdate) return false;
|
|
298
|
+
|
|
299
|
+
const env = options.env || process.env;
|
|
300
|
+
const packageRoot = options.packageRoot || path.join(__dirname, '..');
|
|
301
|
+
const installState = options.installState || inspectInstallGitState(packageRoot);
|
|
302
|
+
if (!shouldAutoUpdate(updateInfo, installState, env)) return false;
|
|
303
|
+
|
|
304
|
+
const recentlyStarted = options.recentlyStarted || autoUpdateRecentlyStarted;
|
|
305
|
+
if (recentlyStarted(updateInfo.latest)) return false;
|
|
264
306
|
|
|
265
|
-
|
|
307
|
+
const spawnImpl = options.spawn || spawn;
|
|
308
|
+
const markStarted = options.markStarted || markAutoUpdateStarted;
|
|
309
|
+
const log = options.log || console.log;
|
|
310
|
+
|
|
311
|
+
try {
|
|
312
|
+
const child = spawnImpl('npm', ['install', '-g', `${PACKAGE_NAME}@latest`], {
|
|
313
|
+
detached: true,
|
|
314
|
+
stdio: 'ignore',
|
|
315
|
+
windowsHide: true,
|
|
316
|
+
});
|
|
317
|
+
if (child && typeof child.on === 'function') child.on('error', () => {});
|
|
318
|
+
if (child && typeof child.unref === 'function') child.unref();
|
|
319
|
+
markStarted(updateInfo.latest);
|
|
320
|
+
log(`Auto-update started: atris ${updateInfo.installed} -> ${updateInfo.latest} (background)`);
|
|
266
321
|
return true;
|
|
267
322
|
} catch (error) {
|
|
268
|
-
// npm update failed (permissions, network, etc) — fall back to notification
|
|
269
|
-
console.log(`⚠️ Auto-update failed. Run manually: npm update -g atris`);
|
|
270
|
-
console.log('');
|
|
271
323
|
return false;
|
|
272
324
|
}
|
|
273
325
|
}
|
|
@@ -276,6 +328,7 @@ module.exports = {
|
|
|
276
328
|
checkForUpdates,
|
|
277
329
|
showUpdateNotification,
|
|
278
330
|
autoUpdate,
|
|
331
|
+
shouldAutoUpdate,
|
|
279
332
|
inspectInstallGitState,
|
|
280
333
|
formatInstallGitWarning,
|
|
281
334
|
};
|