ugly-app 0.1.413 → 0.1.415
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/cli/authStore.d.ts +2 -0
- package/dist/cli/authStore.d.ts.map +1 -1
- package/dist/cli/authStore.js +88 -25
- package/dist/cli/authStore.js.map +1 -1
- package/dist/cli/scaffold.js +3 -3
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/cli/uglyBotAuth.d.ts +3 -2
- package/dist/cli/uglyBotAuth.d.ts.map +1 -1
- package/dist/cli/uglyBotAuth.js +12 -13
- package/dist/cli/uglyBotAuth.js.map +1 -1
- package/dist/cli/version.d.ts +1 -1
- package/dist/cli/version.js +1 -1
- package/package.json +1 -1
- package/src/cli/authStore.ts +99 -28
- package/src/cli/scaffold.ts +3 -3
- package/src/cli/uglyBotAuth.ts +25 -14
- package/src/cli/version.ts +1 -1
package/dist/cli/authStore.d.ts
CHANGED
|
@@ -8,4 +8,6 @@ export declare function writeLocalToken(projectId: string, token: string): void;
|
|
|
8
8
|
* and strips them from .uglyapp.
|
|
9
9
|
*/
|
|
10
10
|
export declare function migrateTokensFromUglyApp(cwd: string): void;
|
|
11
|
+
/** Test hook: re-arm migration on the next call. */
|
|
12
|
+
export declare function __resetMigrationForTest(): void;
|
|
11
13
|
//# sourceMappingURL=authStore.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authStore.d.ts","sourceRoot":"","sources":["../../src/cli/authStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"authStore.d.ts","sourceRoot":"","sources":["../../src/cli/authStore.ts"],"names":[],"mappings":"AA+DA,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAErE;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEpE;AAED,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAEtE;AAmDD;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAkC1D;AAED,oDAAoD;AACpD,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
|
package/dist/cli/authStore.js
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Per-project auth tokens, one file per project.
|
|
3
|
+
*
|
|
4
|
+
* ~/.ugly-bot/auth.json — global user identity only
|
|
5
|
+
* ({ token, userId, serverUrl }, see uglyBotAuth.ts)
|
|
6
|
+
* ~/.ugly-bot/<projectId>.json — cloud project token ({ token })
|
|
7
|
+
* ~/.ugly-bot/<projectId>.local.json — local project token ({ token })
|
|
8
|
+
*
|
|
9
|
+
* One file per project keeps `auth.json` strictly global so the studio
|
|
10
|
+
* sandbox can seed it into the per-project sandbox HOME without leaking
|
|
11
|
+
* other projects' tokens.
|
|
12
|
+
*
|
|
13
|
+
* Legacy layout (single `auth.json` / `local.json` with a `projects`
|
|
14
|
+
* map) is migrated on first read.
|
|
4
15
|
*/
|
|
5
16
|
import fs from 'node:fs';
|
|
6
17
|
import path from 'node:path';
|
|
@@ -8,47 +19,95 @@ import os from 'node:os';
|
|
|
8
19
|
const AUTH_DIR = path.join(os.homedir(), '.ugly-bot');
|
|
9
20
|
const AUTH_FILE = path.join(AUTH_DIR, 'auth.json');
|
|
10
21
|
const LOCAL_FILE = path.join(AUTH_DIR, 'local.json');
|
|
11
|
-
function
|
|
22
|
+
function projectFile(projectId, mode) {
|
|
23
|
+
const suffix = mode === 'local' ? '.local.json' : '.json';
|
|
24
|
+
return path.join(AUTH_DIR, `${projectId}${suffix}`);
|
|
25
|
+
}
|
|
26
|
+
function readJson(filePath) {
|
|
12
27
|
try {
|
|
13
28
|
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
14
29
|
const parsed = JSON.parse(raw);
|
|
15
|
-
if (parsed && typeof parsed === 'object'
|
|
30
|
+
if (parsed && typeof parsed === 'object')
|
|
16
31
|
return parsed;
|
|
17
|
-
}
|
|
18
32
|
}
|
|
19
33
|
catch {
|
|
20
34
|
// File doesn't exist or is malformed
|
|
21
35
|
}
|
|
22
|
-
return
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function readProjectToken(projectId, mode) {
|
|
39
|
+
ensureMigrated();
|
|
40
|
+
const data = readJson(projectFile(projectId, mode));
|
|
41
|
+
if (data && typeof data.token === 'string')
|
|
42
|
+
return data.token;
|
|
43
|
+
return undefined;
|
|
23
44
|
}
|
|
24
|
-
function
|
|
45
|
+
function writeProjectToken(projectId, mode, token) {
|
|
46
|
+
ensureMigrated();
|
|
25
47
|
fs.mkdirSync(AUTH_DIR, { recursive: true });
|
|
26
|
-
|
|
27
|
-
let existing = {};
|
|
28
|
-
try {
|
|
29
|
-
existing = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
|
|
30
|
-
}
|
|
31
|
-
catch {
|
|
32
|
-
// File doesn't exist or is malformed — start fresh
|
|
33
|
-
}
|
|
34
|
-
existing.projects = store.projects;
|
|
35
|
-
fs.writeFileSync(filePath, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
48
|
+
fs.writeFileSync(projectFile(projectId, mode), JSON.stringify({ token }, null, 2) + '\n', 'utf-8');
|
|
36
49
|
}
|
|
37
50
|
export function readAuthToken(projectId) {
|
|
38
|
-
return
|
|
51
|
+
return readProjectToken(projectId, 'cloud');
|
|
39
52
|
}
|
|
40
53
|
export function writeAuthToken(projectId, token) {
|
|
41
|
-
|
|
42
|
-
store.projects[projectId] = { token };
|
|
43
|
-
writeStore(AUTH_FILE, store);
|
|
54
|
+
writeProjectToken(projectId, 'cloud', token);
|
|
44
55
|
}
|
|
45
56
|
export function readLocalToken(projectId) {
|
|
46
|
-
return
|
|
57
|
+
return readProjectToken(projectId, 'local');
|
|
47
58
|
}
|
|
48
59
|
export function writeLocalToken(projectId, token) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
60
|
+
writeProjectToken(projectId, 'local', token);
|
|
61
|
+
}
|
|
62
|
+
let migrationChecked = false;
|
|
63
|
+
/**
|
|
64
|
+
* Idempotent. Splits legacy `auth.json.projects` / `local.json.projects`
|
|
65
|
+
* into per-project files and strips the `projects` key from `auth.json`
|
|
66
|
+
* (deletes `local.json` outright since it had no global data). Runs at
|
|
67
|
+
* most once per process, gated by a module-local flag — repeated reads
|
|
68
|
+
* don't re-stat every file.
|
|
69
|
+
*/
|
|
70
|
+
function ensureMigrated() {
|
|
71
|
+
if (migrationChecked)
|
|
72
|
+
return;
|
|
73
|
+
migrationChecked = true;
|
|
74
|
+
migrateLegacyFile(AUTH_FILE, 'cloud');
|
|
75
|
+
migrateLegacyFile(LOCAL_FILE, 'local');
|
|
76
|
+
}
|
|
77
|
+
function migrateLegacyFile(filePath, mode) {
|
|
78
|
+
const data = readJson(filePath);
|
|
79
|
+
if (!data)
|
|
80
|
+
return;
|
|
81
|
+
const projects = data.projects;
|
|
82
|
+
if (!projects || typeof projects !== 'object')
|
|
83
|
+
return;
|
|
84
|
+
fs.mkdirSync(AUTH_DIR, { recursive: true });
|
|
85
|
+
for (const [projectId, entry] of Object.entries(projects)) {
|
|
86
|
+
if (!entry || typeof entry !== 'object')
|
|
87
|
+
continue;
|
|
88
|
+
const token = entry.token;
|
|
89
|
+
if (typeof token !== 'string')
|
|
90
|
+
continue;
|
|
91
|
+
const target = projectFile(projectId, mode);
|
|
92
|
+
// Don't clobber a per-project file the user may already have written.
|
|
93
|
+
if (fs.existsSync(target))
|
|
94
|
+
continue;
|
|
95
|
+
fs.writeFileSync(target, JSON.stringify({ token }, null, 2) + '\n', 'utf-8');
|
|
96
|
+
}
|
|
97
|
+
if (mode === 'cloud') {
|
|
98
|
+
// auth.json keeps its global fields (token, userId, serverUrl) — just drop `projects`.
|
|
99
|
+
delete data.projects;
|
|
100
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// local.json had no global data — remove it entirely.
|
|
104
|
+
try {
|
|
105
|
+
fs.unlinkSync(filePath);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/* already gone */
|
|
109
|
+
}
|
|
110
|
+
}
|
|
52
111
|
}
|
|
53
112
|
/**
|
|
54
113
|
* Migrate tokens from .uglyapp to ~/.ugly-bot/ auth store.
|
|
@@ -88,4 +147,8 @@ export function migrateTokensFromUglyApp(cwd) {
|
|
|
88
147
|
// .uglyapp doesn't exist or is malformed — skip migration
|
|
89
148
|
}
|
|
90
149
|
}
|
|
150
|
+
/** Test hook: re-arm migration on the next call. */
|
|
151
|
+
export function __resetMigrationForTest() {
|
|
152
|
+
migrationChecked = false;
|
|
153
|
+
}
|
|
91
154
|
//# sourceMappingURL=authStore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"authStore.js","sourceRoot":"","sources":["../../src/cli/authStore.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"authStore.js","sourceRoot":"","sources":["../../src/cli/authStore.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/scaffold.js
CHANGED
|
@@ -41,7 +41,7 @@ export async function scaffoldProject(projectName) {
|
|
|
41
41
|
await fs.writeFile(path.join(migrationsDir, '001_bootstrap.ts'), migrationCode, 'utf-8');
|
|
42
42
|
console.log('[ugly-app] Generated server/migrations/001_bootstrap.ts');
|
|
43
43
|
console.log('[ugly-app] Installing dependencies...');
|
|
44
|
-
execSync('
|
|
44
|
+
execSync('pnpm install', { cwd: destDir, stdio: 'inherit' });
|
|
45
45
|
const localPort = DEFAULT_LOCAL_PORT;
|
|
46
46
|
// Only alphanumeric — safe for R2 buckets, Postgres usernames, Docker tags
|
|
47
47
|
const generateId = customAlphabet('abcdefghijklmnopqrstuvwxyz0123456789', 10);
|
|
@@ -61,8 +61,8 @@ export async function scaffoldProject(projectName) {
|
|
|
61
61
|
console.log(`
|
|
62
62
|
[ugly-app] Done! Next steps:
|
|
63
63
|
cd ${projectName}
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
pnpm run db:migrate # create tables and indexes
|
|
65
|
+
pnpm run dev # start everything
|
|
66
66
|
`);
|
|
67
67
|
}
|
|
68
68
|
//# sourceMappingURL=scaffold.js.map
|
package/dist/cli/scaffold.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/cli/scaffold.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/cli/scaffold.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Global user identity stored in ~/.ugly-bot/auth.json. Per-project
|
|
3
|
+
* tokens live in `<projectId>.json` / `<projectId>.local.json` siblings
|
|
4
|
+
* — see authStore.ts. Same format as the Python CLI and VSCode extension.
|
|
4
5
|
*/
|
|
5
6
|
export interface UglyBotAuth {
|
|
6
7
|
token: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uglyBotAuth.d.ts","sourceRoot":"","sources":["../../src/cli/uglyBotAuth.ts"],"names":[],"mappings":"AAIA
|
|
1
|
+
{"version":3,"file":"uglyBotAuth.d.ts","sourceRoot":"","sources":["../../src/cli/uglyBotAuth.ts"],"names":[],"mappings":"AAIA;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,wBAAgB,eAAe,IAAI,WAAW,GAAG,IAAI,CAoBpD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAWvD;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAavD"}
|
package/dist/cli/uglyBotAuth.js
CHANGED
|
@@ -8,7 +8,17 @@ export function readUglyBotAuth() {
|
|
|
8
8
|
if (!fs.existsSync(authFile))
|
|
9
9
|
return null;
|
|
10
10
|
const raw = fs.readFileSync(authFile, 'utf-8');
|
|
11
|
-
|
|
11
|
+
const parsed = JSON.parse(raw);
|
|
12
|
+
if (typeof parsed.token !== 'string' ||
|
|
13
|
+
typeof parsed.userId !== 'string' ||
|
|
14
|
+
typeof parsed.serverUrl !== 'string') {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
return {
|
|
18
|
+
token: parsed.token,
|
|
19
|
+
userId: parsed.userId,
|
|
20
|
+
serverUrl: parsed.serverUrl,
|
|
21
|
+
};
|
|
12
22
|
}
|
|
13
23
|
catch {
|
|
14
24
|
return null;
|
|
@@ -16,18 +26,7 @@ export function readUglyBotAuth() {
|
|
|
16
26
|
}
|
|
17
27
|
export function saveUglyBotAuth(auth) {
|
|
18
28
|
fs.mkdirSync(authDir, { recursive: true });
|
|
19
|
-
|
|
20
|
-
let existing = {};
|
|
21
|
-
try {
|
|
22
|
-
existing = JSON.parse(fs.readFileSync(authFile, 'utf-8'));
|
|
23
|
-
}
|
|
24
|
-
catch {
|
|
25
|
-
// File doesn't exist or is malformed — start fresh
|
|
26
|
-
}
|
|
27
|
-
existing.token = auth.token;
|
|
28
|
-
existing.userId = auth.userId;
|
|
29
|
-
existing.serverUrl = auth.serverUrl;
|
|
30
|
-
fs.writeFileSync(authFile, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
29
|
+
fs.writeFileSync(authFile, JSON.stringify({ token: auth.token, userId: auth.userId, serverUrl: auth.serverUrl }, null, 2) + '\n', 'utf-8');
|
|
31
30
|
}
|
|
32
31
|
/**
|
|
33
32
|
* Returns true if the token exists and is not expired.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uglyBotAuth.js","sourceRoot":"","sources":["../../src/cli/uglyBotAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"uglyBotAuth.js","sourceRoot":"","sources":["../../src/cli/uglyBotAuth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAaxB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,CAAC,CAAC;AACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;AAEjD,MAAM,UAAU,eAAe;IAC7B,IAAI,CAAC;QACH,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyB,CAAC;QACvD,IACE,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ;YAChC,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ;YACjC,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,EACpC,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO;YACL,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,MAAM,EAAE,MAAM,CAAC,MAAM;YACrB,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,IAAiB;IAC/C,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3C,EAAE,CAAC,aAAa,CACd,QAAQ,EACR,IAAI,CAAC,SAAS,CACZ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,EACrE,IAAI,EACJ,CAAC,CACF,GAAG,IAAI,EACR,OAAO,CACR,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAiB;IAC5C,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CACxB,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CACjC,CAAC;QACtB,IAAI,CAAC,OAAO,CAAC,GAAG;YAAE,OAAO,KAAK,CAAC;QAC/B,wCAAwC;QACxC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,GAAG,GAAG,EAAE,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
package/dist/cli/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.1.
|
|
1
|
+
export declare const CLI_VERSION = "0.1.415";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/cli/version.js
CHANGED
package/package.json
CHANGED
package/src/cli/authStore.ts
CHANGED
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
2
|
+
* Per-project auth tokens, one file per project.
|
|
3
|
+
*
|
|
4
|
+
* ~/.ugly-bot/auth.json — global user identity only
|
|
5
|
+
* ({ token, userId, serverUrl }, see uglyBotAuth.ts)
|
|
6
|
+
* ~/.ugly-bot/<projectId>.json — cloud project token ({ token })
|
|
7
|
+
* ~/.ugly-bot/<projectId>.local.json — local project token ({ token })
|
|
8
|
+
*
|
|
9
|
+
* One file per project keeps `auth.json` strictly global so the studio
|
|
10
|
+
* sandbox can seed it into the per-project sandbox HOME without leaking
|
|
11
|
+
* other projects' tokens.
|
|
12
|
+
*
|
|
13
|
+
* Legacy layout (single `auth.json` / `local.json` with a `projects`
|
|
14
|
+
* map) is migrated on first read.
|
|
4
15
|
*/
|
|
5
16
|
import fs from 'node:fs';
|
|
6
17
|
import path from 'node:path';
|
|
@@ -10,54 +21,109 @@ const AUTH_DIR = path.join(os.homedir(), '.ugly-bot');
|
|
|
10
21
|
const AUTH_FILE = path.join(AUTH_DIR, 'auth.json');
|
|
11
22
|
const LOCAL_FILE = path.join(AUTH_DIR, 'local.json');
|
|
12
23
|
|
|
13
|
-
|
|
14
|
-
|
|
24
|
+
function projectFile(projectId: string, mode: 'cloud' | 'local'): string {
|
|
25
|
+
const suffix = mode === 'local' ? '.local.json' : '.json';
|
|
26
|
+
return path.join(AUTH_DIR, `${projectId}${suffix}`);
|
|
15
27
|
}
|
|
16
28
|
|
|
17
|
-
function
|
|
29
|
+
function readJson(filePath: string): Record<string, unknown> | null {
|
|
18
30
|
try {
|
|
19
31
|
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
20
|
-
const parsed = JSON.parse(raw) as
|
|
21
|
-
if (parsed && typeof parsed === 'object'
|
|
22
|
-
return parsed;
|
|
23
|
-
}
|
|
32
|
+
const parsed = JSON.parse(raw) as Record<string, unknown>;
|
|
33
|
+
if (parsed && typeof parsed === 'object') return parsed;
|
|
24
34
|
} catch {
|
|
25
35
|
// File doesn't exist or is malformed
|
|
26
36
|
}
|
|
27
|
-
return
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function readProjectToken(
|
|
41
|
+
projectId: string,
|
|
42
|
+
mode: 'cloud' | 'local',
|
|
43
|
+
): string | undefined {
|
|
44
|
+
ensureMigrated();
|
|
45
|
+
const data = readJson(projectFile(projectId, mode));
|
|
46
|
+
if (data && typeof data.token === 'string') return data.token;
|
|
47
|
+
return undefined;
|
|
28
48
|
}
|
|
29
49
|
|
|
30
|
-
function
|
|
50
|
+
function writeProjectToken(
|
|
51
|
+
projectId: string,
|
|
52
|
+
mode: 'cloud' | 'local',
|
|
53
|
+
token: string,
|
|
54
|
+
): void {
|
|
55
|
+
ensureMigrated();
|
|
31
56
|
fs.mkdirSync(AUTH_DIR, { recursive: true });
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
// File doesn't exist or is malformed — start fresh
|
|
38
|
-
}
|
|
39
|
-
existing.projects = store.projects;
|
|
40
|
-
fs.writeFileSync(filePath, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
57
|
+
fs.writeFileSync(
|
|
58
|
+
projectFile(projectId, mode),
|
|
59
|
+
JSON.stringify({ token }, null, 2) + '\n',
|
|
60
|
+
'utf-8',
|
|
61
|
+
);
|
|
41
62
|
}
|
|
42
63
|
|
|
43
64
|
export function readAuthToken(projectId: string): string | undefined {
|
|
44
|
-
return
|
|
65
|
+
return readProjectToken(projectId, 'cloud');
|
|
45
66
|
}
|
|
46
67
|
|
|
47
68
|
export function writeAuthToken(projectId: string, token: string): void {
|
|
48
|
-
|
|
49
|
-
store.projects[projectId] = { token };
|
|
50
|
-
writeStore(AUTH_FILE, store);
|
|
69
|
+
writeProjectToken(projectId, 'cloud', token);
|
|
51
70
|
}
|
|
52
71
|
|
|
53
72
|
export function readLocalToken(projectId: string): string | undefined {
|
|
54
|
-
return
|
|
73
|
+
return readProjectToken(projectId, 'local');
|
|
55
74
|
}
|
|
56
75
|
|
|
57
76
|
export function writeLocalToken(projectId: string, token: string): void {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
77
|
+
writeProjectToken(projectId, 'local', token);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
let migrationChecked = false;
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Idempotent. Splits legacy `auth.json.projects` / `local.json.projects`
|
|
84
|
+
* into per-project files and strips the `projects` key from `auth.json`
|
|
85
|
+
* (deletes `local.json` outright since it had no global data). Runs at
|
|
86
|
+
* most once per process, gated by a module-local flag — repeated reads
|
|
87
|
+
* don't re-stat every file.
|
|
88
|
+
*/
|
|
89
|
+
function ensureMigrated(): void {
|
|
90
|
+
if (migrationChecked) return;
|
|
91
|
+
migrationChecked = true;
|
|
92
|
+
migrateLegacyFile(AUTH_FILE, 'cloud');
|
|
93
|
+
migrateLegacyFile(LOCAL_FILE, 'local');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function migrateLegacyFile(filePath: string, mode: 'cloud' | 'local'): void {
|
|
97
|
+
const data = readJson(filePath);
|
|
98
|
+
if (!data) return;
|
|
99
|
+
const projects = data.projects;
|
|
100
|
+
if (!projects || typeof projects !== 'object') return;
|
|
101
|
+
|
|
102
|
+
fs.mkdirSync(AUTH_DIR, { recursive: true });
|
|
103
|
+
for (const [projectId, entry] of Object.entries(
|
|
104
|
+
projects as Record<string, unknown>,
|
|
105
|
+
)) {
|
|
106
|
+
if (!entry || typeof entry !== 'object') continue;
|
|
107
|
+
const token = (entry as { token?: unknown }).token;
|
|
108
|
+
if (typeof token !== 'string') continue;
|
|
109
|
+
const target = projectFile(projectId, mode);
|
|
110
|
+
// Don't clobber a per-project file the user may already have written.
|
|
111
|
+
if (fs.existsSync(target)) continue;
|
|
112
|
+
fs.writeFileSync(target, JSON.stringify({ token }, null, 2) + '\n', 'utf-8');
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
if (mode === 'cloud') {
|
|
116
|
+
// auth.json keeps its global fields (token, userId, serverUrl) — just drop `projects`.
|
|
117
|
+
delete data.projects;
|
|
118
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
119
|
+
} else {
|
|
120
|
+
// local.json had no global data — remove it entirely.
|
|
121
|
+
try {
|
|
122
|
+
fs.unlinkSync(filePath);
|
|
123
|
+
} catch {
|
|
124
|
+
/* already gone */
|
|
125
|
+
}
|
|
126
|
+
}
|
|
61
127
|
}
|
|
62
128
|
|
|
63
129
|
/**
|
|
@@ -100,3 +166,8 @@ export function migrateTokensFromUglyApp(cwd: string): void {
|
|
|
100
166
|
// .uglyapp doesn't exist or is malformed — skip migration
|
|
101
167
|
}
|
|
102
168
|
}
|
|
169
|
+
|
|
170
|
+
/** Test hook: re-arm migration on the next call. */
|
|
171
|
+
export function __resetMigrationForTest(): void {
|
|
172
|
+
migrationChecked = false;
|
|
173
|
+
}
|
package/src/cli/scaffold.ts
CHANGED
|
@@ -54,7 +54,7 @@ export async function scaffoldProject(projectName: string): Promise<void> {
|
|
|
54
54
|
console.log('[ugly-app] Generated server/migrations/001_bootstrap.ts');
|
|
55
55
|
|
|
56
56
|
console.log('[ugly-app] Installing dependencies...');
|
|
57
|
-
execSync('
|
|
57
|
+
execSync('pnpm install', { cwd: destDir, stdio: 'inherit' });
|
|
58
58
|
|
|
59
59
|
const localPort = DEFAULT_LOCAL_PORT;
|
|
60
60
|
// Only alphanumeric — safe for R2 buckets, Postgres usernames, Docker tags
|
|
@@ -80,7 +80,7 @@ export async function scaffoldProject(projectName: string): Promise<void> {
|
|
|
80
80
|
console.log(`
|
|
81
81
|
[ugly-app] Done! Next steps:
|
|
82
82
|
cd ${projectName}
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
pnpm run db:migrate # create tables and indexes
|
|
84
|
+
pnpm run dev # start everything
|
|
85
85
|
`);
|
|
86
86
|
}
|
package/src/cli/uglyBotAuth.ts
CHANGED
|
@@ -3,8 +3,9 @@ import os from 'os';
|
|
|
3
3
|
import path from 'path';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Global user identity stored in ~/.ugly-bot/auth.json. Per-project
|
|
7
|
+
* tokens live in `<projectId>.json` / `<projectId>.local.json` siblings
|
|
8
|
+
* — see authStore.ts. Same format as the Python CLI and VSCode extension.
|
|
8
9
|
*/
|
|
9
10
|
export interface UglyBotAuth {
|
|
10
11
|
token: string;
|
|
@@ -19,7 +20,19 @@ export function readUglyBotAuth(): UglyBotAuth | null {
|
|
|
19
20
|
try {
|
|
20
21
|
if (!fs.existsSync(authFile)) return null;
|
|
21
22
|
const raw = fs.readFileSync(authFile, 'utf-8');
|
|
22
|
-
|
|
23
|
+
const parsed = JSON.parse(raw) as Partial<UglyBotAuth>;
|
|
24
|
+
if (
|
|
25
|
+
typeof parsed.token !== 'string' ||
|
|
26
|
+
typeof parsed.userId !== 'string' ||
|
|
27
|
+
typeof parsed.serverUrl !== 'string'
|
|
28
|
+
) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return {
|
|
32
|
+
token: parsed.token,
|
|
33
|
+
userId: parsed.userId,
|
|
34
|
+
serverUrl: parsed.serverUrl,
|
|
35
|
+
};
|
|
23
36
|
} catch {
|
|
24
37
|
return null;
|
|
25
38
|
}
|
|
@@ -27,17 +40,15 @@ export function readUglyBotAuth(): UglyBotAuth | null {
|
|
|
27
40
|
|
|
28
41
|
export function saveUglyBotAuth(auth: UglyBotAuth): void {
|
|
29
42
|
fs.mkdirSync(authDir, { recursive: true });
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
existing.serverUrl = auth.serverUrl;
|
|
40
|
-
fs.writeFileSync(authFile, JSON.stringify(existing, null, 2) + '\n', 'utf-8');
|
|
43
|
+
fs.writeFileSync(
|
|
44
|
+
authFile,
|
|
45
|
+
JSON.stringify(
|
|
46
|
+
{ token: auth.token, userId: auth.userId, serverUrl: auth.serverUrl },
|
|
47
|
+
null,
|
|
48
|
+
2,
|
|
49
|
+
) + '\n',
|
|
50
|
+
'utf-8',
|
|
51
|
+
);
|
|
41
52
|
}
|
|
42
53
|
|
|
43
54
|
/**
|
package/src/cli/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by prebuild — do not edit manually
|
|
2
|
-
export const CLI_VERSION = "0.1.
|
|
2
|
+
export const CLI_VERSION = "0.1.415";
|