create-flow-os 0.0.47-dev.1772045775 → 0.0.47

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 CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "create-flow-os",
3
- "version": "0.0.47-dev.1772045775",
3
+ "version": "0.0.47",
4
4
  "license": "PolyForm-Shield-1.0.0",
5
5
  "type": "module",
6
6
  "dependencies": {
7
- "@flow-os/client": ">=0.0.1-dev.0"
7
+ "@flow-os/client": "^0.0.47"
8
8
  },
9
9
  "bin": {
10
10
  "create-flow-os": "./src/index.ts"
package/src/init/index.ts CHANGED
@@ -1,10 +1,12 @@
1
1
  #!/usr/bin/env bun
2
+ // Clear subito per nascondere resolving/installing di Bun
3
+ process.stdout.write("\x1b[2J\x1b[H");
2
4
 
3
5
  import * as readline from "readline";
4
6
  import { join, dirname } from "path";
5
7
  import { fileURLToPath } from "url";
6
8
  import { libsWithConfig, toShortName, toPkgName } from "./lib";
7
- import { initLib, fetchFlowPackageVersions, shouldUseWorkspace, findFlowOsRepoRoot } from "./scaffold";
9
+ import { initLib, fetchFlowPackageVersions } from "./scaffold";
8
10
  import { bannerBox, withLoading, colors } from "./ui";
9
11
 
10
12
  const { V, V_LIGHT, Y, E, R, B } = colors;
@@ -14,8 +16,7 @@ const { V, V_LIGHT, Y, E, R, B } = colors;
14
16
  // ───────────────────────────────────────────────────────────────────────────────
15
17
  const cwd = process.cwd();
16
18
  const cliRoot = join(dirname(fileURLToPath(import.meta.url)), "..", "..");
17
- const flowOsRepoRoot = findFlowOsRepoRoot(cwd);
18
- const available = libsWithConfig(cliRoot, flowOsRepoRoot).map(toShortName);
19
+ const available = libsWithConfig(cliRoot).map(toShortName);
19
20
 
20
21
  let libs = [...new Set(process.argv.slice(3))];
21
22
 
@@ -42,7 +43,7 @@ if (!toInit.length) {
42
43
  // ───────────────────────────────────────────────────────────────────────────────
43
44
  const pkgNames = toInit.map(toPkgName);
44
45
  await withLoading(async (onStep) => {
45
- const versions = shouldUseWorkspace(cwd) ? new Map<string, string>() : await fetchFlowPackageVersions(pkgNames);
46
+ const versions = await fetchFlowPackageVersions(pkgNames);
46
47
  await initLib(toInit, cwd, versions, onStep);
47
48
  });
48
49
 
package/src/init/lib.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { existsSync, readFileSync, readdirSync } from "fs";
1
+ import { existsSync, readFileSync } from "fs";
2
2
  import { join, dirname } from "path";
3
3
  import { fileURLToPath } from "url";
4
4
 
@@ -21,27 +21,7 @@ export function flowDeps(root: string): string[] {
21
21
  return Object.keys(deps).filter((k) => k.startsWith(FLOW_PREFIX));
22
22
  }
23
23
 
24
- /** Scansiona packages/ per tutti gli @flow-os/* (con o senza config) */
25
- function scanPackagesDir(packagesDir: string): string[] {
26
- const found: string[] = [];
27
- try {
28
- for (const name of readdirSync(packagesDir, { withFileTypes: true })) {
29
- if (!name.isDirectory()) continue;
30
- const pkgPath = join(packagesDir, name.name, "package.json");
31
- if (!existsSync(pkgPath)) continue;
32
- try {
33
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")) as { name?: string };
34
- if (pkg?.name?.startsWith(FLOW_PREFIX)) found.push(pkg.name);
35
- } catch {}
36
- }
37
- } catch {}
38
- return found;
39
- }
40
-
41
- export function libsWithConfig(cliRoot: string, flowOsRepoRoot?: string | null): string[] {
42
- const packagesDir = flowOsRepoRoot ? join(flowOsRepoRoot, "packages") : join(cliRoot, "..");
43
- const fromScan = scanPackagesDir(packagesDir);
44
- if (fromScan.length > 0) return fromScan;
24
+ export function libsWithConfig(cliRoot: string): string[] {
45
25
  const pkg = JSON.parse(readFileSync(join(cliRoot, "package.json"), "utf-8"));
46
26
  const deps = Object.keys(pkg.dependencies ?? {}).filter((k) => k.startsWith(FLOW_PREFIX));
47
27
  return deps.filter((name) => existsSync(join(pkgRoot(name), "config")));
@@ -79,29 +79,6 @@ function isCreateFlowOsDev(): boolean {
79
79
  }
80
80
  }
81
81
 
82
- /** Trova la root del repo flow-os salendo da cwd (contiene packages/client) */
83
- export function findFlowOsRepoRoot(cwd: string): string | null {
84
- let d = cwd;
85
- while (true) {
86
- const pkgClient = join(d, "packages", "client", "package.json");
87
- if (existsSync(pkgClient)) {
88
- try {
89
- const pkg = JSON.parse(readFileSync(pkgClient, "utf-8")) as { name?: string };
90
- if (pkg?.name === "@flow-os/client") return d;
91
- } catch {}
92
- }
93
- const parent = dirname(d);
94
- if (parent === d) break;
95
- d = parent;
96
- }
97
- return null;
98
- }
99
-
100
- /** True se usare workspace:* (cwd dentro repo flow-os) */
101
- export function shouldUseWorkspace(cwd: string): boolean {
102
- return !!findFlowOsRepoRoot(cwd);
103
- }
104
-
105
82
  /** Recupera versione di un pacchetto @flow-os/* dal registry npm (con cache 5 min) */
106
83
  async function fetchFlowPackageVersion(pkgName: string): Promise<string | undefined> {
107
84
  const tag = isCreateFlowOsDev() ? "dev" : "latest";
@@ -192,19 +169,12 @@ async function fetchConfigFromNpm(
192
169
  /** Sostituisce workspace:* e 0.0.1 con versione concreta (workspace va bene solo dentro flow-os) */
193
170
  function resolveFlowDeps(
194
171
  deps: Record<string, string> | undefined,
195
- pkgRootDir: string,
196
- versionsFromNpm: Map<string, string>,
197
- useWorkspace: boolean
172
+ configDir: string,
173
+ versionsFromNpm: Map<string, string>
198
174
  ): Record<string, string> {
199
175
  if (!deps) return {};
200
176
  const resolved = { ...deps };
201
- if (useWorkspace) {
202
- for (const k of Object.keys(resolved)) {
203
- if (k.startsWith("@flow-os/")) resolved[k] = "workspace:*";
204
- }
205
- return resolved;
206
- }
207
- const ownerPkgPath = join(pkgRootDir, "package.json");
177
+ const ownerPkgPath = join(configDir, "..", "package.json");
208
178
  let ownerVersion: string | undefined;
209
179
  if (existsSync(ownerPkgPath)) {
210
180
  try {
@@ -235,7 +205,7 @@ function resolveFlowDeps(
235
205
  return resolved;
236
206
  }
237
207
 
238
- function mergePkg(configDir: string, cwd: string, versionsFromNpm: Map<string, string>, useWorkspace: boolean): void {
208
+ function mergePkg(configDir: string, cwd: string, versionsFromNpm: Map<string, string>): void {
239
209
  const configPkg = join(configDir, "package.json");
240
210
  if (!existsSync(configPkg)) return;
241
211
  const targetPath = join(cwd, "package.json");
@@ -245,77 +215,14 @@ function mergePkg(configDir: string, cwd: string, versionsFromNpm: Map<string, s
245
215
  : { ...config, name: basename(cwd) || "flow-app" };
246
216
  target.dependencies = { ...target.dependencies, ...config.dependencies };
247
217
  target.devDependencies = { ...target.devDependencies, ...config.devDependencies };
248
- const pkgRootDir = join(configDir, "..");
249
- for (const [k, v] of Object.entries(resolveFlowDeps(config.dependencies, pkgRootDir, versionsFromNpm, useWorkspace)))
218
+ for (const [k, v] of Object.entries(resolveFlowDeps(config.dependencies, configDir, versionsFromNpm)))
250
219
  target.dependencies[k] = v;
251
- for (const [k, v] of Object.entries(resolveFlowDeps(config.devDependencies, pkgRootDir, versionsFromNpm, useWorkspace)))
220
+ for (const [k, v] of Object.entries(resolveFlowDeps(config.devDependencies, configDir, versionsFromNpm)))
252
221
  target.devDependencies[k] = v;
253
222
  target.scripts = { ...target.scripts, ...config.scripts };
254
223
  writeFileSync(targetPath, JSON.stringify(target, null, 2));
255
224
  }
256
225
 
257
- type FlowOsInit = { dependencies?: Record<string, string>; devDependencies?: Record<string, string>; scripts?: Record<string, string>; name?: string; version?: string; type?: string };
258
-
259
- /** Merge da flow-os-init: root package.json (se in repo) oppure package (npm) */
260
- function mergeFlowOsInit(
261
- packageRoot: string,
262
- pkgName: string,
263
- cwd: string,
264
- versionsFromNpm: Map<string, string>,
265
- useWorkspace: boolean,
266
- flowOsRepoRoot: string | null
267
- ): void {
268
- let init: FlowOsInit | undefined;
269
- if (flowOsRepoRoot) {
270
- const rootPkgPath = join(flowOsRepoRoot, "package.json");
271
- if (existsSync(rootPkgPath)) {
272
- try {
273
- const rootPkg = JSON.parse(readFileSync(rootPkgPath, "utf-8")) as { "flow-os-init"?: Record<string, FlowOsInit> };
274
- init = rootPkg["flow-os-init"]?.[pkgName];
275
- } catch {}
276
- }
277
- }
278
- if (!init) {
279
- const pkgPath = join(packageRoot, "package.json");
280
- if (!existsSync(pkgPath)) return;
281
- try {
282
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")) as { "flow-os-init"?: FlowOsInit };
283
- init = pkg["flow-os-init"];
284
- } catch {
285
- return;
286
- }
287
- }
288
- if (!init) return;
289
- const targetPath = join(cwd, "package.json");
290
- const target = existsSync(targetPath)
291
- ? JSON.parse(readFileSync(targetPath, "utf-8"))
292
- : { name: init.name ?? (basename(cwd) || "flow-app"), version: init.version ?? "0.0.1", type: init.type ?? "module" };
293
- target.dependencies = { ...target.dependencies, ...init.dependencies };
294
- target.devDependencies = { ...target.devDependencies, ...init.devDependencies };
295
- for (const [k, v] of Object.entries(resolveFlowDeps(init.dependencies, packageRoot, versionsFromNpm, useWorkspace)))
296
- target.dependencies[k] = v;
297
- for (const [k, v] of Object.entries(resolveFlowDeps(init.devDependencies, packageRoot, versionsFromNpm, useWorkspace)))
298
- target.devDependencies[k] = v;
299
- target.scripts = { ...target.scripts, ...init.scripts };
300
- writeFileSync(targetPath, JSON.stringify(target, null, 2));
301
- }
302
-
303
- /** Aggiunge dipendenza per pacchetti senza config (solo install) */
304
- function addDependencyForPackage(
305
- pkgName: string,
306
- cwd: string,
307
- versionsFromNpm: Map<string, string>,
308
- useWorkspace: boolean
309
- ): void {
310
- const targetPath = join(cwd, "package.json");
311
- if (!existsSync(targetPath)) return;
312
- const target = JSON.parse(readFileSync(targetPath, "utf-8"));
313
- target.dependencies = target.dependencies ?? {};
314
- const spec = useWorkspace ? "workspace:*" : (versionsFromNpm.get(pkgName) ? `^${versionsFromNpm.get(pkgName)}` : undefined);
315
- if (spec) target.dependencies[pkgName] = spec;
316
- writeFileSync(targetPath, JSON.stringify(target, null, 2));
317
- }
318
-
319
226
  /** Assicura che versions abbia le versioni per pkgNames (fetch lazy) */
320
227
  async function ensureVersions(versions: Map<string, string>, pkgNames: string[]): Promise<void> {
321
228
  const missing = pkgNames.filter((n) => !versions.has(n));
@@ -344,17 +251,12 @@ async function collectAllTemplates(
344
251
  done: Set<string>,
345
252
  order: string[],
346
253
  versionsFromNpm: Map<string, string>,
347
- tmpDirs: string[],
348
- flowOsRepoRoot: string | null
254
+ tmpDirs: string[]
349
255
  ): Promise<void> {
350
256
  for (const lib of libs) {
351
257
  const pkgName = toPkgName(lib);
352
258
  if (done.has(pkgName)) continue;
353
259
 
354
- const shortName = toShortName(pkgName);
355
- const localFromRepo = flowOsRepoRoot ? join(flowOsRepoRoot, "packages", shortName) : "";
356
- const localConfigFromRepo = localFromRepo ? join(localFromRepo, "config") : "";
357
-
358
260
  let root: string;
359
261
  let configDir: string;
360
262
  try {
@@ -364,22 +266,12 @@ async function collectAllTemplates(
364
266
  root = "";
365
267
  configDir = "";
366
268
  }
367
- const hasLocalFromRepo = !!localConfigFromRepo && existsSync(localConfigFromRepo);
368
269
  const hasLocal = existsSync(configDir);
369
270
 
370
271
  let pkgFiles: Map<string, string>;
371
272
  let configDirForPkg: string;
372
- const useLocalRepo = hasLocalFromRepo && flowOsRepoRoot;
373
273
  const npmVer = versionsFromNpm.get(pkgName);
374
-
375
- if (useLocalRepo) {
376
- configDirForPkg = localConfigFromRepo;
377
- pkgFiles = collectConfigFiles(configDirForPkg);
378
- const subDeps = flowDepsFromPkg(join(configDirForPkg, ".."));
379
- for (const sub of subDeps) {
380
- await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs, flowOsRepoRoot);
381
- }
382
- } else if (npmVer) {
274
+ if (npmVer) {
383
275
  const fetched = await fetchConfigFromNpm(pkgName, npmVer, tmpDirs);
384
276
  if (fetched) {
385
277
  pkgFiles = fetched.files;
@@ -387,13 +279,13 @@ async function collectAllTemplates(
387
279
  const subDeps = flowDepsFromPkg(join(configDirForPkg, ".."));
388
280
  await ensureVersions(versionsFromNpm, subDeps);
389
281
  for (const sub of subDeps) {
390
- await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs, flowOsRepoRoot);
282
+ await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs);
391
283
  }
392
284
  } else if (hasLocal) {
393
285
  const subDeps = flowDeps(root);
394
286
  await ensureVersions(versionsFromNpm, subDeps);
395
287
  for (const sub of subDeps) {
396
- await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs, flowOsRepoRoot);
288
+ await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs);
397
289
  }
398
290
  pkgFiles = collectConfigFiles(configDir);
399
291
  configDirForPkg = configDir;
@@ -404,7 +296,7 @@ async function collectAllTemplates(
404
296
  const subDeps = flowDeps(root);
405
297
  await ensureVersions(versionsFromNpm, subDeps);
406
298
  for (const sub of subDeps) {
407
- await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs, flowOsRepoRoot);
299
+ await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs);
408
300
  }
409
301
  pkgFiles = collectConfigFiles(configDir);
410
302
  configDirForPkg = configDir;
@@ -427,68 +319,28 @@ export async function initLib(
427
319
  onProgress?: (step: InitProgressStep) => void
428
320
  ): Promise<void> {
429
321
  const pkgNames = libs.map(toPkgName);
430
- const flowOsRepoRoot = findFlowOsRepoRoot(cwd);
431
- const useWorkspace = !!flowOsRepoRoot;
432
322
  const versions = versionsFromNpm ?? new Map<string, string>();
433
323
 
434
324
  onProgress?.("fetch");
435
- if (!useWorkspace) {
436
- const fetched = await fetchFlowPackageVersions(pkgNames);
437
- for (const [k, v] of fetched) versions.set(k, v);
438
- }
325
+ const fetched = await fetchFlowPackageVersions(pkgNames);
326
+ for (const [k, v] of fetched) versions.set(k, v);
439
327
 
440
328
  onProgress?.("templates");
441
329
  const combined = new Map<string, string>();
442
330
  const done = new Set<string>();
443
331
  const order: string[] = [];
444
332
  const tmpDirs: string[] = [];
445
- await collectAllTemplates(libs, combined, done, order, versions, tmpDirs, flowOsRepoRoot);
446
-
447
- for (const configDir of order) {
448
- const packageRoot = join(configDir, "..");
449
- const pkgName = (() => {
450
- try {
451
- const p = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf-8")) as { name?: string };
452
- return p?.name ?? "";
453
- } catch {
454
- return "";
455
- }
456
- })();
457
- if (existsSync(join(configDir, "package.json"))) {
458
- mergePkg(configDir, cwd, versions, useWorkspace);
459
- } else {
460
- mergeFlowOsInit(packageRoot, pkgName, cwd, versions, useWorkspace, flowOsRepoRoot);
461
- }
462
- }
333
+ await collectAllTemplates(libs, combined, done, order, versions, tmpDirs);
463
334
 
464
- const targetPath = join(cwd, "package.json");
465
- if (!existsSync(targetPath)) {
466
- writeFileSync(
467
- targetPath,
468
- JSON.stringify({ name: basename(cwd) || "flow-app", version: "0.0.1", private: true, type: "module" }, null, 2)
469
- );
470
- }
471
-
472
- const toAdd = new Set<string>(pkgNames);
473
335
  for (const configDir of order) {
474
- const packageRoot = join(configDir, "..");
475
- for (const peer of flowDepsFromPkg(packageRoot)) toAdd.add(peer);
476
- }
477
- for (const pkgName of pkgNames) {
478
- const packageRoot = flowOsRepoRoot ? join(flowOsRepoRoot, "packages", toShortName(pkgName)) : (() => { try { return pkgRoot(pkgName); } catch { return ""; } })();
479
- if (packageRoot) for (const peer of flowDepsFromPkg(packageRoot)) toAdd.add(peer);
480
- }
481
- await ensureVersions(versions, [...toAdd]);
482
- for (const pkgName of toAdd) {
483
- addDependencyForPackage(pkgName, cwd, versions, useWorkspace);
336
+ mergePkg(configDir, cwd, versions);
484
337
  }
485
338
 
486
339
  onProgress?.("write");
487
340
  await writeMergedWithUser(combined, cwd, (path, conflicts) => resolveConflicts(conflicts, path));
488
341
 
489
342
  onProgress?.("install");
490
- const installCwd = useWorkspace && flowOsRepoRoot ? flowOsRepoRoot : cwd;
491
- const proc = Bun.spawn(["bun", "install"], { cwd: installCwd, stdout: "pipe", stderr: "pipe" });
343
+ const proc = Bun.spawn(["bun", "install"], { cwd, stdout: "inherit", stderr: "inherit" });
492
344
  const exitCode = await proc.exited;
493
345
  if (exitCode !== 0) {
494
346
  throw new Error(`bun install exited with code ${exitCode}`);
package/src/init/ui.ts CHANGED
@@ -9,7 +9,6 @@ const E = "\x1b[91m";
9
9
  const R = "\x1b[0m";
10
10
  const B = "\x1b[1m";
11
11
  const DIM = "\x1b[2m";
12
- const W = "\x1b[97m"; // bianco (solo per headerLogo)
13
12
 
14
13
  const FRAMES = "⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏";
15
14
 
@@ -26,24 +25,19 @@ export function bannerBox(title: string, lines: string[], color: string, w = 50)
26
25
  const c = color;
27
26
  const inner = " " + c + B + title + R + " ";
28
27
  const innerLen = stripAnsi(inner).length;
29
- const innerW = w - 4;
30
- const half = Math.max(0, Math.floor((innerW - innerLen) / 2));
31
- const rest = innerW - half - innerLen;
32
- const top = c + "" + "".repeat(half) + inner + c + "─".repeat(rest) + "" + R;
33
- const bottom = c + "" + "".repeat(innerW) + "" + R;
34
- const emptyLine = c + "│" + R + " " + " ".repeat(innerW - 2) + c + "│" + R;
35
- const bodyLines = lines.map((l) => c + "│" + R + " " + pad(l, innerW - 2) + c + "│" + R);
36
- return "\n" + top + "\n" + emptyLine + "\n" + bodyLines.join("\n") + "\n" + bottom + "\n";
28
+ const half = Math.max(0, Math.floor((w - 2 - innerLen) / 2));
29
+ const top = c + "╭" + "─".repeat(half) + inner + "─".repeat(w - 2 - half - innerLen) + "╮" + R;
30
+ const bottom = c + "╰" + "─".repeat(w - 2) + "╯" + R;
31
+ const bodyLines = lines.map((l) => c + "" + R + " " + pad(l, w - 2) + c + "" + R);
32
+ return "\n" + top + "\n" + bodyLines.join("\n") + "\n" + bottom + "\n";
37
33
  }
38
34
 
39
- export function box(lines: string[], color: string, w = 50): string {
35
+ export function box(lines: string[], color: string, w = 52): string {
40
36
  const c = color;
41
- const innerW = w - 4;
42
- const top = c + "" + "─".repeat(innerW) + "" + R;
43
- const bottom = c + "" + "".repeat(innerW) + "" + R;
44
- const emptyLine = c + "" + R + " " + " ".repeat(innerW - 2) + c + "" + R;
45
- const body = lines.map((l) => c + "│" + R + " " + pad(l, innerW - 2) + c + "│" + R).join("\n");
46
- return "\n" + top + "\n" + emptyLine + "\n" + body + "\n" + bottom + "\n";
37
+ const top = c + "╭" + "─".repeat(w) + "╮" + R;
38
+ const bottom = c + "" + "─".repeat(w) + "" + R;
39
+ const body = lines.map((l) => c + "" + R + " " + pad(l, w - 2) + c + "" + R).join("\n");
40
+ return "\n" + top + "\n" + body + "\n" + bottom + "\n";
47
41
  }
48
42
 
49
43
  import type { InitProgressStep } from "./scaffold";
@@ -93,6 +87,8 @@ export async function withLoading<T>(
93
87
  }
94
88
  }
95
89
 
90
+ const W = "\x1b[97m"; // bianco
91
+
96
92
  export const colors = { V, V_LIGHT, Y, E, R, B, DIM, W };
97
93
 
98
94
  /** Icona layers: 3 quadrati arrotondati sovrapposti, vista isometrica con shading ▓▒░ */