everything-dev 1.3.7 → 1.4.1
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/init.cjs +34 -5
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +10 -7
- package/dist/cli/init.d.cts.map +1 -1
- package/dist/cli/init.d.mts +10 -7
- package/dist/cli/init.d.mts.map +1 -1
- package/dist/cli/init.mjs +34 -6
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/prompts.cjs +19 -9
- package/dist/cli/prompts.cjs.map +1 -1
- package/dist/cli/prompts.mjs +19 -9
- package/dist/cli/prompts.mjs.map +1 -1
- package/dist/cli/snapshot.cjs +35 -0
- package/dist/cli/snapshot.cjs.map +1 -0
- package/dist/cli/snapshot.mjs +33 -0
- package/dist/cli/snapshot.mjs.map +1 -0
- package/dist/cli/status.cjs +80 -0
- package/dist/cli/status.cjs.map +1 -0
- package/dist/cli/status.mjs +79 -0
- package/dist/cli/status.mjs.map +1 -0
- package/dist/cli/sync.cjs +170 -0
- package/dist/cli/sync.cjs.map +1 -0
- package/dist/cli/sync.mjs +169 -0
- package/dist/cli/sync.mjs.map +1 -0
- package/dist/cli/upgrade.cjs +123 -0
- package/dist/cli/upgrade.cjs.map +1 -0
- package/dist/cli/upgrade.mjs +122 -0
- package/dist/cli/upgrade.mjs.map +1 -0
- package/dist/cli.cjs +101 -5
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +101 -5
- package/dist/cli.mjs.map +1 -1
- package/dist/contract.cjs +81 -8
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +162 -21
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +162 -21
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.meta.cjs +32 -9
- package/dist/contract.meta.cjs.map +1 -1
- package/dist/contract.meta.d.cts +50 -11
- package/dist/contract.meta.d.mts +50 -11
- package/dist/contract.meta.mjs +32 -9
- package/dist/contract.meta.mjs.map +1 -1
- package/dist/contract.mjs +77 -9
- package/dist/contract.mjs.map +1 -1
- package/dist/index.cjs +5 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/dist/plugin.cjs +123 -43
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +78 -11
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +78 -11
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +126 -46
- package/dist/plugin.mjs.map +1 -1
- package/dist/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- package/dist/utils/theme.cjs +1 -0
- package/dist/utils/theme.cjs.map +1 -1
- package/dist/utils/theme.mjs +1 -0
- package/dist/utils/theme.mjs.map +1 -1
- package/package.json +1 -1
- package/src/cli/init.ts +60 -11
- package/src/cli/prompts.ts +34 -16
- package/src/cli/snapshot.ts +46 -0
- package/src/cli/status.ts +85 -0
- package/src/cli/sync.ts +239 -0
- package/src/cli/upgrade.ts +165 -0
- package/src/cli.ts +152 -5
- package/src/contract.meta.ts +36 -6
- package/src/contract.ts +74 -7
- package/src/plugin.ts +156 -45
- package/src/utils/theme.ts +1 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import type { UpgradeOptions, UpgradeResult } from "../contract";
|
|
4
|
+
import { runBunInstall } from "./init";
|
|
5
|
+
import { syncTemplate } from "./sync";
|
|
6
|
+
|
|
7
|
+
const FRAMEWORK_PACKAGES = ["everything-dev", "every-plugin"];
|
|
8
|
+
|
|
9
|
+
interface NpmPackageInfo {
|
|
10
|
+
version: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function fetchLatestNpmVersion(packageName: string): Promise<string | null> {
|
|
14
|
+
try {
|
|
15
|
+
const response = await fetch(`https://registry.npmjs.org/${packageName}/latest`, {
|
|
16
|
+
headers: { Accept: "application/json" },
|
|
17
|
+
signal: AbortSignal.timeout(10_000),
|
|
18
|
+
});
|
|
19
|
+
if (!response.ok) return null;
|
|
20
|
+
const data = (await response.json()) as NpmPackageInfo;
|
|
21
|
+
return data.version;
|
|
22
|
+
} catch {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function readInstalledVersion(projectDir: string, packageName: string): string | undefined {
|
|
28
|
+
const pkgPath = join(projectDir, "package.json");
|
|
29
|
+
if (!existsSync(pkgPath)) return undefined;
|
|
30
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")) as Record<string, unknown>;
|
|
31
|
+
const deps = (pkg.dependencies ?? {}) as Record<string, string>;
|
|
32
|
+
const devDeps = (pkg.devDependencies ?? {}) as Record<string, string>;
|
|
33
|
+
const version = deps[packageName] || devDeps[packageName];
|
|
34
|
+
if (!version) return undefined;
|
|
35
|
+
return version.replace(/^[\^~>=]+/, "");
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function updatePackageVersion(projectDir: string, packageName: string, newVersion: string): void {
|
|
39
|
+
const pkgPath = join(projectDir, "package.json");
|
|
40
|
+
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")) as Record<string, unknown>;
|
|
41
|
+
|
|
42
|
+
if (pkg.dependencies && typeof pkg.dependencies === "object") {
|
|
43
|
+
const deps = pkg.dependencies as Record<string, string>;
|
|
44
|
+
if (deps[packageName] !== undefined) {
|
|
45
|
+
deps[packageName] = `^${newVersion}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (pkg.devDependencies && typeof pkg.devDependencies === "object") {
|
|
50
|
+
const deps = pkg.devDependencies as Record<string, string>;
|
|
51
|
+
if (deps[packageName] !== undefined) {
|
|
52
|
+
deps[packageName] = `^${newVersion}`;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function buildChangelogUrl(
|
|
60
|
+
oldVersion: string | undefined,
|
|
61
|
+
newVersion: string,
|
|
62
|
+
parentConfig: Record<string, unknown> | null,
|
|
63
|
+
): string | undefined {
|
|
64
|
+
if (!oldVersion || oldVersion === newVersion) return undefined;
|
|
65
|
+
const repoUrl = parentConfig?.repository as string | undefined;
|
|
66
|
+
if (!repoUrl) return undefined;
|
|
67
|
+
|
|
68
|
+
const githubMatch = repoUrl.match(/^https?:\/\/github\.com\/([^/]+)\/([^/]+?)(?:\.git)?$/);
|
|
69
|
+
if (!githubMatch) return undefined;
|
|
70
|
+
|
|
71
|
+
const [, owner, repo] = githubMatch;
|
|
72
|
+
return `https://github.com/${owner}/${repo}/compare/v${oldVersion}...v${newVersion}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export async function upgradeTemplate(
|
|
76
|
+
projectDir: string,
|
|
77
|
+
options: UpgradeOptions,
|
|
78
|
+
): Promise<UpgradeResult> {
|
|
79
|
+
const pkgPath = join(projectDir, "package.json");
|
|
80
|
+
if (!existsSync(pkgPath)) {
|
|
81
|
+
return {
|
|
82
|
+
status: "error",
|
|
83
|
+
packages: [],
|
|
84
|
+
error: "No package.json found in current directory",
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const packages: UpgradeResult["packages"] = [];
|
|
89
|
+
|
|
90
|
+
for (const name of FRAMEWORK_PACKAGES) {
|
|
91
|
+
const installed = readInstalledVersion(projectDir, name);
|
|
92
|
+
const latest = await fetchLatestNpmVersion(name);
|
|
93
|
+
|
|
94
|
+
if (!latest) {
|
|
95
|
+
packages.push({ name, from: installed, to: installed ?? "unknown" });
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
packages.push({ name, from: installed, to: latest });
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const hasUpdates = packages.some((p) => p.from !== p.to && p.from !== undefined);
|
|
103
|
+
|
|
104
|
+
if (options.dryRun) {
|
|
105
|
+
let changelogUrl: string | undefined;
|
|
106
|
+
if (hasUpdates) {
|
|
107
|
+
const configPath = join(projectDir, "bos.config.json");
|
|
108
|
+
let parentConfig: Record<string, unknown> | null = null;
|
|
109
|
+
if (existsSync(configPath)) {
|
|
110
|
+
try {
|
|
111
|
+
parentConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
112
|
+
} catch {}
|
|
113
|
+
}
|
|
114
|
+
const mainPkg = packages.find((p) => p.name === "everything-dev");
|
|
115
|
+
if (mainPkg?.from && mainPkg.from !== mainPkg.to) {
|
|
116
|
+
changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return {
|
|
121
|
+
status: "dry-run",
|
|
122
|
+
packages,
|
|
123
|
+
changelogUrl,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
for (const pkg of packages) {
|
|
128
|
+
if (pkg.from !== undefined && pkg.from !== pkg.to) {
|
|
129
|
+
updatePackageVersion(projectDir, pkg.name, pkg.to);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (hasUpdates && !options.noInstall) {
|
|
134
|
+
await runBunInstall(projectDir);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
let syncResult: UpgradeResult["sync"];
|
|
138
|
+
if (!options.noSync) {
|
|
139
|
+
syncResult = await syncTemplate(projectDir, {
|
|
140
|
+
dryRun: false,
|
|
141
|
+
force: options.force,
|
|
142
|
+
noInstall: true,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
let changelogUrl: string | undefined;
|
|
147
|
+
const mainPkg = packages.find((p) => p.name === "everything-dev");
|
|
148
|
+
if (mainPkg?.from && mainPkg.from !== mainPkg.to) {
|
|
149
|
+
const configPath = join(projectDir, "bos.config.json");
|
|
150
|
+
let parentConfig: Record<string, unknown> | null = null;
|
|
151
|
+
if (existsSync(configPath)) {
|
|
152
|
+
try {
|
|
153
|
+
parentConfig = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
154
|
+
} catch {}
|
|
155
|
+
}
|
|
156
|
+
changelogUrl = buildChangelogUrl(mainPkg.from, mainPkg.to, parentConfig);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
status: "upgraded",
|
|
161
|
+
packages,
|
|
162
|
+
sync: syncResult,
|
|
163
|
+
changelogUrl,
|
|
164
|
+
};
|
|
165
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -32,6 +32,20 @@ function printConfigView(result: {
|
|
|
32
32
|
console.log();
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function formatTimeAgo(isoTimestamp: string): string {
|
|
36
|
+
const now = Date.now();
|
|
37
|
+
const then = new Date(isoTimestamp).getTime();
|
|
38
|
+
const diffMs = now - then;
|
|
39
|
+
const diffMins = Math.floor(diffMs / 60_000);
|
|
40
|
+
if (diffMins < 1) return "just now";
|
|
41
|
+
if (diffMins < 60) return `${diffMins} minute${diffMins > 1 ? "s" : ""} ago`;
|
|
42
|
+
const diffHours = Math.floor(diffMins / 60);
|
|
43
|
+
if (diffHours < 24) return `${diffHours} hour${diffHours > 1 ? "s" : ""} ago`;
|
|
44
|
+
const diffDays = Math.floor(diffHours / 24);
|
|
45
|
+
if (diffDays < 30) return `${diffDays} day${diffDays > 1 ? "s" : ""} ago`;
|
|
46
|
+
return isoTimestamp.split("T")[0] ?? isoTimestamp;
|
|
47
|
+
}
|
|
48
|
+
|
|
35
49
|
async function main() {
|
|
36
50
|
const args = process.argv.slice(2);
|
|
37
51
|
|
|
@@ -96,18 +110,151 @@ async function main() {
|
|
|
96
110
|
}
|
|
97
111
|
console.log(colors.green(`${icons.ok} Project initialized`));
|
|
98
112
|
console.log(` ${colors.dim("Extends:")} ${result.extends}`);
|
|
99
|
-
console.log(` ${colors.dim("
|
|
100
|
-
if (result.
|
|
113
|
+
console.log(` ${colors.dim("Directory:")} ${result.directory}`);
|
|
114
|
+
if (result.account) console.log(` ${colors.dim("Account:")} ${result.account}`);
|
|
101
115
|
if (result.domain) console.log(` ${colors.dim("Domain:")} ${result.domain}`);
|
|
102
116
|
console.log(` ${colors.dim("Files copied:")} ${result.filesCopied}`);
|
|
103
117
|
console.log();
|
|
104
118
|
console.log(colors.dim(" Next steps:"));
|
|
105
|
-
console.log(colors.dim(` cd ${result.
|
|
119
|
+
console.log(colors.dim(` cd ${result.directory}`));
|
|
120
|
+
console.log(colors.dim(" cp .env.example .env # then fill in your values"));
|
|
106
121
|
if (result.status === "initialized" && !(input as any)?.noInstall) {
|
|
107
|
-
console.log(colors.dim("
|
|
122
|
+
console.log(colors.dim(" bun run dev"));
|
|
108
123
|
} else {
|
|
109
124
|
console.log(colors.dim(" bun install"));
|
|
110
|
-
console.log(colors.dim("
|
|
125
|
+
console.log(colors.dim(" bun run dev"));
|
|
126
|
+
}
|
|
127
|
+
console.log();
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (descriptor.key === "sync") {
|
|
132
|
+
console.log();
|
|
133
|
+
if (result.status === "error") {
|
|
134
|
+
console.error(`[CLI] ${result.error || "Unknown error"}`);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
if (result.status === "dry-run") {
|
|
138
|
+
console.log(colors.cyan(`${icons.ok} Dry run — no files written`));
|
|
139
|
+
} else {
|
|
140
|
+
console.log(colors.green(`${icons.ok} Template synced`));
|
|
141
|
+
}
|
|
142
|
+
if (result.updated.length > 0) {
|
|
143
|
+
console.log(` ${colors.dim("Updated:")} ${result.updated.length} file(s)`);
|
|
144
|
+
for (const f of result.updated) console.log(` ${colors.dim(f)}`);
|
|
145
|
+
}
|
|
146
|
+
if (result.added.length > 0) {
|
|
147
|
+
console.log(` ${colors.dim("Added:")} ${result.added.length} file(s)`);
|
|
148
|
+
for (const f of result.added) console.log(` ${colors.dim(f)}`);
|
|
149
|
+
}
|
|
150
|
+
if (result.skipped.length > 0) {
|
|
151
|
+
console.log(
|
|
152
|
+
` ${colors.yellow("Skipped:")} ${result.skipped.length} file(s) (locally modified, use --force to overwrite)`,
|
|
153
|
+
);
|
|
154
|
+
for (const f of result.skipped) console.log(` ${colors.dim(f)}`);
|
|
155
|
+
}
|
|
156
|
+
if (result.updated.length === 0 && result.added.length === 0 && result.skipped.length === 0) {
|
|
157
|
+
console.log(` ${colors.dim("Already up to date")}`);
|
|
158
|
+
}
|
|
159
|
+
console.log();
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (descriptor.key === "upgrade") {
|
|
164
|
+
console.log();
|
|
165
|
+
if (result.status === "error") {
|
|
166
|
+
console.error(`[CLI] ${result.error || "Unknown error"}`);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
}
|
|
169
|
+
if (result.status === "dry-run") {
|
|
170
|
+
console.log(colors.cyan(`${icons.ok} Dry run — no changes applied`));
|
|
171
|
+
} else {
|
|
172
|
+
console.log(colors.green(`${icons.ok} Framework upgraded`));
|
|
173
|
+
}
|
|
174
|
+
for (const pkg of result.packages) {
|
|
175
|
+
if (pkg.from && pkg.from !== pkg.to) {
|
|
176
|
+
console.log(` ${colors.dim(`${pkg.name}:`)} ${pkg.from} → ${pkg.to}`);
|
|
177
|
+
} else if (!pkg.from) {
|
|
178
|
+
console.log(` ${colors.dim(`${pkg.name}:`)} ${pkg.to} (new)`);
|
|
179
|
+
} else {
|
|
180
|
+
console.log(` ${colors.dim(`${pkg.name}:`)} ${pkg.to} (up to date)`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (result.changelogUrl) {
|
|
184
|
+
console.log(` ${colors.dim("Changelog:")} ${result.changelogUrl}`);
|
|
185
|
+
}
|
|
186
|
+
if (result.sync) {
|
|
187
|
+
const sync = result.sync;
|
|
188
|
+
if (sync.updated.length > 0) {
|
|
189
|
+
console.log(` ${colors.dim("Synced updated:")} ${sync.updated.length} file(s)`);
|
|
190
|
+
}
|
|
191
|
+
if (sync.added.length > 0) {
|
|
192
|
+
console.log(` ${colors.dim("Synced added:")} ${sync.added.length} file(s)`);
|
|
193
|
+
}
|
|
194
|
+
if (sync.skipped.length > 0) {
|
|
195
|
+
console.log(
|
|
196
|
+
` ${colors.yellow("Synced skipped:")} ${sync.skipped.length} file(s) (locally modified, use --force to overwrite)`,
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
console.log();
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (descriptor.key === "status") {
|
|
205
|
+
console.log();
|
|
206
|
+
if (result.status === "error") {
|
|
207
|
+
console.error(`[CLI] ${result.error || "Unknown error"}`);
|
|
208
|
+
process.exit(1);
|
|
209
|
+
}
|
|
210
|
+
console.log(colors.cyan(frames.top(52)));
|
|
211
|
+
console.log(` ${icons.app} ${gradients.cyber("STATUS")}`);
|
|
212
|
+
console.log(colors.cyan(frames.bottom(52)));
|
|
213
|
+
console.log();
|
|
214
|
+
if (result.extends) console.log(` ${colors.dim("Extends:")} ${result.extends}`);
|
|
215
|
+
if (result.account) console.log(` ${colors.dim("Account:")} ${result.account}`);
|
|
216
|
+
if (result.domain) console.log(` ${colors.dim("Domain:")} ${result.domain}`);
|
|
217
|
+
console.log();
|
|
218
|
+
console.log(` ${colors.dim("Packages:")}`);
|
|
219
|
+
for (const pkg of result.packages) {
|
|
220
|
+
const hasUpdate = pkg.installed && pkg.latest && pkg.installed !== pkg.latest;
|
|
221
|
+
const versionStr = hasUpdate
|
|
222
|
+
? `${pkg.installed} → ${pkg.latest}`
|
|
223
|
+
: pkg.installed || "not installed";
|
|
224
|
+
const label = hasUpdate ? colors.yellow(versionStr) : colors.dim(versionStr);
|
|
225
|
+
console.log(` ${colors.dim(`${pkg.name}`)} ${label}`);
|
|
226
|
+
}
|
|
227
|
+
console.log();
|
|
228
|
+
if (result.lastSync) {
|
|
229
|
+
const ago = formatTimeAgo(result.lastSync);
|
|
230
|
+
console.log(` ${colors.dim("Last sync:")} ${ago}`);
|
|
231
|
+
} else {
|
|
232
|
+
console.log(` ${colors.dim("Last sync:")} never`);
|
|
233
|
+
}
|
|
234
|
+
const envLabel =
|
|
235
|
+
result.envFile === "found"
|
|
236
|
+
? colors.green("found")
|
|
237
|
+
: result.envFile === "example-only"
|
|
238
|
+
? colors.yellow("missing (only .env.example found)")
|
|
239
|
+
: colors.error("missing");
|
|
240
|
+
console.log(` ${colors.dim(".env:")} ${envLabel}`);
|
|
241
|
+
if (result.parentReachable !== undefined) {
|
|
242
|
+
const parentLabel = result.parentReachable
|
|
243
|
+
? colors.green("reachable")
|
|
244
|
+
: colors.error("unreachable");
|
|
245
|
+
console.log(` ${colors.dim("Parent:")} ${parentLabel}`);
|
|
246
|
+
}
|
|
247
|
+
const hasUpdates = result.packages.some(
|
|
248
|
+
(p: { installed?: string; latest?: string }) =>
|
|
249
|
+
p.installed && p.latest && p.installed !== p.latest,
|
|
250
|
+
);
|
|
251
|
+
if (hasUpdates) {
|
|
252
|
+
console.log();
|
|
253
|
+
console.log(
|
|
254
|
+
colors.dim(
|
|
255
|
+
` Run ${colors.cyan("bos upgrade")} to update packages and sync template files.`,
|
|
256
|
+
),
|
|
257
|
+
);
|
|
111
258
|
}
|
|
112
259
|
console.log();
|
|
113
260
|
return;
|
package/src/contract.meta.ts
CHANGED
|
@@ -79,18 +79,48 @@ export const cliCommandMeta = {
|
|
|
79
79
|
summary: "Scaffold a new project from a bos template",
|
|
80
80
|
interactive: true,
|
|
81
81
|
fields: {
|
|
82
|
-
|
|
82
|
+
domain: {
|
|
83
83
|
positional: true,
|
|
84
|
-
description: "
|
|
84
|
+
description: "New project domain (e.g. ironclaw.everything.dev)",
|
|
85
85
|
},
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
account: { description: "New project NEAR account (auto-derived from domain)" },
|
|
87
|
+
extendsAccount: {
|
|
88
|
+
description: "Parent NEAR account to extend from (defaults to dev.everything.near)",
|
|
89
|
+
},
|
|
90
|
+
extendsGateway: {
|
|
91
|
+
description: "Parent gateway to extend from (defaults to everything.dev)",
|
|
92
|
+
},
|
|
93
|
+
directory: { description: "Target directory (auto-derived from domain)" },
|
|
90
94
|
source: { description: "Local source dir (skips GitHub download)" },
|
|
91
95
|
withHost: { description: "Include host/ in template output" },
|
|
92
96
|
noInteractive: { description: "Skip prompts, use flags only" },
|
|
93
97
|
noInstall: { description: "Skip bun install" },
|
|
94
98
|
},
|
|
95
99
|
},
|
|
100
|
+
sync: {
|
|
101
|
+
commandPath: ["sync"],
|
|
102
|
+
summary: "Sync template files from parent project",
|
|
103
|
+
interactive: false,
|
|
104
|
+
fields: {
|
|
105
|
+
dryRun: { description: "Preview changes without writing files" },
|
|
106
|
+
force: { description: "Overwrite user-modified files" },
|
|
107
|
+
noInstall: { description: "Skip bun install" },
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
upgrade: {
|
|
111
|
+
commandPath: ["upgrade"],
|
|
112
|
+
summary: "Upgrade framework packages and sync template files",
|
|
113
|
+
interactive: false,
|
|
114
|
+
fields: {
|
|
115
|
+
dryRun: { description: "Preview changes without writing" },
|
|
116
|
+
force: { description: "Overwrite user-modified files during sync" },
|
|
117
|
+
noInstall: { description: "Skip bun install" },
|
|
118
|
+
noSync: { description: "Only upgrade packages, skip template sync" },
|
|
119
|
+
},
|
|
120
|
+
},
|
|
121
|
+
status: {
|
|
122
|
+
commandPath: ["status"],
|
|
123
|
+
summary: "Show project health, versions, and update availability",
|
|
124
|
+
interactive: false,
|
|
125
|
+
},
|
|
96
126
|
} as const satisfies Record<string, CliCommandMeta>;
|
package/src/contract.ts
CHANGED
|
@@ -134,10 +134,10 @@ export const KeyPublishResultSchema = z.object({
|
|
|
134
134
|
});
|
|
135
135
|
|
|
136
136
|
export const InitOptionsSchema = z.object({
|
|
137
|
+
extendsAccount: z.string().optional(),
|
|
138
|
+
extendsGateway: z.string().optional(),
|
|
139
|
+
directory: z.string().optional(),
|
|
137
140
|
account: z.string().optional(),
|
|
138
|
-
gateway: z.string().optional(),
|
|
139
|
-
destination: z.string().optional(),
|
|
140
|
-
name: z.string().optional(),
|
|
141
141
|
domain: z.string().optional(),
|
|
142
142
|
source: z.string().optional(),
|
|
143
143
|
withHost: z.boolean().default(false),
|
|
@@ -147,16 +147,69 @@ export const InitOptionsSchema = z.object({
|
|
|
147
147
|
|
|
148
148
|
export const InitResultSchema = z.object({
|
|
149
149
|
status: z.enum(["initialized", "error"]),
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
150
|
+
directory: z.string(),
|
|
151
|
+
extendsAccount: z.string(),
|
|
152
|
+
extendsGateway: z.string(),
|
|
153
|
+
account: z.string().optional(),
|
|
154
154
|
domain: z.string().optional(),
|
|
155
155
|
extends: z.string(),
|
|
156
156
|
filesCopied: z.number(),
|
|
157
157
|
error: z.string().optional(),
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
+
export const SyncOptionsSchema = z.object({
|
|
161
|
+
dryRun: z.boolean().default(false),
|
|
162
|
+
force: z.boolean().default(false),
|
|
163
|
+
noInstall: z.boolean().default(false),
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
export const SyncResultSchema = z.object({
|
|
167
|
+
status: z.enum(["synced", "dry-run", "error"]),
|
|
168
|
+
updated: z.array(z.string()),
|
|
169
|
+
skipped: z.array(z.string()),
|
|
170
|
+
added: z.array(z.string()),
|
|
171
|
+
error: z.string().optional(),
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
export const UpgradeOptionsSchema = z.object({
|
|
175
|
+
dryRun: z.boolean().default(false),
|
|
176
|
+
force: z.boolean().default(false),
|
|
177
|
+
noInstall: z.boolean().default(false),
|
|
178
|
+
noSync: z.boolean().default(false),
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
export const UpgradeResultSchema = z.object({
|
|
182
|
+
status: z.enum(["upgraded", "dry-run", "error"]),
|
|
183
|
+
packages: z.array(
|
|
184
|
+
z.object({
|
|
185
|
+
name: z.string(),
|
|
186
|
+
from: z.string().optional(),
|
|
187
|
+
to: z.string(),
|
|
188
|
+
}),
|
|
189
|
+
),
|
|
190
|
+
sync: SyncResultSchema.optional(),
|
|
191
|
+
changelogUrl: z.string().optional(),
|
|
192
|
+
error: z.string().optional(),
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
export const StatusResultSchema = z.object({
|
|
196
|
+
status: z.enum(["ok", "error"]),
|
|
197
|
+
extends: z.string().optional(),
|
|
198
|
+
account: z.string().optional(),
|
|
199
|
+
domain: z.string().optional(),
|
|
200
|
+
packages: z.array(
|
|
201
|
+
z.object({
|
|
202
|
+
name: z.string(),
|
|
203
|
+
installed: z.string().optional(),
|
|
204
|
+
latest: z.string().optional(),
|
|
205
|
+
}),
|
|
206
|
+
),
|
|
207
|
+
lastSync: z.string().optional(),
|
|
208
|
+
envFile: z.enum(["found", "missing", "example-only"]),
|
|
209
|
+
parentReachable: z.boolean().optional(),
|
|
210
|
+
error: z.string().optional(),
|
|
211
|
+
});
|
|
212
|
+
|
|
160
213
|
export const bosContract = oc.router({
|
|
161
214
|
dev: oc.route({ method: "POST", path: "/dev" }).input(DevOptionsSchema).output(DevResultSchema),
|
|
162
215
|
start: oc
|
|
@@ -193,6 +246,15 @@ export const bosContract = oc.router({
|
|
|
193
246
|
.route({ method: "POST", path: "/init" })
|
|
194
247
|
.input(InitOptionsSchema)
|
|
195
248
|
.output(InitResultSchema),
|
|
249
|
+
sync: oc
|
|
250
|
+
.route({ method: "POST", path: "/sync" })
|
|
251
|
+
.input(SyncOptionsSchema)
|
|
252
|
+
.output(SyncResultSchema),
|
|
253
|
+
upgrade: oc
|
|
254
|
+
.route({ method: "POST", path: "/upgrade" })
|
|
255
|
+
.input(UpgradeOptionsSchema)
|
|
256
|
+
.output(UpgradeResultSchema),
|
|
257
|
+
status: oc.route({ method: "GET", path: "/status" }).output(StatusResultSchema),
|
|
196
258
|
});
|
|
197
259
|
|
|
198
260
|
export type DevOptions = z.infer<typeof DevOptionsSchema>;
|
|
@@ -211,3 +273,8 @@ export type KeyPublishOptions = z.infer<typeof KeyPublishOptionsSchema>;
|
|
|
211
273
|
export type KeyPublishResult = z.infer<typeof KeyPublishResultSchema>;
|
|
212
274
|
export type InitOptions = z.infer<typeof InitOptionsSchema>;
|
|
213
275
|
export type InitResult = z.infer<typeof InitResultSchema>;
|
|
276
|
+
export type SyncOptions = z.infer<typeof SyncOptionsSchema>;
|
|
277
|
+
export type SyncResult = z.infer<typeof SyncResultSchema>;
|
|
278
|
+
export type UpgradeOptions = z.infer<typeof UpgradeOptionsSchema>;
|
|
279
|
+
export type UpgradeResult = z.infer<typeof UpgradeResultSchema>;
|
|
280
|
+
export type StatusResult = z.infer<typeof StatusResultSchema>;
|