skills-atlas-cli 0.8.8 → 0.8.9
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/bin/skills.js +3 -0
- package/package.json +1 -1
- package/src/commands/update.js +4 -1
- package/src/data.js +32 -1
package/bin/skills.js
CHANGED
|
@@ -73,6 +73,9 @@ async function main() {
|
|
|
73
73
|
process.exitCode = 1;
|
|
74
74
|
return;
|
|
75
75
|
}
|
|
76
|
+
// Opportunistic, non-blocking background catalog refresh so new skills appear over
|
|
77
|
+
// time without a manual `update`. Skipped for `update` itself; fully fail-silent.
|
|
78
|
+
if (sub !== 'update') { try { require('../src/data').maybeBackgroundRefresh(); } catch { /* ignore */ } }
|
|
76
79
|
await cmd(rest);
|
|
77
80
|
}
|
|
78
81
|
|
package/package.json
CHANGED
package/src/commands/update.js
CHANGED
|
@@ -6,7 +6,10 @@ const { refreshData, refreshSources } = require('../data');
|
|
|
6
6
|
module.exports = async function update(argv) {
|
|
7
7
|
const { values } = parse(argv, ['json']);
|
|
8
8
|
if (values.help) {
|
|
9
|
-
console.log('usage: skills-atlas update\n\
|
|
9
|
+
console.log('usage: skills-atlas update\n\n' +
|
|
10
|
+
'Refresh the local catalog cache from the public data feed.\n' +
|
|
11
|
+
'The catalog also auto-refreshes in the background (~daily) so new skills appear\n' +
|
|
12
|
+
'on their own; set SKILLS_ATLAS_NO_REFRESH=1 (or SKILLS_ATLAS_OFFLINE=1) to disable.');
|
|
10
13
|
return;
|
|
11
14
|
}
|
|
12
15
|
|
package/src/data.js
CHANGED
|
@@ -93,6 +93,37 @@ function maybeStaleNudge(fromCache) {
|
|
|
93
93
|
process.stderr.write("tip: run 'skills-atlas update' to refresh the catalog\n");
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
+
const REFRESH_AFTER_MS = 24 * 3600000; // auto-refresh once the cache is a day old
|
|
97
|
+
const refreshStampFile = () => path.join(cacheDir(), 'autorefresh.json');
|
|
98
|
+
|
|
99
|
+
// Pure decision: should we kick off a background refresh now? (cache stale/absent,
|
|
100
|
+
// not throttled, not opted out). Injectable for tests.
|
|
101
|
+
function shouldAutoRefresh({ meta, stamp, env, now }) {
|
|
102
|
+
if (env.SKILLS_ATLAS_NO_REFRESH || env.SKILLS_ATLAS_OFFLINE || env.SKILLS_ATLAS_BG_REFRESH) return false;
|
|
103
|
+
const t = meta && meta.fetchedAt ? Date.parse(meta.fetchedAt) : NaN;
|
|
104
|
+
const ageMs = Number.isFinite(t) ? now - t : Infinity; // absent/bad meta → treat as stale
|
|
105
|
+
if (ageMs < REFRESH_AFTER_MS) return false;
|
|
106
|
+
const st = stamp && stamp.at ? Date.parse(stamp.at) : NaN;
|
|
107
|
+
if (Number.isFinite(st) && (now - st) < REFRESH_AFTER_MS) return false; // already tried today
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Fire-and-forget: if the catalog is old (or absent) and we haven't tried today,
|
|
112
|
+
// spawn a DETACHED background `update` so new skills appear next time. Never blocks,
|
|
113
|
+
// never errors out. Opt out with SKILLS_ATLAS_NO_REFRESH / SKILLS_ATLAS_OFFLINE.
|
|
114
|
+
function maybeBackgroundRefresh() {
|
|
115
|
+
try {
|
|
116
|
+
if (!shouldAutoRefresh({ meta: tryReadJSON(metaFile()), stamp: tryReadJSON(refreshStampFile()), env: process.env, now: Date.now() })) return;
|
|
117
|
+
ensureDir(cacheDir());
|
|
118
|
+
fs.writeFileSync(refreshStampFile(), JSON.stringify({ at: new Date().toISOString() })); // stamp first → no double-spawn
|
|
119
|
+
const { spawn } = require('child_process');
|
|
120
|
+
const child = spawn(process.execPath, [path.join(__dirname, '..', 'bin', 'skills.js'), 'update'], {
|
|
121
|
+
detached: true, stdio: 'ignore', env: { ...process.env, SKILLS_ATLAS_BG_REFRESH: '1' },
|
|
122
|
+
});
|
|
123
|
+
child.unref();
|
|
124
|
+
} catch { /* fully fail-silent — never affect the foreground command */ }
|
|
125
|
+
}
|
|
126
|
+
|
|
96
127
|
function loadData({ quiet = false } = {}) {
|
|
97
128
|
const cached = tryReadJSON(cacheFile());
|
|
98
129
|
let base, info;
|
|
@@ -205,4 +236,4 @@ async function refreshSources() {
|
|
|
205
236
|
return out;
|
|
206
237
|
}
|
|
207
238
|
|
|
208
|
-
module.exports = { loadData, refreshData, fetchSource, refreshSources, counts, isValid, cacheDir, PUBLIC_URL };
|
|
239
|
+
module.exports = { loadData, refreshData, fetchSource, refreshSources, counts, isValid, shouldAutoRefresh, maybeBackgroundRefresh, cacheDir, PUBLIC_URL };
|