atris 3.5.0 → 3.12.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/bin/atris.js +16 -7
- package/commands/align.js +1 -0
- package/commands/autopilot.js +473 -16
- package/commands/brainstorm.js +7 -5
- package/commands/clean.js +19 -3
- package/commands/computer.js +43 -0
- package/commands/integrations.js +14 -9
- package/commands/pull.js +46 -10
- package/commands/push.js +110 -10
- package/commands/workflow.js +24 -9
- package/lib/manifest.js +3 -0
- package/lib/workspace-safety.js +87 -0
- package/package.json +1 -1
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const os = require('os');
|
|
3
|
+
|
|
4
|
+
// Returns a human-readable reason string if `dir` is a path we must never
|
|
5
|
+
// treat as an Atris workspace root (pull/push would walk and mutate it).
|
|
6
|
+
// Returns null if the dir is safe.
|
|
7
|
+
//
|
|
8
|
+
// The real bug this guards against: if outputDir resolves to $HOME, pull's
|
|
9
|
+
// force mirror sweep walks ~/Library, ~/Documents, ~/Downloads, ... and
|
|
10
|
+
// deletes any local file not on cloud. That wipes the user's home dir.
|
|
11
|
+
function dangerousWorkspaceReason(dir) {
|
|
12
|
+
if (!dir) return 'empty path';
|
|
13
|
+
const abs = path.resolve(dir);
|
|
14
|
+
const home = os.homedir();
|
|
15
|
+
const rootParsed = path.parse(abs).root;
|
|
16
|
+
|
|
17
|
+
if (abs === home) return 'your home directory';
|
|
18
|
+
if (abs === rootParsed) return 'the filesystem root';
|
|
19
|
+
if (abs === path.dirname(home)) return `the users root (${path.dirname(home)})`;
|
|
20
|
+
|
|
21
|
+
const systemPaths = [
|
|
22
|
+
'/tmp', '/var', '/etc', '/usr', '/bin', '/sbin', '/opt',
|
|
23
|
+
'/private', '/Library', '/Applications', '/System', '/Volumes',
|
|
24
|
+
'/Users', '/home', '/root',
|
|
25
|
+
];
|
|
26
|
+
for (const p of systemPaths) {
|
|
27
|
+
if (abs === p) return `the system path ${p}`;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Reserved top-level folders inside the user's home — never workspaces.
|
|
31
|
+
const homeReservedNames = new Set([
|
|
32
|
+
'Library', 'Applications', 'Documents', 'Downloads', 'Desktop',
|
|
33
|
+
'Pictures', 'Music', 'Movies', 'Public', 'Sites', 'Dropbox',
|
|
34
|
+
'OneDrive', 'iCloud Drive',
|
|
35
|
+
]);
|
|
36
|
+
if (path.dirname(abs) === home && homeReservedNames.has(path.basename(abs))) {
|
|
37
|
+
return `a reserved home folder (~/${path.basename(abs)})`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Pick a safe fallback directory for a business workspace when the
|
|
44
|
+
// originally-resolved path is dangerous. Prefers cwd/slug, falls back to
|
|
45
|
+
// ~/atris-workspaces/slug if cwd itself is unsafe.
|
|
46
|
+
function safeFallbackDir(slug, cwd) {
|
|
47
|
+
const cwdFallback = path.join(cwd, slug);
|
|
48
|
+
if (!dangerousWorkspaceReason(cwdFallback)) return cwdFallback;
|
|
49
|
+
return path.join(os.homedir(), 'atris-workspaces', slug);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Resolve an outputDir, auto-relocating to a safe fallback if the originally
|
|
53
|
+
// chosen path is dangerous. Non-technical users don't need to know about
|
|
54
|
+
// mkdir/cd — atris picks a safe folder and tells them where it landed.
|
|
55
|
+
function resolveSafeOutputDir(requested, { slug, cwd = process.cwd(), op = 'use' } = {}) {
|
|
56
|
+
const reason = dangerousWorkspaceReason(requested);
|
|
57
|
+
if (!reason) return { dir: path.resolve(requested), relocated: false };
|
|
58
|
+
|
|
59
|
+
const fallback = safeFallbackDir(slug, cwd);
|
|
60
|
+
console.log('');
|
|
61
|
+
console.log(` ${requested} is ${reason} — not safe to ${op}.`);
|
|
62
|
+
console.log(` Using ${fallback} instead.`);
|
|
63
|
+
console.log('');
|
|
64
|
+
return { dir: fallback, relocated: true, originalReason: reason };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Hard-refuse variant — used by push where we can't auto-relocate (the
|
|
68
|
+
// source has to be where the user actually has their files).
|
|
69
|
+
function assertSafeWorkspaceRoot(dir, { slug, op } = {}) {
|
|
70
|
+
const reason = dangerousWorkspaceReason(dir);
|
|
71
|
+
if (!reason) return;
|
|
72
|
+
const label = op || 'operate on';
|
|
73
|
+
console.error('');
|
|
74
|
+
console.error(` Refusing to ${label} ${dir} (${reason}).`);
|
|
75
|
+
console.error('');
|
|
76
|
+
console.error(' Atris would walk this folder and sync files inside it.');
|
|
77
|
+
console.error(' Cd into a dedicated workspace folder first.');
|
|
78
|
+
if (slug) console.error(` For example: mkdir -p ~/code/${slug} && cd ~/code/${slug}`);
|
|
79
|
+
process.exit(1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
module.exports = {
|
|
83
|
+
dangerousWorkspaceReason,
|
|
84
|
+
safeFallbackDir,
|
|
85
|
+
resolveSafeOutputDir,
|
|
86
|
+
assertSafeWorkspaceRoot,
|
|
87
|
+
};
|