create-flow-os 0.0.24 → 0.0.25

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.
@@ -1,6 +1,6 @@
1
- {
2
- "files.exclude": {
3
- "**/node_modules": true,
4
- "**/index.html": true
5
- }
6
- }
1
+ {
2
+ "files.exclude": {
3
+ "**/node_modules": true,
4
+ "**/index.html": true
5
+ }
6
+ }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "create-flow-os",
3
- "version": "0.0.24",
3
+ "version": "0.0.25",
4
4
  "license": "PolyForm-Shield-1.0.0",
5
5
  "type": "module",
6
6
  "dependencies": {
7
- "@flow-os/client": "^0.0.24"
7
+ "@flow-os/client": "^0.0.25"
8
8
  },
9
9
  "bin": {
10
10
  "create-flow-os": "./src/index.ts"
package/prova.tsx ADDED
@@ -0,0 +1,2 @@
1
+ provaaaaa
2
+ sdwdw
package/src/init/index.ts CHANGED
@@ -3,8 +3,8 @@
3
3
  import * as readline from "readline";
4
4
  import { join, dirname } from "path";
5
5
  import { fileURLToPath } from "url";
6
- import { libsWithConfig, toShortName } from "./lib";
7
- import { initLib, fetchFlowClientVersion } from "./scaffold";
6
+ import { libsWithConfig, toShortName, toPkgName } from "./lib";
7
+ import { initLib, fetchFlowPackageVersions } from "./scaffold";
8
8
 
9
9
  // ───────────────────────────────────────────────────────────────────────────────
10
10
  // Usage: bun create flow-os i [lib...] | bun create flow-os i (prompt interattivo)
@@ -62,12 +62,13 @@ if (!toInit.length) {
62
62
  }
63
63
 
64
64
  // ───────────────────────────────────────────────────────────────────────────────
65
- // Execute: fetch versione client da npm (latest/dev), init libs, poi output box
65
+ // Execute: fetch versioni pacchetti da npm (latest/dev), init libs, poi output box
66
66
  // ───────────────────────────────────────────────────────────────────────────────
67
- process.stdout.write(V + "Fetching latest @flow-os/client..." + R);
68
- const clientVersion = await fetchFlowClientVersion();
69
- process.stdout.write(clientVersion ? ` ${V}${clientVersion}${R}\n` : " (fallback)\n");
70
- await initLib(toInit, cwd, clientVersion);
67
+ const pkgNames = toInit.map(toPkgName);
68
+ process.stdout.write(V + "Fetching latest @flow-os/* packages..." + R);
69
+ const versions = await fetchFlowPackageVersions(pkgNames);
70
+ process.stdout.write(versions.size ? ` ${V}${versions.size} pkg${R}\n` : " (fallback)\n");
71
+ await initLib(toInit, cwd, versions);
71
72
 
72
73
  const iconOk = V + "◆" + R;
73
74
  const iconUnrec = Y + "?" + R;
@@ -72,24 +72,40 @@ function isCreateFlowOsDev(): boolean {
72
72
  }
73
73
  }
74
74
 
75
- /** Recupera la versione di @flow-os/client dal registry npm in tempo reale (latest o dev) */
76
- export async function fetchFlowClientVersion(): Promise<string | undefined> {
75
+ /** Recupera versione di un pacchetto @flow-os/* dal registry npm (latest o dev) */
76
+ async function fetchFlowPackageVersion(pkgName: string): Promise<string | undefined> {
77
77
  const tag = isCreateFlowOsDev() ? "dev" : "latest";
78
78
  try {
79
- const res = await fetch(`${NPM_REGISTRY}/@flow-os/client?t=${Date.now()}`, {
79
+ const res = await fetch(`${NPM_REGISTRY}/${pkgName}?t=${Date.now()}`, {
80
80
  cache: "no-store",
81
81
  headers: { "Cache-Control": "no-cache", Pragma: "no-cache" },
82
82
  });
83
83
  if (!res.ok) return undefined;
84
84
  const data = (await res.json()) as { "dist-tags"?: Record<string, string> };
85
- const version = data["dist-tags"]?.[tag] ?? data["dist-tags"]?.["latest"];
86
- return version;
85
+ return data["dist-tags"]?.[tag] ?? data["dist-tags"]?.["latest"];
87
86
  } catch {
88
87
  return undefined;
89
88
  }
90
89
  }
91
90
 
92
- /** Scarica config da npm (bypass cache) - estrae in temp, ritorna { files, configDir, tmpDir } */
91
+ /** Recupera versioni di tutti i pacchetti @flow-os/* richiesti dal registry npm */
92
+ export async function fetchFlowPackageVersions(pkgNames: string[]): Promise<Map<string, string>> {
93
+ const out = new Map<string, string>();
94
+ await Promise.all(
95
+ pkgNames.map(async (name) => {
96
+ const v = await fetchFlowPackageVersion(name);
97
+ if (v) out.set(name, v);
98
+ })
99
+ );
100
+ return out;
101
+ }
102
+
103
+ /** @deprecated Usa fetchFlowPackageVersions. Mantenuto per retrocompatibilità. */
104
+ export async function fetchFlowClientVersion(): Promise<string | undefined> {
105
+ return fetchFlowPackageVersion("@flow-os/client");
106
+ }
107
+
108
+ /** Scarica config da npm per qualsiasi @flow-os/* (bypass cache) */
93
109
  async function fetchConfigFromNpm(
94
110
  pkgName: string,
95
111
  version: string
@@ -101,7 +117,7 @@ async function fetchConfigFromNpm(
101
117
  if (!res.ok) return null;
102
118
  const archive = new Bun.Archive(await res.blob());
103
119
  const { tmpdir } = await import("os");
104
- const tmpDir = join(tmpdir(), `flow-os-client-${version}-${Date.now()}`);
120
+ const tmpDir = join(tmpdir(), `flow-os-${shortName}-${version}-${Date.now()}`);
105
121
  await archive.extract(tmpDir, { glob: ["package/config/**"] });
106
122
  const configDir = join(tmpDir, "package", "config");
107
123
  if (!existsSync(configDir)) return null;
@@ -116,7 +132,7 @@ async function fetchConfigFromNpm(
116
132
  function resolveFlowDeps(
117
133
  deps: Record<string, string> | undefined,
118
134
  configDir: string,
119
- clientVersionFromNpm: string | undefined
135
+ versionsFromNpm: Map<string, string>
120
136
  ): Record<string, string> {
121
137
  if (!deps) return {};
122
138
  const resolved = { ...deps };
@@ -131,21 +147,13 @@ function resolveFlowDeps(
131
147
  for (const k of Object.keys(resolved)) {
132
148
  if (!k.startsWith("@flow-os/")) continue;
133
149
  const v = resolved[k];
134
- if (v !== "workspace:*" && v !== "0.0.1" && k !== "@flow-os/client") continue;
150
+ if (v !== "workspace:*" && v !== "0.0.1" && !versionsFromNpm.has(k)) continue;
135
151
  let spec: string | undefined;
136
- if (k === "@flow-os/client") {
137
- if (clientVersionFromNpm) {
138
- spec = isDevSpec ? "dev" : `^${clientVersionFromNpm}`;
139
- } else if (isDevSpec) {
140
- spec = "dev";
141
- } else {
142
- try {
143
- const root = pkgRoot(k);
144
- const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf-8")) as { version?: string };
145
- if (pkg.version) spec = `^${pkg.version}`;
146
- } catch {}
147
- if (!spec && ownerVersion) spec = `^${ownerVersion}`;
148
- }
152
+ const npmVer = versionsFromNpm.get(k);
153
+ if (npmVer) {
154
+ spec = isDevSpec && k === "@flow-os/client" ? "dev" : `^${npmVer}`;
155
+ } else if (k === "@flow-os/client" && isDevSpec) {
156
+ spec = "dev";
149
157
  } else {
150
158
  try {
151
159
  const root = pkgRoot(k);
@@ -159,7 +167,7 @@ function resolveFlowDeps(
159
167
  return resolved;
160
168
  }
161
169
 
162
- function mergePkg(configDir: string, cwd: string, clientVersionFromNpm: string | undefined): void {
170
+ function mergePkg(configDir: string, cwd: string, versionsFromNpm: Map<string, string>): void {
163
171
  const configPkg = join(configDir, "package.json");
164
172
  if (!existsSync(configPkg)) return;
165
173
  const targetPath = join(cwd, "package.json");
@@ -169,52 +177,94 @@ function mergePkg(configDir: string, cwd: string, clientVersionFromNpm: string |
169
177
  : { ...config, name: basename(cwd) || "flow-app" };
170
178
  target.dependencies = { ...target.dependencies, ...config.dependencies };
171
179
  target.devDependencies = { ...target.devDependencies, ...config.devDependencies };
172
- for (const [k, v] of Object.entries(resolveFlowDeps(config.dependencies, configDir, clientVersionFromNpm)))
180
+ for (const [k, v] of Object.entries(resolveFlowDeps(config.dependencies, configDir, versionsFromNpm)))
173
181
  target.dependencies[k] = v;
174
- for (const [k, v] of Object.entries(resolveFlowDeps(config.devDependencies, configDir, clientVersionFromNpm)))
182
+ for (const [k, v] of Object.entries(resolveFlowDeps(config.devDependencies, configDir, versionsFromNpm)))
175
183
  target.devDependencies[k] = v;
176
184
  target.scripts = { ...target.scripts, ...config.scripts };
177
185
  writeFileSync(targetPath, JSON.stringify(target, null, 2));
178
186
  }
179
187
 
188
+ /** Assicura che versions abbia le versioni per pkgNames (fetch lazy) */
189
+ async function ensureVersions(versions: Map<string, string>, pkgNames: string[]): Promise<void> {
190
+ const missing = pkgNames.filter((n) => !versions.has(n));
191
+ if (!missing.length) return;
192
+ const fetched = await fetchFlowPackageVersions(missing);
193
+ for (const [k, v] of fetched) versions.set(k, v);
194
+ }
195
+
196
+ /** Legge flow deps da package.json (path a package.json o dir che lo contiene) */
197
+ function flowDepsFromPkg(pkgPath: string): string[] {
198
+ const pkgJson = pkgPath.endsWith("package.json") ? pkgPath : join(pkgPath, "package.json");
199
+ if (!existsSync(pkgJson)) return [];
200
+ try {
201
+ const pkg = JSON.parse(readFileSync(pkgJson, "utf-8"));
202
+ const deps = { ...pkg.dependencies, ...pkg.peerDependencies } as Record<string, string>;
203
+ return Object.keys(deps).filter((k) => k.startsWith("@flow-os/"));
204
+ } catch {
205
+ return [];
206
+ }
207
+ }
208
+
180
209
  /** Fase 1: raccoglie e merge tutti i template in memoria, ritorna ordine pacchetti */
181
210
  async function collectAllTemplates(
182
211
  libs: string[],
183
212
  combined: Map<string, string>,
184
213
  done: Set<string>,
185
214
  order: string[],
186
- clientVersionFromNpm: string | undefined,
215
+ versionsFromNpm: Map<string, string>,
187
216
  tmpDirs: string[]
188
217
  ): Promise<void> {
189
218
  for (const lib of libs) {
190
219
  const pkgName = toPkgName(lib);
191
220
  if (done.has(pkgName)) continue;
192
221
 
193
- const root = pkgRoot(pkgName);
194
- const configDir = join(root, "config");
195
- if (!existsSync(configDir) && pkgName !== "@flow-os/client") continue;
196
-
197
- for (const sub of flowDeps(root)) {
198
- await collectAllTemplates([toShortName(sub)], combined, done, order, clientVersionFromNpm, tmpDirs);
222
+ let root: string;
223
+ let configDir: string;
224
+ try {
225
+ root = pkgRoot(pkgName);
226
+ configDir = join(root, "config");
227
+ } catch {
228
+ root = "";
229
+ configDir = "";
199
230
  }
231
+ const hasLocal = existsSync(configDir);
200
232
 
201
233
  let pkgFiles: Map<string, string>;
202
234
  let configDirForPkg: string;
203
- if (pkgName === "@flow-os/client" && clientVersionFromNpm) {
204
- const fetched = await fetchConfigFromNpm(pkgName, clientVersionFromNpm);
235
+ const npmVer = versionsFromNpm.get(pkgName);
236
+ if (npmVer) {
237
+ const fetched = await fetchConfigFromNpm(pkgName, npmVer);
205
238
  if (fetched) {
206
239
  pkgFiles = fetched.files;
207
240
  configDirForPkg = fetched.configDir;
208
241
  tmpDirs.push(fetched.tmpDir);
209
- } else {
210
- if (!existsSync(configDir)) continue;
242
+ const subDeps = flowDepsFromPkg(join(configDirForPkg, ".."));
243
+ await ensureVersions(versionsFromNpm, subDeps);
244
+ for (const sub of subDeps) {
245
+ await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs);
246
+ }
247
+ } else if (hasLocal) {
248
+ const subDeps = flowDeps(root);
249
+ await ensureVersions(versionsFromNpm, subDeps);
250
+ for (const sub of subDeps) {
251
+ await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs);
252
+ }
211
253
  pkgFiles = collectConfigFiles(configDir);
212
254
  configDirForPkg = configDir;
255
+ } else {
256
+ continue;
257
+ }
258
+ } else if (hasLocal) {
259
+ const subDeps = flowDeps(root);
260
+ await ensureVersions(versionsFromNpm, subDeps);
261
+ for (const sub of subDeps) {
262
+ await collectAllTemplates([toShortName(sub)], combined, done, order, versionsFromNpm, tmpDirs);
213
263
  }
214
- } else {
215
- if (!existsSync(configDir)) continue;
216
264
  pkgFiles = collectConfigFiles(configDir);
217
265
  configDirForPkg = configDir;
266
+ } else {
267
+ continue;
218
268
  }
219
269
  mergeTemplateInto(combined, pkgFiles);
220
270
  order.push(configDirForPkg);
@@ -222,20 +272,25 @@ async function collectAllTemplates(
222
272
  }
223
273
  }
224
274
 
225
- /** Init: 1) merge tutti i template in memoria, 2) mergePkg per ogni lib, 3) un solo merge con file utente */
275
+ /** Init: 1) fetch versioni npm per tutti i pacchetti, 2) merge template in memoria, 3) mergePkg, 4) merge con file utente */
226
276
  export async function initLib(
227
277
  libs: string[],
228
278
  cwd: string,
229
- clientVersionFromNpm?: string
279
+ versionsFromNpm?: Map<string, string>
230
280
  ): Promise<void> {
281
+ const pkgNames = libs.map(toPkgName);
282
+ const versions = versionsFromNpm ?? new Map<string, string>();
283
+ const fetched = await fetchFlowPackageVersions(pkgNames);
284
+ for (const [k, v] of fetched) versions.set(k, v);
285
+
231
286
  const combined = new Map<string, string>();
232
287
  const done = new Set<string>();
233
288
  const order: string[] = [];
234
289
  const tmpDirs: string[] = [];
235
- await collectAllTemplates(libs, combined, done, order, clientVersionFromNpm, tmpDirs);
290
+ await collectAllTemplates(libs, combined, done, order, versions, tmpDirs);
236
291
 
237
292
  for (const configDir of order) {
238
- mergePkg(configDir, cwd, clientVersionFromNpm);
293
+ mergePkg(configDir, cwd, versions);
239
294
  }
240
295
 
241
296
  await writeMergedWithUser(combined, cwd, (path, conflicts) => resolveConflicts(conflicts, path));