everything-dev 0.1.4 → 0.2.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/package.json +22 -2
- package/src/cli.ts +50 -57
- package/src/components/dev-view.tsx +49 -9
- package/src/components/streaming-view.ts +10 -1
- package/src/config.ts +46 -9
- package/src/contract.ts +9 -10
- package/src/lib/process.ts +80 -44
- package/src/lib/resource-monitor/diff.ts +7 -11
- package/src/lib/resource-monitor/platform/darwin.ts +1 -1
- package/src/lib/sync.ts +1 -133
- package/src/plugin.ts +65 -21
- package/src/types.ts +48 -3
- package/src/ui/files.ts +134 -0
- package/src/ui/head.ts +65 -0
- package/src/ui/index.ts +5 -0
- package/src/ui/router.ts +72 -0
- package/src/ui/runtime.ts +35 -0
- package/src/ui/types.ts +51 -0
package/package.json
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "everything-dev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"exports": {
|
|
7
7
|
".": "./src/index.ts",
|
|
8
|
-
"./types": "./src/types.ts"
|
|
8
|
+
"./types": "./src/types.ts",
|
|
9
|
+
"./config": "./src/config.ts",
|
|
10
|
+
"./ui": "./src/ui/index.ts",
|
|
11
|
+
"./ui/types": "./src/ui/types.ts",
|
|
12
|
+
"./ui/runtime": "./src/ui/runtime.ts",
|
|
13
|
+
"./ui/head": "./src/ui/head.ts",
|
|
14
|
+
"./ui/router": "./src/ui/router.ts"
|
|
9
15
|
},
|
|
10
16
|
"files": [
|
|
11
17
|
"src"
|
|
@@ -50,6 +56,8 @@
|
|
|
50
56
|
"zod": "4.3.5"
|
|
51
57
|
},
|
|
52
58
|
"devDependencies": {
|
|
59
|
+
"@tanstack/react-query": "^5.0.0",
|
|
60
|
+
"@tanstack/react-router": "^1.0.0",
|
|
53
61
|
"@types/bun": "^1.3.8",
|
|
54
62
|
"@types/gradient-string": "^1.1.6",
|
|
55
63
|
"@types/react": "^18.3.0",
|
|
@@ -57,5 +65,17 @@
|
|
|
57
65
|
"playwright": "^1.58.1",
|
|
58
66
|
"typescript": "^5.9.3",
|
|
59
67
|
"vitest": "^4.0.18"
|
|
68
|
+
},
|
|
69
|
+
"peerDependencies": {
|
|
70
|
+
"@tanstack/react-query": ">=5.0.0",
|
|
71
|
+
"@tanstack/react-router": ">=1.0.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"@tanstack/react-query": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"@tanstack/react-router": {
|
|
78
|
+
"optional": true
|
|
79
|
+
}
|
|
60
80
|
}
|
|
61
81
|
}
|
package/src/cli.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { spinner } from "@clack/prompts";
|
|
3
3
|
import { program } from "commander";
|
|
4
4
|
import { createPluginRuntime } from "every-plugin";
|
|
5
|
-
import { type BosConfig, getConfigDir, getConfigPath, getPackages,
|
|
5
|
+
import { type BosConfig, getConfigDir, getConfigPath, getPackages, loadConfig } from "./config";
|
|
6
6
|
import BosPlugin from "./plugin";
|
|
7
7
|
import { printBanner } from "./utils/banner";
|
|
8
8
|
import { colors, frames, gradients, icons } from "./utils/theme";
|
|
@@ -21,9 +21,6 @@ function getHelpHeader(config: BosConfig | null, configPath: string): string {
|
|
|
21
21
|
lines.push(` ${colors.dim("Account")} ${colors.cyan(config.account)}`);
|
|
22
22
|
lines.push(` ${colors.dim("Gateway")} ${colors.white(config.gateway?.production ?? "not configured")}`);
|
|
23
23
|
lines.push(` ${colors.dim("Config ")} ${colors.dim(configPath)}`);
|
|
24
|
-
if (host?.description) {
|
|
25
|
-
lines.push(` ${colors.dim("About ")} ${colors.white(host.description)}`);
|
|
26
|
-
}
|
|
27
24
|
} else {
|
|
28
25
|
lines.push(` ${colors.dim("No project config found")}`);
|
|
29
26
|
lines.push(` ${colors.dim("Run")} ${colors.cyan("bos create project <name>")} ${colors.dim("to get started")}`);
|
|
@@ -48,7 +45,6 @@ async function main() {
|
|
|
48
45
|
const config = loadConfig();
|
|
49
46
|
const configPath = config ? getConfigPath() : process.cwd();
|
|
50
47
|
const packages = config ? getPackages() : [];
|
|
51
|
-
const title = config ? getTitle() : "BOS CLI";
|
|
52
48
|
|
|
53
49
|
if (config) {
|
|
54
50
|
const envPath = `${getConfigDir()}/.env.bos`;
|
|
@@ -69,7 +65,7 @@ async function main() {
|
|
|
69
65
|
}
|
|
70
66
|
}
|
|
71
67
|
|
|
72
|
-
printBanner(
|
|
68
|
+
printBanner("BOS CLI");
|
|
73
69
|
|
|
74
70
|
const runtime = createPluginRuntime({
|
|
75
71
|
registry: {
|
|
@@ -113,10 +109,6 @@ async function main() {
|
|
|
113
109
|
|
|
114
110
|
const host = result.config.app.host;
|
|
115
111
|
console.log(colors.magenta(` ┌─ HOST ${"─".repeat(42)}┐`));
|
|
116
|
-
console.log(` ${colors.magenta("│")} ${colors.dim("title")} ${colors.white(host.title)}`);
|
|
117
|
-
if (host.description) {
|
|
118
|
-
console.log(` ${colors.magenta("│")} ${colors.dim("description")} ${colors.gray(host.description)}`);
|
|
119
|
-
}
|
|
120
112
|
console.log(` ${colors.magenta("│")} ${colors.dim("development")} ${colors.cyan(host.development)}`);
|
|
121
113
|
console.log(` ${colors.magenta("│")} ${colors.dim("production")} ${colors.green(host.production)}`);
|
|
122
114
|
console.log(colors.magenta(` └${"─".repeat(49)}┘`));
|
|
@@ -238,7 +230,7 @@ async function main() {
|
|
|
238
230
|
new OpenAPIReferencePlugin({
|
|
239
231
|
schemaConverters: [new ZodToJsonSchemaConverter()],
|
|
240
232
|
specGenerateOptions: {
|
|
241
|
-
info: { title: "
|
|
233
|
+
info: { title: "everything-dev api", version: "1.0.0" },
|
|
242
234
|
servers: [{ url: `http://localhost:${port}/api` }],
|
|
243
235
|
},
|
|
244
236
|
}),
|
|
@@ -248,7 +240,7 @@ async function main() {
|
|
|
248
240
|
|
|
249
241
|
app.get("/", (c) => c.json({
|
|
250
242
|
ok: true,
|
|
251
|
-
plugin: "
|
|
243
|
+
plugin: "everything-dev",
|
|
252
244
|
status: "ready",
|
|
253
245
|
endpoints: {
|
|
254
246
|
health: "/",
|
|
@@ -341,47 +333,49 @@ async function main() {
|
|
|
341
333
|
});
|
|
342
334
|
|
|
343
335
|
program
|
|
344
|
-
.command("
|
|
345
|
-
.description(
|
|
346
|
-
.argument("[packages]", "Packages to deploy (comma-separated: host,ui,api)", "all")
|
|
336
|
+
.command("publish")
|
|
337
|
+
.description("Build, deploy, and publish to Near Social (full release)")
|
|
338
|
+
.argument("[packages]", "Packages to build/deploy (comma-separated: host,ui,api)", "all")
|
|
347
339
|
.option("--force", "Force rebuild")
|
|
340
|
+
.option("--network <network>", "Network: mainnet | testnet", "mainnet")
|
|
341
|
+
.option("--path <path>", "Near Social relative path", "bos.config.json")
|
|
342
|
+
.option("--dry-run", "Show what would be published without sending")
|
|
348
343
|
.addHelpText("after", `
|
|
344
|
+
Release Workflow:
|
|
345
|
+
1. Build packages (bun run build)
|
|
346
|
+
2. Deploy to Zephyr Cloud (updates production URLs)
|
|
347
|
+
3. Publish config to Near Social
|
|
348
|
+
|
|
349
349
|
Zephyr Configuration:
|
|
350
350
|
Set ZE_SERVER_TOKEN and ZE_USER_EMAIL in .env.bos for CI/CD deployment.
|
|
351
351
|
Docs: https://docs.zephyr-cloud.io/features/ci-cd-server-token
|
|
352
352
|
`)
|
|
353
353
|
.action(async (pkgs: string, options) => {
|
|
354
354
|
console.log();
|
|
355
|
-
console.log(` ${icons.pkg}
|
|
355
|
+
console.log(` ${icons.pkg} Starting release workflow...`);
|
|
356
|
+
console.log(colors.dim(` Account: ${config?.account}`));
|
|
357
|
+
console.log(colors.dim(` Network: ${options.network}`));
|
|
358
|
+
console.log();
|
|
356
359
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
force: options.force || false,
|
|
360
|
-
deploy: true,
|
|
361
|
-
});
|
|
360
|
+
if (!options.dryRun) {
|
|
361
|
+
console.log(` ${icons.pkg} Step 1/3: Building & deploying...`);
|
|
362
362
|
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
363
|
+
const buildResult = await client.build({
|
|
364
|
+
packages: pkgs,
|
|
365
|
+
force: options.force || false,
|
|
366
|
+
deploy: true,
|
|
367
|
+
});
|
|
367
368
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
});
|
|
369
|
+
if (buildResult.status === "error") {
|
|
370
|
+
console.error(colors.error(`${icons.err} Build/deploy failed`));
|
|
371
|
+
process.exit(1);
|
|
372
|
+
}
|
|
373
373
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
.option("--dry-run", "Show what would be published without sending")
|
|
380
|
-
.action(async (options) => {
|
|
381
|
-
console.log();
|
|
382
|
-
console.log(` ${icons.pkg} Publishing to Near Social...`);
|
|
383
|
-
console.log(colors.dim(` Account: ${config?.account}`));
|
|
384
|
-
console.log(colors.dim(` Network: ${options.network}`));
|
|
374
|
+
console.log(colors.green(` ${icons.ok} Built & deployed: ${buildResult.built.join(", ")}`));
|
|
375
|
+
console.log();
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
console.log(` ${icons.pkg} ${options.dryRun ? "Dry run:" : "Step 2/3:"} Publishing to Near Social...`);
|
|
385
379
|
|
|
386
380
|
if (options.dryRun) {
|
|
387
381
|
console.log(colors.cyan(` ${icons.scan} Dry run mode - no transaction will be sent`));
|
|
@@ -406,11 +400,12 @@ Zephyr Configuration:
|
|
|
406
400
|
return;
|
|
407
401
|
}
|
|
408
402
|
|
|
409
|
-
console.log();
|
|
410
|
-
console.log(colors.green(`${icons.ok} Published!`));
|
|
403
|
+
console.log(colors.green(` ${icons.ok} Published to Near Social`));
|
|
411
404
|
console.log(` ${colors.dim("TX:")} ${result.txHash}`);
|
|
412
405
|
console.log(` ${colors.dim("URL:")} ${result.registryUrl}`);
|
|
413
406
|
console.log();
|
|
407
|
+
console.log(colors.green(`${icons.ok} Release complete!`));
|
|
408
|
+
console.log();
|
|
414
409
|
});
|
|
415
410
|
|
|
416
411
|
program
|
|
@@ -742,40 +737,38 @@ Zephyr Configuration:
|
|
|
742
737
|
});
|
|
743
738
|
|
|
744
739
|
program
|
|
745
|
-
.command("
|
|
746
|
-
.description("
|
|
747
|
-
.option("--account <account>", "NEAR account to
|
|
748
|
-
.option("--gateway <gateway>", "Gateway domain
|
|
740
|
+
.command("update")
|
|
741
|
+
.description("Update from published config (host prod, secrets, shared deps, UI files)")
|
|
742
|
+
.option("--account <account>", "NEAR account to update from (default: from config)")
|
|
743
|
+
.option("--gateway <gateway>", "Gateway domain (default: from config)")
|
|
749
744
|
.option("--network <network>", "Network: mainnet | testnet", "mainnet")
|
|
750
|
-
.option("--force", "Force
|
|
751
|
-
.
|
|
752
|
-
.action(async (options: { account?: string; gateway?: string; network?: string; force?: boolean; files?: boolean }) => {
|
|
745
|
+
.option("--force", "Force update even if versions match")
|
|
746
|
+
.action(async (options: { account?: string; gateway?: string; network?: string; force?: boolean }) => {
|
|
753
747
|
console.log();
|
|
754
748
|
const gateway = config?.gateway as { production?: string } | undefined;
|
|
755
749
|
const gatewayDomain = gateway?.production?.replace(/^https?:\/\//, "") || "everything.dev";
|
|
756
750
|
const source = `${options.account || config?.account || "every.near"}/${options.gateway || gatewayDomain}`;
|
|
757
751
|
|
|
758
752
|
const s = spinner();
|
|
759
|
-
s.start(`
|
|
753
|
+
s.start(`Updating from ${source}...`);
|
|
760
754
|
|
|
761
|
-
const result = await client.
|
|
755
|
+
const result = await client.update({
|
|
762
756
|
account: options.account,
|
|
763
757
|
gateway: options.gateway,
|
|
764
758
|
network: (options.network as "mainnet" | "testnet") || "mainnet",
|
|
765
759
|
force: options.force || false,
|
|
766
|
-
files: options.files || false,
|
|
767
760
|
});
|
|
768
761
|
|
|
769
762
|
if (result.status === "error") {
|
|
770
|
-
s.stop(colors.error(`${icons.err}
|
|
763
|
+
s.stop(colors.error(`${icons.err} Update failed: ${result.error || "Unknown error"}`));
|
|
771
764
|
process.exit(1);
|
|
772
765
|
}
|
|
773
766
|
|
|
774
|
-
s.stop(colors.green(`${icons.ok}
|
|
767
|
+
s.stop(colors.green(`${icons.ok} Updated from ${source}`));
|
|
775
768
|
|
|
776
769
|
console.log();
|
|
777
770
|
console.log(colors.cyan(frames.top(52)));
|
|
778
|
-
console.log(` ${icons.ok} ${gradients.cyber("
|
|
771
|
+
console.log(` ${icons.ok} ${gradients.cyber("UPDATED")}`);
|
|
779
772
|
console.log(colors.cyan(frames.bottom(52)));
|
|
780
773
|
console.log();
|
|
781
774
|
console.log(` ${colors.dim("Source:")} ${colors.cyan(`${result.account}/${result.gateway}`)}`);
|
|
@@ -793,7 +786,7 @@ Zephyr Configuration:
|
|
|
793
786
|
|
|
794
787
|
if (result.filesSynced && result.filesSynced.length > 0) {
|
|
795
788
|
const totalFiles = result.filesSynced.reduce((sum, pkg) => sum + pkg.files.length, 0);
|
|
796
|
-
console.log(colors.green(` ${icons.ok} Synced ${totalFiles} files`));
|
|
789
|
+
console.log(colors.green(` ${icons.ok} Synced ${totalFiles} UI files`));
|
|
797
790
|
for (const pkg of result.filesSynced) {
|
|
798
791
|
console.log(colors.dim(` ${pkg.package}: ${pkg.files.join(", ")}`));
|
|
799
792
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Box, render, Text, useApp, useInput } from "ink";
|
|
2
2
|
import { useEffect, useState } from "react";
|
|
3
3
|
import { linkify } from "../utils/linkify";
|
|
4
|
-
import { colors, divider, gradients, icons
|
|
4
|
+
import { colors, divider, frames, gradients, icons } from "../utils/theme";
|
|
5
5
|
|
|
6
6
|
export type ProcessStatus = "pending" | "starting" | "ready" | "error";
|
|
7
7
|
|
|
@@ -11,6 +11,7 @@ export interface ProcessState {
|
|
|
11
11
|
port: number;
|
|
12
12
|
message?: string;
|
|
13
13
|
source?: "local" | "remote";
|
|
14
|
+
proxyTarget?: string;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
export interface LogEntry {
|
|
@@ -24,6 +25,7 @@ interface DevViewProps {
|
|
|
24
25
|
processes: ProcessState[];
|
|
25
26
|
logs: LogEntry[];
|
|
26
27
|
description: string;
|
|
28
|
+
proxyTarget?: string;
|
|
27
29
|
onExit?: () => void;
|
|
28
30
|
onExportLogs?: () => void;
|
|
29
31
|
}
|
|
@@ -64,14 +66,14 @@ function ProcessRow({ proc }: { proc: ProcessState }) {
|
|
|
64
66
|
<Text>{" "}</Text>
|
|
65
67
|
<StatusIcon status={proc.status} />
|
|
66
68
|
<Text> </Text>
|
|
67
|
-
<Text color={color} bold>
|
|
69
|
+
<Text color={color} bold>
|
|
70
|
+
{proc.name.toUpperCase().padEnd(6)}
|
|
71
|
+
</Text>
|
|
68
72
|
<Text color="gray">{sourceLabel.padEnd(10)}</Text>
|
|
69
73
|
<Text color={proc.status === "ready" ? "#00ff41" : "gray"}>
|
|
70
74
|
{statusText}
|
|
71
75
|
</Text>
|
|
72
|
-
{proc.port > 0 &&
|
|
73
|
-
<Text color="#00ffff"> {portStr}</Text>
|
|
74
|
-
)}
|
|
76
|
+
{proc.port > 0 && <Text color="#00ffff"> {portStr}</Text>}
|
|
75
77
|
</Box>
|
|
76
78
|
);
|
|
77
79
|
}
|
|
@@ -82,15 +84,33 @@ function LogLine({ entry }: { entry: LogEntry }) {
|
|
|
82
84
|
return (
|
|
83
85
|
<Box>
|
|
84
86
|
<Text color={color}>[{entry.source}]</Text>
|
|
85
|
-
<Text color={entry.isError ? "#ff3366" : undefined}>
|
|
87
|
+
<Text color={entry.isError ? "#ff3366" : undefined}>
|
|
88
|
+
{" "}
|
|
89
|
+
{linkify(entry.line)}
|
|
90
|
+
</Text>
|
|
86
91
|
</Box>
|
|
87
92
|
);
|
|
88
93
|
}
|
|
89
94
|
|
|
95
|
+
function truncateUrl(url: string, maxLen: number): string {
|
|
96
|
+
if (url.length <= maxLen) return url;
|
|
97
|
+
try {
|
|
98
|
+
const parsed = new URL(url);
|
|
99
|
+
const host = parsed.host;
|
|
100
|
+
if (host.length > maxLen - 10) {
|
|
101
|
+
return `${host.slice(0, maxLen - 13)}...`;
|
|
102
|
+
}
|
|
103
|
+
return host;
|
|
104
|
+
} catch {
|
|
105
|
+
return `${url.slice(0, maxLen - 3)}...`;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
90
109
|
function DevView({
|
|
91
110
|
processes,
|
|
92
111
|
logs,
|
|
93
112
|
description,
|
|
113
|
+
proxyTarget,
|
|
94
114
|
onExit,
|
|
95
115
|
onExportLogs,
|
|
96
116
|
}: DevViewProps) {
|
|
@@ -133,14 +153,29 @@ function DevView({
|
|
|
133
153
|
{allReady && (
|
|
134
154
|
<Box marginBottom={1} flexDirection="column">
|
|
135
155
|
<Box>
|
|
136
|
-
<Text color="#00ff41">
|
|
156
|
+
<Text color="#00ff41">
|
|
157
|
+
{" "}
|
|
158
|
+
{icons.app} APP READY
|
|
159
|
+
</Text>
|
|
137
160
|
</Box>
|
|
138
161
|
<Box>
|
|
139
|
-
<Text color="#00ff41" bold>
|
|
162
|
+
<Text color="#00ff41" bold>
|
|
163
|
+
{" "}
|
|
164
|
+
{icons.arrow} http://localhost:{hostPort}
|
|
165
|
+
</Text>
|
|
140
166
|
</Box>
|
|
141
167
|
</Box>
|
|
142
168
|
)}
|
|
143
169
|
|
|
170
|
+
{proxyTarget && (
|
|
171
|
+
<Box marginBottom={1}>
|
|
172
|
+
<Text color="#ffaa00">
|
|
173
|
+
{" "}
|
|
174
|
+
{icons.arrow} API PROXY → {truncateUrl(proxyTarget, 38)}
|
|
175
|
+
</Text>
|
|
176
|
+
</Box>
|
|
177
|
+
)}
|
|
178
|
+
|
|
144
179
|
<Box marginTop={0} marginBottom={0}>
|
|
145
180
|
<Text>{colors.dim(divider(52))}</Text>
|
|
146
181
|
</Box>
|
|
@@ -160,7 +195,10 @@ function DevView({
|
|
|
160
195
|
? `${icons.ok} All ${total} services running`
|
|
161
196
|
: `${icons.scan} ${readyCount}/${total} ready`}
|
|
162
197
|
</Text>
|
|
163
|
-
<Text color="gray">
|
|
198
|
+
<Text color="gray">
|
|
199
|
+
{" "}
|
|
200
|
+
{icons.dot} q quit {icons.dot} l logs
|
|
201
|
+
</Text>
|
|
164
202
|
</Box>
|
|
165
203
|
|
|
166
204
|
{recentLogs.length > 0 && (
|
|
@@ -199,6 +237,7 @@ export function renderDevView(
|
|
|
199
237
|
let processes = [...initialProcesses];
|
|
200
238
|
let logs: LogEntry[] = [];
|
|
201
239
|
let rerender: (() => void) | null = null;
|
|
240
|
+
const proxyTarget = env.API_PROXY;
|
|
202
241
|
|
|
203
242
|
const updateProcess = (
|
|
204
243
|
name: string,
|
|
@@ -232,6 +271,7 @@ export function renderDevView(
|
|
|
232
271
|
processes={processes}
|
|
233
272
|
logs={logs}
|
|
234
273
|
description={description}
|
|
274
|
+
proxyTarget={proxyTarget}
|
|
235
275
|
onExit={onExit}
|
|
236
276
|
onExportLogs={onExportLogs}
|
|
237
277
|
/>
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
1
2
|
import { linkify } from "../utils/linkify";
|
|
2
3
|
import { colors, icons } from "../utils/theme";
|
|
3
4
|
import type { ProcessState, ProcessStatus } from "./dev-view";
|
|
4
5
|
|
|
6
|
+
const orange = chalk.hex("#ffaa00");
|
|
7
|
+
|
|
5
8
|
export interface StreamingViewHandle {
|
|
6
9
|
updateProcess: (name: string, status: ProcessStatus, message?: string) => void;
|
|
7
10
|
addLog: (source: string, line: string, isError?: boolean) => void;
|
|
@@ -34,7 +37,7 @@ const getStatusIcon = (status: ProcessStatus): string => {
|
|
|
34
37
|
export function renderStreamingView(
|
|
35
38
|
initialProcesses: ProcessState[],
|
|
36
39
|
description: string,
|
|
37
|
-
|
|
40
|
+
env: Record<string, string>,
|
|
38
41
|
onExit?: () => void,
|
|
39
42
|
_onExportLogs?: () => void,
|
|
40
43
|
): StreamingViewHandle {
|
|
@@ -46,6 +49,7 @@ export function renderStreamingView(
|
|
|
46
49
|
let allReadyPrinted = false;
|
|
47
50
|
const hostProcess = initialProcesses.find(p => p.name === "host");
|
|
48
51
|
const hostPort = hostProcess?.port || 3000;
|
|
52
|
+
const proxyTarget = env.API_PROXY;
|
|
49
53
|
|
|
50
54
|
console.log();
|
|
51
55
|
console.log(colors.cyan(`${"─".repeat(52)}`));
|
|
@@ -53,6 +57,11 @@ export function renderStreamingView(
|
|
|
53
57
|
console.log(colors.cyan(`${"─".repeat(52)}`));
|
|
54
58
|
console.log();
|
|
55
59
|
|
|
60
|
+
if (proxyTarget) {
|
|
61
|
+
console.log(orange(` ${icons.arrow} API PROXY → ${proxyTarget}`));
|
|
62
|
+
console.log();
|
|
63
|
+
}
|
|
64
|
+
|
|
56
65
|
for (const proc of initialProcesses) {
|
|
57
66
|
const color = getServiceColor(proc.name);
|
|
58
67
|
const sourceLabel = proc.source ? ` (${proc.source})` : "";
|
package/src/config.ts
CHANGED
|
@@ -6,10 +6,11 @@ import type {
|
|
|
6
6
|
HostConfig,
|
|
7
7
|
PortConfig,
|
|
8
8
|
RemoteConfig,
|
|
9
|
+
RuntimeConfig,
|
|
9
10
|
SourceMode,
|
|
10
11
|
} from "./types";
|
|
11
12
|
|
|
12
|
-
export type { AppConfig, BosConfig, GatewayConfig, HostConfig, PortConfig, RemoteConfig, SourceMode };
|
|
13
|
+
export type { AppConfig, BosConfig, GatewayConfig, HostConfig, PortConfig, RemoteConfig, RuntimeConfig, SourceMode };
|
|
13
14
|
|
|
14
15
|
export const DEFAULT_DEV_CONFIG: AppConfig = {
|
|
15
16
|
host: "local",
|
|
@@ -132,14 +133,6 @@ export function getAccount(): string {
|
|
|
132
133
|
return config.account;
|
|
133
134
|
}
|
|
134
135
|
|
|
135
|
-
export function getTitle(): string {
|
|
136
|
-
const config = loadConfig();
|
|
137
|
-
if (!config) {
|
|
138
|
-
throw new Error("No bos.config.json found");
|
|
139
|
-
}
|
|
140
|
-
return config.app.host.title;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
136
|
export function getComponentUrl(
|
|
144
137
|
component: "host" | "ui" | "api",
|
|
145
138
|
source: SourceMode
|
|
@@ -247,3 +240,47 @@ export async function getExistingPackages(packages: string[]): Promise<{ existin
|
|
|
247
240
|
|
|
248
241
|
return { existing, missing };
|
|
249
242
|
}
|
|
243
|
+
|
|
244
|
+
export async function loadBosConfig(
|
|
245
|
+
env: "development" | "production" = "production"
|
|
246
|
+
): Promise<RuntimeConfig> {
|
|
247
|
+
const configPath = process.env.BOS_CONFIG_PATH;
|
|
248
|
+
|
|
249
|
+
let bosConfig: BosConfig;
|
|
250
|
+
if (configPath) {
|
|
251
|
+
const file = Bun.file(configPath);
|
|
252
|
+
const text = await file.text();
|
|
253
|
+
bosConfig = JSON.parse(text) as BosConfig;
|
|
254
|
+
} else {
|
|
255
|
+
const config = loadConfig();
|
|
256
|
+
if (!config) {
|
|
257
|
+
throw new Error("No bos.config.json found");
|
|
258
|
+
}
|
|
259
|
+
bosConfig = config;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
const uiConfig = bosConfig.app.ui as RemoteConfig;
|
|
263
|
+
const apiConfig = bosConfig.app.api as RemoteConfig;
|
|
264
|
+
|
|
265
|
+
return {
|
|
266
|
+
env,
|
|
267
|
+
account: bosConfig.account,
|
|
268
|
+
title: bosConfig.account,
|
|
269
|
+
hostUrl: bosConfig.app.host[env],
|
|
270
|
+
shared: bosConfig.shared,
|
|
271
|
+
ui: {
|
|
272
|
+
name: uiConfig.name,
|
|
273
|
+
url: uiConfig[env],
|
|
274
|
+
ssrUrl: uiConfig.ssr,
|
|
275
|
+
source: "remote",
|
|
276
|
+
},
|
|
277
|
+
api: {
|
|
278
|
+
name: apiConfig.name,
|
|
279
|
+
url: apiConfig[env],
|
|
280
|
+
source: "remote",
|
|
281
|
+
proxy: apiConfig.proxy,
|
|
282
|
+
variables: apiConfig.variables,
|
|
283
|
+
secrets: apiConfig.secrets,
|
|
284
|
+
},
|
|
285
|
+
};
|
|
286
|
+
}
|
package/src/contract.ts
CHANGED
|
@@ -211,16 +211,15 @@ const GatewaySyncResultSchema = z.object({
|
|
|
211
211
|
error: z.string().optional(),
|
|
212
212
|
});
|
|
213
213
|
|
|
214
|
-
const
|
|
214
|
+
const UpdateOptionsSchema = z.object({
|
|
215
215
|
account: z.string().optional(),
|
|
216
216
|
gateway: z.string().optional(),
|
|
217
217
|
network: z.enum(["mainnet", "testnet"]).default("mainnet"),
|
|
218
218
|
force: z.boolean().optional(),
|
|
219
|
-
files: z.boolean().optional(),
|
|
220
219
|
});
|
|
221
220
|
|
|
222
|
-
const
|
|
223
|
-
status: z.enum(["
|
|
221
|
+
const UpdateResultSchema = z.object({
|
|
222
|
+
status: z.enum(["updated", "error"]),
|
|
224
223
|
account: z.string(),
|
|
225
224
|
gateway: z.string(),
|
|
226
225
|
socialUrl: z.string().optional(),
|
|
@@ -500,10 +499,10 @@ export const bosContract = oc.router({
|
|
|
500
499
|
.input(GatewaySyncOptionsSchema)
|
|
501
500
|
.output(GatewaySyncResultSchema),
|
|
502
501
|
|
|
503
|
-
|
|
504
|
-
.route({ method: "POST", path: "/
|
|
505
|
-
.input(
|
|
506
|
-
.output(
|
|
502
|
+
update: oc
|
|
503
|
+
.route({ method: "POST", path: "/update" })
|
|
504
|
+
.input(UpdateOptionsSchema)
|
|
505
|
+
.output(UpdateResultSchema),
|
|
507
506
|
|
|
508
507
|
depsUpdate: oc
|
|
509
508
|
.route({ method: "POST", path: "/deps/update" })
|
|
@@ -580,8 +579,8 @@ export type SecretsDeleteResult = z.infer<typeof SecretsDeleteResultSchema>;
|
|
|
580
579
|
export type LoginOptions = z.infer<typeof LoginOptionsSchema>;
|
|
581
580
|
export type LoginResult = z.infer<typeof LoginResultSchema>;
|
|
582
581
|
export type LogoutResult = z.infer<typeof LogoutResultSchema>;
|
|
583
|
-
export type
|
|
584
|
-
export type
|
|
582
|
+
export type UpdateOptions = z.infer<typeof UpdateOptionsSchema>;
|
|
583
|
+
export type UpdateResult = z.infer<typeof UpdateResultSchema>;
|
|
585
584
|
export type DepsUpdateOptions = z.infer<typeof DepsUpdateOptionsSchema>;
|
|
586
585
|
export type DepsUpdateResult = z.infer<typeof DepsUpdateResultSchema>;
|
|
587
586
|
export type FilesSyncOptions = z.infer<typeof FilesSyncOptionsSchema>;
|