@upend/cli 0.1.1 → 0.1.2
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/cli.ts +11 -0
- package/package.json +2 -1
- package/src/commands/dev.ts +2 -2
- package/src/commands/init.ts +3 -3
- package/src/services/dashboard/public/index.html +33 -4
package/bin/cli.ts
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
2
|
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
|
|
5
|
+
// auto-load encrypted .env if present (skip for init — no .env yet)
|
|
3
6
|
const args = process.argv.slice(2);
|
|
4
7
|
const command = args[0];
|
|
8
|
+
if (command !== "init" && existsSync(".env")) {
|
|
9
|
+
try {
|
|
10
|
+
const { config } = await import("@dotenvx/dotenvx");
|
|
11
|
+
config({ quiet: true });
|
|
12
|
+
} catch {
|
|
13
|
+
// dotenvx not available, env vars must be set manually
|
|
14
|
+
}
|
|
15
|
+
}
|
|
5
16
|
|
|
6
17
|
const commands: Record<string, () => Promise<void>> = {
|
|
7
18
|
init: () => import("../src/commands/init").then((m) => m.default(args.slice(1))),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@upend/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Anti-SaaS stack. Deploy live apps with Claude, Postgres, and rsync.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"url": "https://github.com/cif/upend"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
+
"@dotenvx/dotenvx": "^1.55.1",
|
|
22
23
|
"hono": "^4.12.8",
|
|
23
24
|
"jose": "^6.2.1",
|
|
24
25
|
"postgres": "^3.4.8"
|
package/src/commands/dev.ts
CHANGED
|
@@ -23,7 +23,7 @@ export default async function dev(args: string[]) {
|
|
|
23
23
|
|
|
24
24
|
// start API service
|
|
25
25
|
log.info(`starting api → :${apiPort}`);
|
|
26
|
-
Bun.spawn(["
|
|
26
|
+
Bun.spawn(["bun", "--watch", `${cliRoot}/src/services/gateway/index.ts`], {
|
|
27
27
|
cwd: projectDir,
|
|
28
28
|
env: { ...process.env, API_PORT: apiPort, UPEND_PROJECT: projectDir },
|
|
29
29
|
stdout: "inherit",
|
|
@@ -32,7 +32,7 @@ export default async function dev(args: string[]) {
|
|
|
32
32
|
|
|
33
33
|
// start Claude service
|
|
34
34
|
log.info(`starting claude → :${claudePort}`);
|
|
35
|
-
Bun.spawn(["
|
|
35
|
+
Bun.spawn(["bun", "--watch", `${cliRoot}/src/services/claude/index.ts`], {
|
|
36
36
|
cwd: projectDir,
|
|
37
37
|
env: { ...process.env, CLAUDE_PORT: claudePort, UPEND_PROJECT: projectDir },
|
|
38
38
|
stdout: "inherit",
|
package/src/commands/init.ts
CHANGED
|
@@ -340,10 +340,10 @@ All requests need \`Authorization: Bearer <jwt>\` header.
|
|
|
340
340
|
log.blank();
|
|
341
341
|
log.info(`cd ${name}`);
|
|
342
342
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
343
|
-
log.info("upend env:set ANTHROPIC_API_KEY <your-key>");
|
|
343
|
+
log.info("bunx upend env:set ANTHROPIC_API_KEY <your-key>");
|
|
344
344
|
}
|
|
345
|
-
log.info("upend migrate");
|
|
346
|
-
log.info("upend dev");
|
|
345
|
+
log.info("bunx upend migrate");
|
|
346
|
+
log.info("bunx upend dev");
|
|
347
347
|
log.blank();
|
|
348
348
|
if (databaseUrl) {
|
|
349
349
|
log.dim(`database: ${neonProjectId}`);
|
|
@@ -190,6 +190,25 @@
|
|
|
190
190
|
</div>
|
|
191
191
|
</div>
|
|
192
192
|
|
|
193
|
+
<!-- new app modal -->
|
|
194
|
+
<div x-show="showNewAppModal" x-transition class="fixed inset-0 bg-black/60 flex items-center justify-center z-50">
|
|
195
|
+
<form @submit.prevent="submitNewApp()"
|
|
196
|
+
@keydown.escape="showNewAppModal = false"
|
|
197
|
+
class="bg-surface border border-border rounded-xl p-6 w-96 flex flex-col gap-4">
|
|
198
|
+
<h3 class="text-accent font-bold text-sm">new app</h3>
|
|
199
|
+
<input x-model="newAppName" x-ref="newAppNameInput" type="text" placeholder="app name (lowercase, no spaces)"
|
|
200
|
+
class="bg-bg border border-border rounded-md px-3 py-2 text-sm text-gray-200 font-mono outline-none focus:border-accent">
|
|
201
|
+
<textarea x-model="newAppDesc" rows="3" placeholder="what should this app do?"
|
|
202
|
+
class="bg-bg border border-border rounded-md px-3 py-2 text-sm text-gray-200 font-mono outline-none focus:border-accent resize-none"></textarea>
|
|
203
|
+
<div class="flex gap-2 justify-end">
|
|
204
|
+
<button type="button" @click="showNewAppModal = false"
|
|
205
|
+
class="text-muted text-xs px-3 py-1.5 rounded border border-border cursor-pointer hover:text-gray-200 font-mono">cancel</button>
|
|
206
|
+
<button type="submit" :disabled="!newAppName.trim() || !newAppDesc.trim()"
|
|
207
|
+
class="bg-accent text-black text-xs px-4 py-1.5 rounded font-bold cursor-pointer disabled:opacity-40 font-mono">create</button>
|
|
208
|
+
</div>
|
|
209
|
+
</form>
|
|
210
|
+
</div>
|
|
211
|
+
|
|
193
212
|
<!-- main panels -->
|
|
194
213
|
<div x-show="token" class="flex-1 flex min-h-0">
|
|
195
214
|
<!-- left: chat (native DOM) -->
|
|
@@ -385,6 +404,9 @@ function dashboard() {
|
|
|
385
404
|
showSessionModal: false,
|
|
386
405
|
showCloseModal: false,
|
|
387
406
|
showPublishModal: false,
|
|
407
|
+
showNewAppModal: false,
|
|
408
|
+
newAppName: '',
|
|
409
|
+
newAppDesc: '',
|
|
388
410
|
sessionTitle: '',
|
|
389
411
|
_pendingPrompt: '',
|
|
390
412
|
|
|
@@ -826,10 +848,17 @@ function dashboard() {
|
|
|
826
848
|
|
|
827
849
|
createNewApp() {
|
|
828
850
|
this.appsOpen = false;
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
851
|
+
this.newAppName = '';
|
|
852
|
+
this.newAppDesc = '';
|
|
853
|
+
this.showNewAppModal = true;
|
|
854
|
+
this.$nextTick(() => this.$refs.newAppNameInput?.focus());
|
|
855
|
+
},
|
|
856
|
+
|
|
857
|
+
submitNewApp() {
|
|
858
|
+
const name = this.newAppName.trim().toLowerCase().replace(/\s+/g, '-');
|
|
859
|
+
const desc = this.newAppDesc.trim();
|
|
860
|
+
if (!name || !desc) return;
|
|
861
|
+
this.showNewAppModal = false;
|
|
833
862
|
this.prompt = `create an app called "${name}" in apps/${name}/. ${desc}`;
|
|
834
863
|
this.sendPrompt();
|
|
835
864
|
},
|