everything-dev 1.27.0 → 1.28.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/infra.cjs +1 -1
- package/dist/cli/infra.mjs +1 -1
- package/dist/cli/init.cjs +34 -9
- package/dist/cli/init.cjs.map +1 -1
- package/dist/cli/init.d.cts +2 -1
- package/dist/cli/init.d.cts.map +1 -1
- package/dist/cli/init.d.mts +2 -1
- package/dist/cli/init.d.mts.map +1 -1
- package/dist/cli/init.mjs +34 -9
- package/dist/cli/init.mjs.map +1 -1
- package/dist/cli/prompts.cjs +28 -24
- package/dist/cli/prompts.cjs.map +1 -1
- package/dist/cli/prompts.mjs +27 -24
- package/dist/cli/prompts.mjs.map +1 -1
- package/dist/cli/sync.cjs +40 -3
- package/dist/cli/sync.cjs.map +1 -1
- package/dist/cli/sync.mjs +40 -3
- package/dist/cli/sync.mjs.map +1 -1
- package/dist/cli.cjs +187 -12
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.mjs +186 -11
- package/dist/cli.mjs.map +1 -1
- package/dist/config.cjs +1 -0
- package/dist/config.cjs.map +1 -1
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +1 -0
- package/dist/config.mjs.map +1 -1
- package/dist/contract.cjs +1 -1
- package/dist/contract.cjs.map +1 -1
- package/dist/contract.d.cts +38 -34
- package/dist/contract.d.cts.map +1 -1
- package/dist/contract.d.mts +38 -34
- package/dist/contract.d.mts.map +1 -1
- package/dist/contract.mjs +1 -0
- package/dist/contract.mjs.map +1 -1
- package/dist/dev-session.cjs +0 -1
- package/dist/dev-session.mjs +1 -1
- package/dist/index.cjs +0 -2
- package/dist/index.d.cts +2 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +0 -1
- package/dist/near-cli.cjs +1 -1
- package/dist/near-cli.mjs +1 -1
- package/dist/orchestrator.cjs +1 -1
- package/dist/orchestrator.mjs +1 -1
- package/dist/plugin.cjs +183 -151
- package/dist/plugin.cjs.map +1 -1
- package/dist/plugin.d.cts +67 -34
- package/dist/plugin.d.cts.map +1 -1
- package/dist/plugin.d.mts +66 -34
- package/dist/plugin.d.mts.map +1 -1
- package/dist/plugin.mjs +173 -142
- package/dist/plugin.mjs.map +1 -1
- package/dist/service-descriptor.d.cts +34 -0
- package/dist/service-descriptor.d.cts.map +1 -0
- package/dist/service-descriptor.d.mts +36 -0
- package/dist/service-descriptor.d.mts.map +1 -0
- package/dist/types.d.cts +2 -2
- package/dist/types.d.mts +2 -2
- package/dist/utils/run.cjs +9 -20
- package/dist/utils/run.cjs.map +1 -1
- package/dist/utils/run.mjs +9 -20
- package/dist/utils/run.mjs.map +1 -1
- package/package.json +2 -2
- package/src/api-contract.ts +0 -623
- package/src/app.ts +0 -193
- package/src/cli/catalog.ts +0 -49
- package/src/cli/framework-version.ts +0 -61
- package/src/cli/help.ts +0 -13
- package/src/cli/infra.ts +0 -190
- package/src/cli/init.ts +0 -1145
- package/src/cli/parse.ts +0 -147
- package/src/cli/prompts.ts +0 -135
- package/src/cli/snapshot.ts +0 -46
- package/src/cli/status.ts +0 -99
- package/src/cli/sync.ts +0 -429
- package/src/cli/timing.ts +0 -63
- package/src/cli/upgrade.ts +0 -869
- package/src/cli.ts +0 -516
- package/src/components/dev-view.tsx +0 -352
- package/src/components/streaming-view.ts +0 -177
- package/src/config.ts +0 -893
- package/src/contract.meta.ts +0 -140
- package/src/contract.ts +0 -326
- package/src/dev-logs.ts +0 -92
- package/src/dev-session.ts +0 -283
- package/src/fastkv.ts +0 -181
- package/src/index.ts +0 -8
- package/src/integrity.ts +0 -138
- package/src/internal/manifest-normalizer.ts +0 -290
- package/src/merge.ts +0 -187
- package/src/mf.ts +0 -147
- package/src/near-cli.ts +0 -259
- package/src/network.ts +0 -3
- package/src/orchestrator.ts +0 -493
- package/src/plugin.ts +0 -1799
- package/src/sdk.ts +0 -14
- package/src/service-descriptor.ts +0 -281
- package/src/shared.ts +0 -249
- package/src/sidebar.ts +0 -140
- package/src/types.ts +0 -330
- package/src/ui/head.ts +0 -83
- package/src/ui/index.ts +0 -5
- package/src/ui/metadata.ts +0 -95
- package/src/ui/router.ts +0 -88
- package/src/ui/runtime.ts +0 -42
- package/src/ui/types.ts +0 -65
- package/src/utils/banner.ts +0 -21
- package/src/utils/linkify.ts +0 -11
- package/src/utils/path-match.ts +0 -16
- package/src/utils/run.ts +0 -31
- package/src/utils/save-config.ts +0 -20
- package/src/utils/theme.ts +0 -39
package/src/cli/sync.ts
DELETED
|
@@ -1,429 +0,0 @@
|
|
|
1
|
-
import { createHash } from "node:crypto";
|
|
2
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
import { loadConfig } from "../config";
|
|
5
|
-
import type { SyncOptions, SyncResult } from "../contract";
|
|
6
|
-
import {
|
|
7
|
-
isPlainObject as isPlainObjectFromMerge,
|
|
8
|
-
mergeBosConfigWithTemplate,
|
|
9
|
-
resolveExtendsRef,
|
|
10
|
-
} from "../merge";
|
|
11
|
-
import { writeGeneratedInfra } from "./infra";
|
|
12
|
-
import {
|
|
13
|
-
personalizeConfig,
|
|
14
|
-
resolveSourceDir,
|
|
15
|
-
runBunInstall,
|
|
16
|
-
runTypesGen,
|
|
17
|
-
sourcePathToDestinationPath,
|
|
18
|
-
} from "./init";
|
|
19
|
-
import { writeSnapshot } from "./snapshot";
|
|
20
|
-
|
|
21
|
-
const FRAMEWORK_OWNED_SYNC_FILES = new Set([
|
|
22
|
-
".env.example",
|
|
23
|
-
".gitignore",
|
|
24
|
-
"AGENTS.md",
|
|
25
|
-
"biome.json",
|
|
26
|
-
"bos.config.json",
|
|
27
|
-
"bunfig.toml",
|
|
28
|
-
"CONTRIBUTING.md",
|
|
29
|
-
"package.json",
|
|
30
|
-
".changeset/config.json",
|
|
31
|
-
".changeset/README.md",
|
|
32
|
-
"docker-compose.yml",
|
|
33
|
-
".github/renovate.json",
|
|
34
|
-
".github/workflows/ci.yml",
|
|
35
|
-
".github/workflows/release-sync.yml",
|
|
36
|
-
".opencode/skills/everything-dev/SKILL.md",
|
|
37
|
-
"ui/package.json",
|
|
38
|
-
"ui/postcss.config.mjs",
|
|
39
|
-
"ui/rsbuild.config.ts",
|
|
40
|
-
"ui/tsconfig.json",
|
|
41
|
-
"ui/src/app.ts",
|
|
42
|
-
"ui/src/globals.d.ts",
|
|
43
|
-
"ui/src/hydrate.tsx",
|
|
44
|
-
"ui/src/lib/api.ts",
|
|
45
|
-
"ui/src/lib/auth.ts",
|
|
46
|
-
"ui/src/router.server.tsx",
|
|
47
|
-
"ui/src/router.tsx",
|
|
48
|
-
"ui/src/routes/__root.tsx",
|
|
49
|
-
"api/package.json",
|
|
50
|
-
"api/plugin.dev.ts",
|
|
51
|
-
"api/rspack.config.js",
|
|
52
|
-
"api/tsconfig.contract.json",
|
|
53
|
-
"api/tsconfig.json",
|
|
54
|
-
"api/src/lib/auth.ts",
|
|
55
|
-
]);
|
|
56
|
-
|
|
57
|
-
type PackageJson = Record<string, unknown>;
|
|
58
|
-
|
|
59
|
-
export function isFrameworkOwnedSyncFile(filePath: string): boolean {
|
|
60
|
-
return FRAMEWORK_OWNED_SYNC_FILES.has(filePath);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function computeLocalHash(projectDir: string, filePath: string): string | null {
|
|
64
|
-
const fullPath = join(projectDir, filePath);
|
|
65
|
-
if (!existsSync(fullPath)) return null;
|
|
66
|
-
try {
|
|
67
|
-
const content = readFileSync(fullPath);
|
|
68
|
-
return createHash("sha256").update(content).digest("hex").substring(0, 16);
|
|
69
|
-
} catch {
|
|
70
|
-
return null;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function backupFiles(projectDir: string, filePaths: string[]): string | null {
|
|
75
|
-
const filesToBackup = filePaths.filter((f) => existsSync(join(projectDir, f)));
|
|
76
|
-
if (filesToBackup.length === 0) return null;
|
|
77
|
-
|
|
78
|
-
const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
|
|
79
|
-
const backupDir = join(projectDir, ".bos", "sync-backup", timestamp);
|
|
80
|
-
|
|
81
|
-
for (const filePath of filesToBackup) {
|
|
82
|
-
const src = join(projectDir, filePath);
|
|
83
|
-
const dest = join(backupDir, filePath);
|
|
84
|
-
mkdirSync(dirname(dest), { recursive: true });
|
|
85
|
-
copyFileSync(src, dest);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
return backupDir;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function mergeStringMaps(
|
|
92
|
-
local: Record<string, string> | undefined,
|
|
93
|
-
template: Record<string, string> | undefined,
|
|
94
|
-
): Record<string, string> | undefined {
|
|
95
|
-
if (!local && !template) return undefined;
|
|
96
|
-
|
|
97
|
-
const merged: Record<string, string> = { ...(local ?? {}) };
|
|
98
|
-
for (const [name, value] of Object.entries(template ?? {})) {
|
|
99
|
-
merged[name] = value;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
return Object.keys(merged).length > 0 ? merged : undefined;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
function mergeWorkspacePackages(local: unknown, template: unknown): string[] | undefined {
|
|
106
|
-
const localPackages = Array.isArray(local) ? local : [];
|
|
107
|
-
const templatePackages = Array.isArray(template) ? template : [];
|
|
108
|
-
if (localPackages.length === 0 && templatePackages.length === 0) return undefined;
|
|
109
|
-
|
|
110
|
-
const ordered = new Set<string>();
|
|
111
|
-
for (const entry of templatePackages) {
|
|
112
|
-
if (typeof entry === "string" && entry.length > 0) ordered.add(entry);
|
|
113
|
-
}
|
|
114
|
-
for (const entry of localPackages) {
|
|
115
|
-
if (typeof entry === "string" && entry.length > 0) ordered.add(entry);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
return ordered.size > 0 ? [...ordered] : undefined;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
export function mergePackageJson(
|
|
122
|
-
filePath: string,
|
|
123
|
-
local: PackageJson,
|
|
124
|
-
template: PackageJson,
|
|
125
|
-
): PackageJson {
|
|
126
|
-
const merged: PackageJson = { ...local, ...template };
|
|
127
|
-
|
|
128
|
-
if (filePath === "package.json") {
|
|
129
|
-
for (const key of ["name", "private", "version"] as const) {
|
|
130
|
-
if (key in local) {
|
|
131
|
-
merged[key] = local[key];
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
} else if ("version" in local) {
|
|
135
|
-
merged.version = local.version;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
for (const depField of [
|
|
139
|
-
"dependencies",
|
|
140
|
-
"devDependencies",
|
|
141
|
-
"peerDependencies",
|
|
142
|
-
"overrides",
|
|
143
|
-
] as const) {
|
|
144
|
-
const localDeps = local[depField] as Record<string, string> | undefined;
|
|
145
|
-
const templateDeps = template[depField] as Record<string, string> | undefined;
|
|
146
|
-
|
|
147
|
-
const mergedDeps = mergeStringMaps(localDeps, templateDeps);
|
|
148
|
-
if (mergedDeps) {
|
|
149
|
-
merged[depField] = mergedDeps;
|
|
150
|
-
} else {
|
|
151
|
-
delete merged[depField];
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
if (
|
|
156
|
-
(local.scripts && typeof local.scripts === "object") ||
|
|
157
|
-
(template.scripts && typeof template.scripts === "object")
|
|
158
|
-
) {
|
|
159
|
-
const mergedScripts = mergeStringMaps(
|
|
160
|
-
local.scripts as Record<string, string> | undefined,
|
|
161
|
-
template.scripts as Record<string, string> | undefined,
|
|
162
|
-
);
|
|
163
|
-
if (mergedScripts) {
|
|
164
|
-
merged.scripts = mergedScripts;
|
|
165
|
-
} else {
|
|
166
|
-
delete merged.scripts;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
if (
|
|
171
|
-
(local.workspaces && typeof local.workspaces === "object") ||
|
|
172
|
-
(template.workspaces && typeof template.workspaces === "object")
|
|
173
|
-
) {
|
|
174
|
-
const localWorkspaces = (local.workspaces ?? {}) as {
|
|
175
|
-
packages?: string[];
|
|
176
|
-
catalog?: Record<string, string>;
|
|
177
|
-
};
|
|
178
|
-
const templateWorkspaces = (template.workspaces ?? {}) as {
|
|
179
|
-
packages?: string[];
|
|
180
|
-
catalog?: Record<string, string>;
|
|
181
|
-
};
|
|
182
|
-
|
|
183
|
-
const mergedWorkspaces: { packages?: string[]; catalog?: Record<string, string> } = {
|
|
184
|
-
...localWorkspaces,
|
|
185
|
-
...templateWorkspaces,
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
const mergedPackages = mergeWorkspacePackages(
|
|
189
|
-
localWorkspaces.packages,
|
|
190
|
-
templateWorkspaces.packages,
|
|
191
|
-
);
|
|
192
|
-
if (mergedPackages) {
|
|
193
|
-
mergedWorkspaces.packages = mergedPackages;
|
|
194
|
-
} else {
|
|
195
|
-
delete mergedWorkspaces.packages;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const mergedCatalog = mergeStringMaps(localWorkspaces.catalog, templateWorkspaces.catalog);
|
|
199
|
-
if (mergedCatalog) {
|
|
200
|
-
mergedWorkspaces.catalog = mergedCatalog;
|
|
201
|
-
} else {
|
|
202
|
-
delete mergedWorkspaces.catalog;
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
if (Object.keys(mergedWorkspaces).length > 0) {
|
|
206
|
-
merged.workspaces = mergedWorkspaces;
|
|
207
|
-
} else {
|
|
208
|
-
delete merged.workspaces;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
return merged;
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
function toDestPath(filePath: string): string {
|
|
216
|
-
return sourcePathToDestinationPath(filePath);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
function toSourcePath(sourceDir: string, destPath: string): string | null {
|
|
220
|
-
const directPath = join(sourceDir, destPath);
|
|
221
|
-
if (existsSync(directPath)) {
|
|
222
|
-
return destPath;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
if (destPath.startsWith(".github/")) {
|
|
226
|
-
const templatePath = destPath.replace(/^\.github\//, ".github/templates/");
|
|
227
|
-
if (existsSync(join(sourceDir, templatePath))) {
|
|
228
|
-
return templatePath;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
return null;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
function writeSyncedFile(sourceDir: string, projectDir: string, filePath: string): void {
|
|
236
|
-
const src = join(sourceDir, filePath);
|
|
237
|
-
const destPath = filePath.startsWith(".github/templates/")
|
|
238
|
-
? filePath.replace(/^\.github\/templates\//, ".github/")
|
|
239
|
-
: filePath;
|
|
240
|
-
const dest = join(projectDir, destPath);
|
|
241
|
-
mkdirSync(dirname(dest), { recursive: true });
|
|
242
|
-
|
|
243
|
-
if (filePath.endsWith("bos.config.json")) {
|
|
244
|
-
const localContent = existsSync(dest) ? readFileSync(dest, "utf-8") : null;
|
|
245
|
-
const templateContent = readFileSync(src, "utf-8");
|
|
246
|
-
|
|
247
|
-
if (localContent) {
|
|
248
|
-
const local = JSON.parse(localContent) as Record<string, unknown>;
|
|
249
|
-
const template = JSON.parse(templateContent) as Record<string, unknown>;
|
|
250
|
-
const merged = mergeBosConfigWithTemplate(local, template);
|
|
251
|
-
writeFileSync(dest, `${JSON.stringify(merged, null, 2)}\n`);
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
if (filePath.endsWith("package.json")) {
|
|
257
|
-
const localContent = existsSync(dest) ? readFileSync(dest, "utf-8") : null;
|
|
258
|
-
const templateContent = readFileSync(src, "utf-8");
|
|
259
|
-
|
|
260
|
-
if (localContent) {
|
|
261
|
-
const local = JSON.parse(localContent) as Record<string, unknown>;
|
|
262
|
-
const template = JSON.parse(templateContent) as Record<string, unknown>;
|
|
263
|
-
const merged = mergePackageJson(destPath, local, template);
|
|
264
|
-
writeFileSync(dest, `${JSON.stringify(merged, null, 2)}\n`);
|
|
265
|
-
return;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
writeFileSync(dest, readFileSync(src));
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
export async function syncTemplate(projectDir: string, options: SyncOptions): Promise<SyncResult> {
|
|
273
|
-
// Sync reads the raw bos.config.json (not the resolved config) because it needs
|
|
274
|
-
// the user's explicit local settings: their extends ref, selected plugins, etc.
|
|
275
|
-
// The resolved config is the merged result and would include inherited parent
|
|
276
|
-
// values that the user didn't explicitly choose, which would break sync filtering.
|
|
277
|
-
const localConfig = JSON.parse(
|
|
278
|
-
readFileSync(join(projectDir, "bos.config.json"), "utf-8"),
|
|
279
|
-
) as Record<string, unknown>;
|
|
280
|
-
|
|
281
|
-
let extendsRef: string | undefined;
|
|
282
|
-
if (typeof localConfig.extends === "string") {
|
|
283
|
-
extendsRef = localConfig.extends;
|
|
284
|
-
} else if (isPlainObjectFromMerge(localConfig.extends)) {
|
|
285
|
-
extendsRef = resolveExtendsRef(localConfig.extends as Record<string, string>, "production");
|
|
286
|
-
}
|
|
287
|
-
if (!extendsRef?.startsWith("bos://")) {
|
|
288
|
-
return {
|
|
289
|
-
status: "error",
|
|
290
|
-
updated: [],
|
|
291
|
-
skipped: [],
|
|
292
|
-
added: [],
|
|
293
|
-
error: "No extends field found in bos.config.json — cannot determine parent",
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
297
|
-
const extendsMatch = extendsRef.match(/^bos:\/\/([^/]+)\/(.+)$/);
|
|
298
|
-
if (!extendsMatch) {
|
|
299
|
-
return {
|
|
300
|
-
status: "error",
|
|
301
|
-
updated: [],
|
|
302
|
-
skipped: [],
|
|
303
|
-
added: [],
|
|
304
|
-
error: `Invalid extends reference: ${extendsRef}`,
|
|
305
|
-
};
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const extendsAccount = extendsMatch[1];
|
|
309
|
-
const extendsGateway = extendsMatch[2];
|
|
310
|
-
|
|
311
|
-
const { sourceDir, cleanup } = await resolveSourceDir({
|
|
312
|
-
extendsAccount,
|
|
313
|
-
extendsGateway,
|
|
314
|
-
});
|
|
315
|
-
|
|
316
|
-
try {
|
|
317
|
-
const childPlugins =
|
|
318
|
-
localConfig.plugins && typeof localConfig.plugins === "object"
|
|
319
|
-
? Object.keys(localConfig.plugins as Record<string, unknown>)
|
|
320
|
-
: [];
|
|
321
|
-
const withUi = existsSync(join(projectDir, "ui", "package.json"));
|
|
322
|
-
const withApi = existsSync(join(projectDir, "api", "package.json"));
|
|
323
|
-
const withHost = existsSync(join(projectDir, "host", "package.json"));
|
|
324
|
-
|
|
325
|
-
const filteredFiles = new Set<string>();
|
|
326
|
-
const destToSource = new Map<string, string>();
|
|
327
|
-
for (const destPath of FRAMEWORK_OWNED_SYNC_FILES) {
|
|
328
|
-
if (destPath.startsWith("ui/") && !withUi) continue;
|
|
329
|
-
if (destPath.startsWith("api/") && !withApi) continue;
|
|
330
|
-
if (destPath.startsWith("host/") && !withHost) continue;
|
|
331
|
-
const sourcePath = toSourcePath(sourceDir, destPath);
|
|
332
|
-
if (!sourcePath) continue;
|
|
333
|
-
filteredFiles.add(sourcePath);
|
|
334
|
-
destToSource.set(destPath, sourcePath);
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
const updated: string[] = [];
|
|
338
|
-
const skipped: string[] = [];
|
|
339
|
-
const added: string[] = [];
|
|
340
|
-
|
|
341
|
-
for (const [destPath, filePath] of destToSource.entries()) {
|
|
342
|
-
const localHash = computeLocalHash(projectDir, destPath);
|
|
343
|
-
const sourceContent = readFileSync(join(sourceDir, filePath));
|
|
344
|
-
const sourceHash = createHash("sha256").update(sourceContent).digest("hex").substring(0, 16);
|
|
345
|
-
|
|
346
|
-
if (localHash === null) {
|
|
347
|
-
added.push(destPath);
|
|
348
|
-
continue;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
if (localHash !== sourceHash) {
|
|
352
|
-
updated.push(destPath);
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
if (options.dryRun) {
|
|
357
|
-
return {
|
|
358
|
-
status: "dry-run",
|
|
359
|
-
updated,
|
|
360
|
-
skipped,
|
|
361
|
-
added,
|
|
362
|
-
};
|
|
363
|
-
}
|
|
364
|
-
|
|
365
|
-
const filesToWrite = [...updated, ...added];
|
|
366
|
-
|
|
367
|
-
if (filesToWrite.length > 0) {
|
|
368
|
-
backupFiles(projectDir, filesToWrite);
|
|
369
|
-
|
|
370
|
-
for (const destPath of filesToWrite) {
|
|
371
|
-
const sourcePath = destToSource.get(destPath) ?? destPath;
|
|
372
|
-
writeSyncedFile(sourceDir, projectDir, sourcePath);
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
const newSnapshotFiles: Record<string, string> = {};
|
|
377
|
-
for (const filePath of filteredFiles) {
|
|
378
|
-
const src = join(sourceDir, filePath);
|
|
379
|
-
const content = readFileSync(src);
|
|
380
|
-
newSnapshotFiles[toDestPath(filePath)] = createHash("sha256")
|
|
381
|
-
.update(content)
|
|
382
|
-
.digest("hex")
|
|
383
|
-
.substring(0, 16);
|
|
384
|
-
}
|
|
385
|
-
|
|
386
|
-
await writeSnapshot(projectDir, {
|
|
387
|
-
parentRef: `bos://${extendsAccount}/${extendsGateway}`,
|
|
388
|
-
files: newSnapshotFiles,
|
|
389
|
-
});
|
|
390
|
-
|
|
391
|
-
const account = (localConfig.account as string) || extendsAccount;
|
|
392
|
-
const domain = (localConfig.domain as string) || extendsGateway;
|
|
393
|
-
const overrides: Array<"ui" | "api" | "host" | "plugins"> = [];
|
|
394
|
-
if (withUi) overrides.push("ui");
|
|
395
|
-
if (withApi) overrides.push("api");
|
|
396
|
-
if (withHost) overrides.push("host");
|
|
397
|
-
if (childPlugins.length > 0) overrides.push("plugins");
|
|
398
|
-
|
|
399
|
-
await personalizeConfig(projectDir, {
|
|
400
|
-
extendsAccount,
|
|
401
|
-
extendsGateway,
|
|
402
|
-
account,
|
|
403
|
-
domain,
|
|
404
|
-
overrides,
|
|
405
|
-
plugins: childPlugins,
|
|
406
|
-
workspaceOpts: { sourceDir },
|
|
407
|
-
mode: "sync",
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
const syncedConfig = await loadConfig({ cwd: projectDir });
|
|
411
|
-
if (syncedConfig?.runtime) {
|
|
412
|
-
writeGeneratedInfra(projectDir, syncedConfig.runtime);
|
|
413
|
-
}
|
|
414
|
-
|
|
415
|
-
if (!options.noInstall) {
|
|
416
|
-
await runBunInstall(projectDir);
|
|
417
|
-
await runTypesGen(projectDir);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
return {
|
|
421
|
-
status: "synced",
|
|
422
|
-
updated,
|
|
423
|
-
skipped,
|
|
424
|
-
added,
|
|
425
|
-
};
|
|
426
|
-
} finally {
|
|
427
|
-
await cleanup();
|
|
428
|
-
}
|
|
429
|
-
}
|
package/src/cli/timing.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import type { spinner as clackSpinner } from "@clack/prompts";
|
|
2
|
-
|
|
3
|
-
type Spinner = ReturnType<typeof clackSpinner>;
|
|
4
|
-
|
|
5
|
-
export interface PhaseTiming {
|
|
6
|
-
name: string;
|
|
7
|
-
durationMs: number;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
const PHASE_LABELS: Record<string, string> = {
|
|
11
|
-
"parent config": "Fetching parent config...",
|
|
12
|
-
"template source": "Resolving template source...",
|
|
13
|
-
"scaffold project": "Creating project scaffold...",
|
|
14
|
-
"copy files": "Copying template files...",
|
|
15
|
-
"personalize config": "Personalizing config...",
|
|
16
|
-
"write snapshot": "Writing snapshot...",
|
|
17
|
-
"resolve config": "Resolving config...",
|
|
18
|
-
"generate env/docker": "Generating environment config...",
|
|
19
|
-
"create env file": "Creating .env file...",
|
|
20
|
-
"install dependencies": "Installing dependencies...",
|
|
21
|
-
"generate types": "Generating types...",
|
|
22
|
-
"generate migrations": "Generating database migrations...",
|
|
23
|
-
"generate code artifacts": "Generating code artifacts...",
|
|
24
|
-
"docker compose up": "Starting Docker services...",
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
function phaseLabel(name: string): string {
|
|
28
|
-
return PHASE_LABELS[name] ?? name;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function timePhase<T>(
|
|
32
|
-
timings: PhaseTiming[],
|
|
33
|
-
name: string,
|
|
34
|
-
fn: () => Promise<T>,
|
|
35
|
-
spinner?: Spinner,
|
|
36
|
-
): Promise<T> {
|
|
37
|
-
spinner?.message(phaseLabel(name));
|
|
38
|
-
const startedAt = Date.now();
|
|
39
|
-
try {
|
|
40
|
-
return await fn();
|
|
41
|
-
} finally {
|
|
42
|
-
timings.push({ name, durationMs: Date.now() - startedAt });
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function sumPhaseDurations(timings: PhaseTiming[]): number {
|
|
47
|
-
return timings.reduce((total, timing) => total + timing.durationMs, 0);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export function formatDuration(durationMs: number): string {
|
|
51
|
-
if (durationMs < 1000) {
|
|
52
|
-
return `${durationMs}ms`;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
if (durationMs < 60_000) {
|
|
56
|
-
const seconds = durationMs / 1000;
|
|
57
|
-
return `${seconds.toFixed(seconds >= 10 ? 0 : 1)}s`;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const minutes = Math.floor(durationMs / 60_000);
|
|
61
|
-
const seconds = Math.round((durationMs % 60_000) / 1000);
|
|
62
|
-
return `${minutes}m ${seconds}s`;
|
|
63
|
-
}
|