@rigstate/cli 0.7.34 → 0.7.36
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/dist/index.cjs +4220 -9314
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +4192 -9314
- package/dist/index.js.map +1 -1
- package/package.json +5 -4
- package/src/commands/env.ts +3 -6
- package/src/commands/focus.ts +3 -6
- package/src/commands/genesis.ts +305 -0
- package/src/commands/init.ts +4 -5
- package/src/commands/link.ts +25 -19
- package/src/commands/plan.ts +22 -5
- package/src/commands/sync.ts +7 -12
- package/src/commands/watch.ts +3 -7
- package/src/index.ts +8 -0
- package/src/utils/config.ts +79 -4
- package/src/utils/manifest.ts +62 -5
package/src/utils/config.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import Conf from 'conf';
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
import chalk from 'chalk';
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
4
6
|
|
|
5
7
|
interface RigstateConfig {
|
|
6
8
|
apiKey?: string;
|
|
@@ -20,6 +22,29 @@ const config = new Conf<RigstateConfig>({
|
|
|
20
22
|
* @throws {Error} If no API key is found (user not logged in)
|
|
21
23
|
*/
|
|
22
24
|
export function getApiKey(): string {
|
|
25
|
+
// 1. Check local manifest first (Folder Affinity)
|
|
26
|
+
try {
|
|
27
|
+
const cwd = process.cwd();
|
|
28
|
+
const manifestPaths = [
|
|
29
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
30
|
+
path.join(cwd, '.rigstate')
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
for (const manifestPath of manifestPaths) {
|
|
34
|
+
if (fs.existsSync(manifestPath) && fs.statSync(manifestPath).isFile()) {
|
|
35
|
+
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
36
|
+
const manifest = JSON.parse(content);
|
|
37
|
+
if (manifest.api_key) return manifest.api_key;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch (e) { /* Fallback */ }
|
|
41
|
+
|
|
42
|
+
// 2. Check environment variable
|
|
43
|
+
if (process.env.RIGSTATE_API_KEY) {
|
|
44
|
+
return process.env.RIGSTATE_API_KEY;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// 3. Fall back to global config
|
|
23
48
|
const apiKey = config.get('apiKey');
|
|
24
49
|
if (!apiKey) {
|
|
25
50
|
throw new Error(
|
|
@@ -40,7 +65,40 @@ export function setApiKey(key: string): void {
|
|
|
40
65
|
* Get the default project ID (if set)
|
|
41
66
|
*/
|
|
42
67
|
export function getProjectId(): string | undefined {
|
|
43
|
-
|
|
68
|
+
// 1. Check local manifest first (Folder Affinity)
|
|
69
|
+
try {
|
|
70
|
+
const cwd = process.cwd();
|
|
71
|
+
const manifestPaths = [
|
|
72
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
73
|
+
path.join(cwd, '.rigstate')
|
|
74
|
+
];
|
|
75
|
+
|
|
76
|
+
for (const manifestPath of manifestPaths) {
|
|
77
|
+
if (fs.existsSync(manifestPath) && fs.statSync(manifestPath).isFile()) {
|
|
78
|
+
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
79
|
+
const manifest = JSON.parse(content);
|
|
80
|
+
if (manifest.project_id) {
|
|
81
|
+
console.log(chalk.dim(` [Auth] Context: Project ID ${manifest.project_id.substring(0, 8)}... (from ${path.basename(manifestPath)})`));
|
|
82
|
+
return manifest.project_id;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
} catch (e: any) {
|
|
87
|
+
console.log(chalk.red(` [Error] Failed to read context: ${e.message}`));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// 2. Check environment variable
|
|
91
|
+
if (process.env.RIGSTATE_PROJECT_ID) {
|
|
92
|
+
console.log(chalk.dim(` [Auth] Context: Project ID ${process.env.RIGSTATE_PROJECT_ID.substring(0, 8)}... (from ENV)`));
|
|
93
|
+
return process.env.RIGSTATE_PROJECT_ID;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// 3. Fall back to global config
|
|
97
|
+
const globalId = config.get('projectId');
|
|
98
|
+
if (globalId) {
|
|
99
|
+
console.log(chalk.dim(` [Auth] Context: Project ID ${globalId.substring(0, 8)}... (from GLOBAL CONFIG)`));
|
|
100
|
+
}
|
|
101
|
+
return globalId;
|
|
44
102
|
}
|
|
45
103
|
|
|
46
104
|
/**
|
|
@@ -55,16 +113,33 @@ export function setProjectId(projectId: string): void {
|
|
|
55
113
|
* Priority: Environment variable > Stored config > Production default
|
|
56
114
|
*/
|
|
57
115
|
export function getApiUrl(): string {
|
|
58
|
-
// 1. Check
|
|
116
|
+
// 1. Check local manifest first
|
|
117
|
+
try {
|
|
118
|
+
const cwd = process.cwd();
|
|
119
|
+
const manifestPaths = [
|
|
120
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
121
|
+
path.join(cwd, '.rigstate')
|
|
122
|
+
];
|
|
123
|
+
|
|
124
|
+
for (const manifestPath of manifestPaths) {
|
|
125
|
+
if (fs.existsSync(manifestPath) && fs.statSync(manifestPath).isFile()) {
|
|
126
|
+
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
127
|
+
const manifest = JSON.parse(content);
|
|
128
|
+
if (manifest.api_url) return manifest.api_url;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} catch (e) { /* Fallback */ }
|
|
132
|
+
|
|
133
|
+
// 2. Check environment variable next
|
|
59
134
|
if (process.env.RIGSTATE_API_URL) {
|
|
60
135
|
return process.env.RIGSTATE_API_URL;
|
|
61
136
|
}
|
|
62
|
-
//
|
|
137
|
+
// 3. Check stored config
|
|
63
138
|
const storedUrl = config.get('apiUrl');
|
|
64
139
|
if (storedUrl) {
|
|
65
140
|
return storedUrl;
|
|
66
141
|
}
|
|
67
|
-
//
|
|
142
|
+
// 4. Default to production
|
|
68
143
|
return 'https://app.rigstate.com';
|
|
69
144
|
}
|
|
70
145
|
|
package/src/utils/manifest.ts
CHANGED
|
@@ -1,18 +1,75 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
|
+
import fsSync from 'fs';
|
|
2
3
|
import path from 'path';
|
|
3
4
|
|
|
4
5
|
export interface RigstateManifest {
|
|
5
6
|
project_id: string;
|
|
6
7
|
api_url?: string;
|
|
7
8
|
linked_at?: string;
|
|
9
|
+
api_key?: string;
|
|
10
|
+
// Genesis Protocol status (cached locally to avoid API calls)
|
|
11
|
+
genesis_complete?: boolean;
|
|
12
|
+
genesis_template?: string;
|
|
13
|
+
genesis_stack_key?: string;
|
|
14
|
+
genesis_initialized_at?: string;
|
|
8
15
|
}
|
|
9
16
|
|
|
17
|
+
|
|
10
18
|
export async function loadManifest(): Promise<RigstateManifest | null> {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
const manifestPaths = [
|
|
21
|
+
path.join(cwd, '.rigstate', 'identity.json'),
|
|
22
|
+
path.join(cwd, '.rigstate')
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
for (const p of manifestPaths) {
|
|
26
|
+
try {
|
|
27
|
+
if (fsSync.existsSync(p) && fsSync.statSync(p).isFile()) {
|
|
28
|
+
const content = await fs.readFile(p, 'utf-8');
|
|
29
|
+
const data = JSON.parse(content);
|
|
30
|
+
|
|
31
|
+
// Handle both flat manifest and identity.json schema
|
|
32
|
+
return {
|
|
33
|
+
project_id: data.project?.id || data.project_id,
|
|
34
|
+
api_url: data.api_url,
|
|
35
|
+
linked_at: data.linked_at || data.project?.created_at,
|
|
36
|
+
api_key: data.api_key
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
} catch (e) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Saves project context to the local manifest.
|
|
48
|
+
* Prioritizes .rigstate/identity.json if the directory exists.
|
|
49
|
+
*/
|
|
50
|
+
export async function saveManifest(data: Partial<RigstateManifest>): Promise<string> {
|
|
51
|
+
const cwd = process.cwd();
|
|
52
|
+
const rigstatePath = path.join(cwd, '.rigstate');
|
|
53
|
+
let targetFile = rigstatePath;
|
|
54
|
+
|
|
11
55
|
try {
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
56
|
+
const stats = await fs.stat(rigstatePath);
|
|
57
|
+
if (stats.isDirectory()) {
|
|
58
|
+
targetFile = path.join(rigstatePath, 'identity.json');
|
|
59
|
+
}
|
|
60
|
+
} catch (e) {
|
|
61
|
+
// Doesn't exist, will be created as file/dir below
|
|
17
62
|
}
|
|
63
|
+
|
|
64
|
+
// Load existing to merge
|
|
65
|
+
const existing = await loadManifest() || {} as RigstateManifest;
|
|
66
|
+
const merged = { ...existing, ...data };
|
|
67
|
+
|
|
68
|
+
// If we need to create a directory for identity.json
|
|
69
|
+
if (targetFile.endsWith('identity.json')) {
|
|
70
|
+
await fs.mkdir(rigstatePath, { recursive: true });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
await fs.writeFile(targetFile, JSON.stringify(merged, null, 2), 'utf-8');
|
|
74
|
+
return targetFile;
|
|
18
75
|
}
|