create-flow-os 0.0.24 → 0.0.26
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/.vscode/settings.json +6 -6
- package/package.json +2 -2
- package/prova.tsx +2 -0
- package/src/init/index.ts +8 -7
- package/src/init/scaffold.ts +97 -42
package/.vscode/settings.json
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"license": "PolyForm-Shield-1.0.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@flow-os/client": "^0.0.
|
|
7
|
+
"@flow-os/client": "^0.0.26"
|
|
8
8
|
},
|
|
9
9
|
"bin": {
|
|
10
10
|
"create-flow-os": "./src/index.ts"
|
package/prova.tsx
ADDED
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,
|
|
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
|
|
65
|
+
// Execute: fetch versioni pacchetti da npm (latest/dev), init libs, poi output box
|
|
66
66
|
// ───────────────────────────────────────────────────────────────────────────────
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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;
|
package/src/init/scaffold.ts
CHANGED
|
@@ -72,24 +72,40 @@ function isCreateFlowOsDev(): boolean {
|
|
|
72
72
|
}
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
/** Recupera
|
|
76
|
-
|
|
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}
|
|
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
|
-
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
|
|
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
|
|
150
|
+
if (v !== "workspace:*" && v !== "0.0.1" && !versionsFromNpm.has(k)) continue;
|
|
135
151
|
let spec: string | undefined;
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
204
|
-
|
|
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
|
-
|
|
210
|
-
|
|
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)
|
|
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
|
-
|
|
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,
|
|
290
|
+
await collectAllTemplates(libs, combined, done, order, versions, tmpDirs);
|
|
236
291
|
|
|
237
292
|
for (const configDir of order) {
|
|
238
|
-
mergePkg(configDir, cwd,
|
|
293
|
+
mergePkg(configDir, cwd, versions);
|
|
239
294
|
}
|
|
240
295
|
|
|
241
296
|
await writeMergedWithUser(combined, cwd, (path, conflicts) => resolveConflicts(conflicts, path));
|