create-flow-os 0.0.23 → 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.
- 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 +140 -36
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.25",
|
|
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.25"
|
|
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,28 +72,67 @@ 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
|
|
|
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) */
|
|
109
|
+
async function fetchConfigFromNpm(
|
|
110
|
+
pkgName: string,
|
|
111
|
+
version: string
|
|
112
|
+
): Promise<{ files: Map<string, string>; configDir: string; tmpDir: string } | null> {
|
|
113
|
+
const shortName = pkgName.replace(/^@flow-os\//, "");
|
|
114
|
+
const url = `${NPM_REGISTRY}/${pkgName}/-/${shortName}-${version}.tgz`;
|
|
115
|
+
try {
|
|
116
|
+
const res = await fetch(url, { cache: "no-store" });
|
|
117
|
+
if (!res.ok) return null;
|
|
118
|
+
const archive = new Bun.Archive(await res.blob());
|
|
119
|
+
const { tmpdir } = await import("os");
|
|
120
|
+
const tmpDir = join(tmpdir(), `flow-os-${shortName}-${version}-${Date.now()}`);
|
|
121
|
+
await archive.extract(tmpDir, { glob: ["package/config/**"] });
|
|
122
|
+
const configDir = join(tmpDir, "package", "config");
|
|
123
|
+
if (!existsSync(configDir)) return null;
|
|
124
|
+
const files = collectConfigFiles(configDir);
|
|
125
|
+
return { files, configDir, tmpDir };
|
|
126
|
+
} catch {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
92
131
|
/** Sostituisce workspace:* e 0.0.1 con versione concreta (workspace va bene solo dentro flow-os) */
|
|
93
132
|
function resolveFlowDeps(
|
|
94
133
|
deps: Record<string, string> | undefined,
|
|
95
134
|
configDir: string,
|
|
96
|
-
|
|
135
|
+
versionsFromNpm: Map<string, string>
|
|
97
136
|
): Record<string, string> {
|
|
98
137
|
if (!deps) return {};
|
|
99
138
|
const resolved = { ...deps };
|
|
@@ -108,21 +147,13 @@ function resolveFlowDeps(
|
|
|
108
147
|
for (const k of Object.keys(resolved)) {
|
|
109
148
|
if (!k.startsWith("@flow-os/")) continue;
|
|
110
149
|
const v = resolved[k];
|
|
111
|
-
if (v !== "workspace:*" && v !== "0.0.1" && k
|
|
150
|
+
if (v !== "workspace:*" && v !== "0.0.1" && !versionsFromNpm.has(k)) continue;
|
|
112
151
|
let spec: string | undefined;
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
} else {
|
|
119
|
-
try {
|
|
120
|
-
const root = pkgRoot(k);
|
|
121
|
-
const pkg = JSON.parse(readFileSync(join(root, "package.json"), "utf-8")) as { version?: string };
|
|
122
|
-
if (pkg.version) spec = `^${pkg.version}`;
|
|
123
|
-
} catch {}
|
|
124
|
-
if (!spec && ownerVersion) spec = `^${ownerVersion}`;
|
|
125
|
-
}
|
|
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";
|
|
126
157
|
} else {
|
|
127
158
|
try {
|
|
128
159
|
const root = pkgRoot(k);
|
|
@@ -136,7 +167,7 @@ function resolveFlowDeps(
|
|
|
136
167
|
return resolved;
|
|
137
168
|
}
|
|
138
169
|
|
|
139
|
-
function mergePkg(configDir: string, cwd: string,
|
|
170
|
+
function mergePkg(configDir: string, cwd: string, versionsFromNpm: Map<string, string>): void {
|
|
140
171
|
const configPkg = join(configDir, "package.json");
|
|
141
172
|
if (!existsSync(configPkg)) return;
|
|
142
173
|
const targetPath = join(cwd, "package.json");
|
|
@@ -146,55 +177,128 @@ function mergePkg(configDir: string, cwd: string, clientVersionFromNpm: string |
|
|
|
146
177
|
: { ...config, name: basename(cwd) || "flow-app" };
|
|
147
178
|
target.dependencies = { ...target.dependencies, ...config.dependencies };
|
|
148
179
|
target.devDependencies = { ...target.devDependencies, ...config.devDependencies };
|
|
149
|
-
for (const [k, v] of Object.entries(resolveFlowDeps(config.dependencies, configDir,
|
|
180
|
+
for (const [k, v] of Object.entries(resolveFlowDeps(config.dependencies, configDir, versionsFromNpm)))
|
|
150
181
|
target.dependencies[k] = v;
|
|
151
|
-
for (const [k, v] of Object.entries(resolveFlowDeps(config.devDependencies, configDir,
|
|
182
|
+
for (const [k, v] of Object.entries(resolveFlowDeps(config.devDependencies, configDir, versionsFromNpm)))
|
|
152
183
|
target.devDependencies[k] = v;
|
|
153
184
|
target.scripts = { ...target.scripts, ...config.scripts };
|
|
154
185
|
writeFileSync(targetPath, JSON.stringify(target, null, 2));
|
|
155
186
|
}
|
|
156
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
|
+
|
|
157
209
|
/** Fase 1: raccoglie e merge tutti i template in memoria, ritorna ordine pacchetti */
|
|
158
210
|
async function collectAllTemplates(
|
|
159
211
|
libs: string[],
|
|
160
212
|
combined: Map<string, string>,
|
|
161
213
|
done: Set<string>,
|
|
162
214
|
order: string[],
|
|
163
|
-
|
|
215
|
+
versionsFromNpm: Map<string, string>,
|
|
216
|
+
tmpDirs: string[]
|
|
164
217
|
): Promise<void> {
|
|
165
218
|
for (const lib of libs) {
|
|
166
219
|
const pkgName = toPkgName(lib);
|
|
167
220
|
if (done.has(pkgName)) continue;
|
|
168
221
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
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 = "";
|
|
175
230
|
}
|
|
231
|
+
const hasLocal = existsSync(configDir);
|
|
176
232
|
|
|
177
|
-
|
|
233
|
+
let pkgFiles: Map<string, string>;
|
|
234
|
+
let configDirForPkg: string;
|
|
235
|
+
const npmVer = versionsFromNpm.get(pkgName);
|
|
236
|
+
if (npmVer) {
|
|
237
|
+
const fetched = await fetchConfigFromNpm(pkgName, npmVer);
|
|
238
|
+
if (fetched) {
|
|
239
|
+
pkgFiles = fetched.files;
|
|
240
|
+
configDirForPkg = fetched.configDir;
|
|
241
|
+
tmpDirs.push(fetched.tmpDir);
|
|
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
|
+
}
|
|
253
|
+
pkgFiles = collectConfigFiles(configDir);
|
|
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);
|
|
263
|
+
}
|
|
264
|
+
pkgFiles = collectConfigFiles(configDir);
|
|
265
|
+
configDirForPkg = configDir;
|
|
266
|
+
} else {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
178
269
|
mergeTemplateInto(combined, pkgFiles);
|
|
179
|
-
order.push(
|
|
270
|
+
order.push(configDirForPkg);
|
|
180
271
|
done.add(pkgName);
|
|
181
272
|
}
|
|
182
273
|
}
|
|
183
274
|
|
|
184
|
-
/** Init: 1)
|
|
275
|
+
/** Init: 1) fetch versioni npm per tutti i pacchetti, 2) merge template in memoria, 3) mergePkg, 4) merge con file utente */
|
|
185
276
|
export async function initLib(
|
|
186
277
|
libs: string[],
|
|
187
278
|
cwd: string,
|
|
188
|
-
|
|
279
|
+
versionsFromNpm?: Map<string, string>
|
|
189
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
|
+
|
|
190
286
|
const combined = new Map<string, string>();
|
|
191
287
|
const done = new Set<string>();
|
|
192
288
|
const order: string[] = [];
|
|
193
|
-
|
|
289
|
+
const tmpDirs: string[] = [];
|
|
290
|
+
await collectAllTemplates(libs, combined, done, order, versions, tmpDirs);
|
|
194
291
|
|
|
195
292
|
for (const configDir of order) {
|
|
196
|
-
mergePkg(configDir, cwd,
|
|
293
|
+
mergePkg(configDir, cwd, versions);
|
|
197
294
|
}
|
|
198
295
|
|
|
199
296
|
await writeMergedWithUser(combined, cwd, (path, conflicts) => resolveConflicts(conflicts, path));
|
|
297
|
+
|
|
298
|
+
const { rmSync } = await import("fs");
|
|
299
|
+
for (const d of tmpDirs) {
|
|
300
|
+
try {
|
|
301
|
+
rmSync(d, { recursive: true, force: true });
|
|
302
|
+
} catch {}
|
|
303
|
+
}
|
|
200
304
|
}
|