create-flow-os 0.0.1-dev.1771667897 → 0.0.1-dev.1771668924
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/bin/index.js +131 -33
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -872,10 +872,107 @@ var useDevTag = argv.includes("--dev");
|
|
|
872
872
|
var nameArg = argv.find((a3) => !a3.startsWith("--"));
|
|
873
873
|
var DIR = basename(import.meta.dir) === "dist" || basename(import.meta.dir) === "bin" ? join2(import.meta.dir, "..") : import.meta.dir;
|
|
874
874
|
var REPO_ROOT = (process.env.FLOW_FRAMEWORK_ROOT ?? join2(DIR, "..", "..")).replace(/\\/g, "/");
|
|
875
|
-
var
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
875
|
+
var c2 = {
|
|
876
|
+
brand: (s) => import_picocolors3.default.bold(import_picocolors3.default.cyan(s)),
|
|
877
|
+
cyan: (s) => import_picocolors3.default.cyan(s),
|
|
878
|
+
dim: (s) => import_picocolors3.default.dim(s),
|
|
879
|
+
bold: (s) => import_picocolors3.default.bold(s),
|
|
880
|
+
muted: (s) => import_picocolors3.default.cyan(s),
|
|
881
|
+
bright: (s) => import_picocolors3.default.white(s)
|
|
882
|
+
};
|
|
883
|
+
var W2 = 50;
|
|
884
|
+
var ICON = {
|
|
885
|
+
full: "\u25C9",
|
|
886
|
+
client: "\u25C6",
|
|
887
|
+
server: "\u25CF",
|
|
888
|
+
deps: "\uD83D\uDCE6",
|
|
889
|
+
rocket: "\u25B6"
|
|
890
|
+
};
|
|
891
|
+
function stripAnsi(s) {
|
|
892
|
+
return s.replace(/\x1b\[[0-9;]*m/g, "");
|
|
893
|
+
}
|
|
894
|
+
function box(lines) {
|
|
895
|
+
const top = c2.dim("\u256D" + "\u2500".repeat(W2 - 2) + "\u256E");
|
|
896
|
+
const bottom = c2.dim("\u2570" + "\u2500".repeat(W2 - 2) + "\u256F");
|
|
897
|
+
const body = lines.map((l2) => {
|
|
898
|
+
const plain = stripAnsi(l2);
|
|
899
|
+
const pad = Math.max(0, W2 - 4 - plain.length);
|
|
900
|
+
return c2.dim("\u2502 ") + l2 + " ".repeat(pad) + c2.dim(" \u2502");
|
|
901
|
+
}).join(`
|
|
902
|
+
`);
|
|
903
|
+
return `
|
|
904
|
+
` + top + `
|
|
905
|
+
` + body + `
|
|
906
|
+
` + bottom + `
|
|
907
|
+
`;
|
|
908
|
+
}
|
|
909
|
+
var LOCAL_URL_RE = /https?:\/\/localhost(:\d+)?(?:\/[^\s]*)?/i;
|
|
910
|
+
function flowBanner(url) {
|
|
911
|
+
const link = c2.brand(url);
|
|
912
|
+
return [
|
|
913
|
+
"",
|
|
914
|
+
c2.cyan(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"),
|
|
915
|
+
c2.cyan(" \u2502 ") + c2.bold("Flow OS") + c2.cyan(" is running \u2502"),
|
|
916
|
+
c2.cyan(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"),
|
|
917
|
+
"",
|
|
918
|
+
" Open: " + link,
|
|
919
|
+
""
|
|
920
|
+
].join(`
|
|
921
|
+
`);
|
|
922
|
+
}
|
|
923
|
+
async function runDevWithBanner(cwd) {
|
|
924
|
+
const devProc = Bun.spawn(["bun", "run", "dev"], {
|
|
925
|
+
cwd,
|
|
926
|
+
stdout: "pipe",
|
|
927
|
+
stderr: "pipe",
|
|
928
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
929
|
+
});
|
|
930
|
+
let bannerShown = false;
|
|
931
|
+
const decoder = new TextDecoder;
|
|
932
|
+
let outBuf = "";
|
|
933
|
+
const drain = (stream, isErr) => {
|
|
934
|
+
const target = isErr ? process.stderr : process.stdout;
|
|
935
|
+
const reader = stream.getReader();
|
|
936
|
+
function read() {
|
|
937
|
+
return reader.read().then(({ done, value }) => {
|
|
938
|
+
const text = value ? decoder.decode(value, { stream: !done }) : "";
|
|
939
|
+
if (isErr) {
|
|
940
|
+
if (text)
|
|
941
|
+
target.write(text);
|
|
942
|
+
return done ? undefined : read();
|
|
943
|
+
}
|
|
944
|
+
if (text)
|
|
945
|
+
outBuf += text;
|
|
946
|
+
const lines = outBuf.split(/\r?\n/);
|
|
947
|
+
outBuf = done ? "" : lines.pop() ?? "";
|
|
948
|
+
for (const line of lines) {
|
|
949
|
+
const urlMatch = line.match(LOCAL_URL_RE);
|
|
950
|
+
if (!bannerShown && urlMatch) {
|
|
951
|
+
bannerShown = true;
|
|
952
|
+
process.stdout.write(flowBanner(urlMatch[0]));
|
|
953
|
+
}
|
|
954
|
+
target.write(line + `
|
|
955
|
+
`);
|
|
956
|
+
}
|
|
957
|
+
if (done && outBuf) {
|
|
958
|
+
const urlMatch = outBuf.match(LOCAL_URL_RE);
|
|
959
|
+
if (!bannerShown && urlMatch) {
|
|
960
|
+
bannerShown = true;
|
|
961
|
+
process.stdout.write(flowBanner(urlMatch[0]));
|
|
962
|
+
}
|
|
963
|
+
target.write(outBuf);
|
|
964
|
+
}
|
|
965
|
+
return done ? undefined : read();
|
|
966
|
+
});
|
|
967
|
+
}
|
|
968
|
+
return read();
|
|
969
|
+
};
|
|
970
|
+
await Promise.all([
|
|
971
|
+
drain(devProc.stdout, false),
|
|
972
|
+
drain(devProc.stderr, true)
|
|
973
|
+
]).catch(() => {});
|
|
974
|
+
await devProc.exited;
|
|
975
|
+
}
|
|
879
976
|
function optsForProfile(config, profileId) {
|
|
880
977
|
return Object.entries(config.packages).filter(([, e2]) => {
|
|
881
978
|
const inc = e2.includeIn ?? [];
|
|
@@ -887,20 +984,24 @@ function optsForProfile(config, profileId) {
|
|
|
887
984
|
});
|
|
888
985
|
}
|
|
889
986
|
async function main() {
|
|
890
|
-
const devBadge = useDevTag ?
|
|
891
|
-
|
|
892
|
-
|
|
987
|
+
const devBadge = useDevTag ? c2.brand(" \xB7 dev") : "";
|
|
988
|
+
const introLines = [
|
|
989
|
+
c2.bold("Flow") + devBadge,
|
|
990
|
+
"",
|
|
991
|
+
c2.cyan("We're creating your Flow application.")
|
|
992
|
+
];
|
|
993
|
+
pe(box(introLines));
|
|
893
994
|
const config = await Bun.file(join2(DIR, "config.json")).json();
|
|
894
995
|
const hasDeps = Object.values(config.packages).every((e2) => Array.isArray(e2.deps));
|
|
895
996
|
if (!hasDeps) {
|
|
896
|
-
he(dim("Run ") +
|
|
997
|
+
he(c2.dim("Run ") + c2.brand("bun run gen") + c2.dim(" from create-flow first."));
|
|
897
998
|
process.exit(1);
|
|
898
999
|
}
|
|
899
1000
|
const projectName = nameArg?.trim() || (yes ? "my-flow-app" : null);
|
|
900
1001
|
let name = projectName;
|
|
901
1002
|
if (!name && !yes) {
|
|
902
1003
|
const r2 = await ae({
|
|
903
|
-
message:
|
|
1004
|
+
message: c2.muted("Project name"),
|
|
904
1005
|
initialValue: "my-flow-app",
|
|
905
1006
|
validate: (v3) => !v3?.trim() ? "Required" : undefined
|
|
906
1007
|
});
|
|
@@ -918,11 +1019,11 @@ async function main() {
|
|
|
918
1019
|
selected = optsFull.map(([id]) => id);
|
|
919
1020
|
} else {
|
|
920
1021
|
const choice = await le({
|
|
921
|
-
message:
|
|
1022
|
+
message: c2.muted("Template"),
|
|
922
1023
|
options: [
|
|
923
|
-
{ value: "full", label:
|
|
924
|
-
{ value: "client", label:
|
|
925
|
-
{ value: "server", label:
|
|
1024
|
+
{ value: "full", label: `${ICON.full} Full stack ${c2.dim("(client + server)")}` },
|
|
1025
|
+
{ value: "client", label: `${ICON.client} Client only` },
|
|
1026
|
+
{ value: "server", label: `${ICON.server} Server only` }
|
|
926
1027
|
]
|
|
927
1028
|
});
|
|
928
1029
|
if (lD(choice))
|
|
@@ -938,7 +1039,7 @@ async function main() {
|
|
|
938
1039
|
const optionalIds = optIds.filter((id) => !defaultIds.includes(id));
|
|
939
1040
|
if (optionalIds.length > 0) {
|
|
940
1041
|
const r2 = await $e({
|
|
941
|
-
message:
|
|
1042
|
+
message: c2.muted("Add-ons"),
|
|
942
1043
|
options: optionalIds.map((id) => ({ value: id, label: id })),
|
|
943
1044
|
required: false
|
|
944
1045
|
});
|
|
@@ -956,17 +1057,17 @@ async function main() {
|
|
|
956
1057
|
stat(projectPath).then(() => true).catch(() => false)
|
|
957
1058
|
]);
|
|
958
1059
|
if (!profileExists) {
|
|
959
|
-
he(dim("Profile not found. Run ") +
|
|
1060
|
+
he(c2.dim("Profile not found. Run ") + c2.brand("bun run gen") + c2.dim("."));
|
|
960
1061
|
process.exit(1);
|
|
961
1062
|
}
|
|
962
1063
|
if (pathExists && !force) {
|
|
963
|
-
he(dim("Folder ") + name + dim(" exists. Use ") +
|
|
1064
|
+
he(c2.dim("Folder ") + name + c2.dim(" exists. Use ") + c2.brand("--force") + c2.dim("."));
|
|
964
1065
|
process.exit(1);
|
|
965
1066
|
}
|
|
966
1067
|
const isDevFromRepoPromise = useDevTag ? findPackageDir(REPO_ROOT, "@flow.os/client").then((d2) => !!d2) : Promise.resolve(false);
|
|
967
1068
|
await rm(projectPathNew, { recursive: true, force: true });
|
|
968
1069
|
const createSpinner = _2();
|
|
969
|
-
createSpinner.start(
|
|
1070
|
+
createSpinner.start(c2.cyan(ICON.rocket + " Creating project\u2026"));
|
|
970
1071
|
await copyWithExclude(profileDir, projectPathNew, ["node_modules", ".git"]);
|
|
971
1072
|
for (const id of selected) {
|
|
972
1073
|
const pkgDir = join2(DIR, "packages", id);
|
|
@@ -974,7 +1075,7 @@ async function main() {
|
|
|
974
1075
|
await copyWithExclude(pkgDir, projectPathNew, []);
|
|
975
1076
|
} catch {}
|
|
976
1077
|
}
|
|
977
|
-
createSpinner.stop(
|
|
1078
|
+
createSpinner.stop(c2.cyan(ICON.rocket + " Project created"));
|
|
978
1079
|
const extraDeps = {};
|
|
979
1080
|
for (const id of selected) {
|
|
980
1081
|
const deps = config.packages[id]?.deps;
|
|
@@ -1028,10 +1129,10 @@ async function main() {
|
|
|
1028
1129
|
}
|
|
1029
1130
|
if (!noInstall) {
|
|
1030
1131
|
const s = _2();
|
|
1031
|
-
s.start(
|
|
1132
|
+
s.start(c2.cyan(ICON.deps + " Installing dependencies\u2026"));
|
|
1032
1133
|
const proc = Bun.spawn(["bun", "install"], { cwd: projectPathNew, stdout: "pipe", stderr: "pipe" });
|
|
1033
1134
|
const code = await proc.exited;
|
|
1034
|
-
s.stop(code === 0 ?
|
|
1135
|
+
s.stop(code === 0 ? c2.cyan(ICON.deps + " Dependencies installed") : "Failed");
|
|
1035
1136
|
if (code !== 0) {
|
|
1036
1137
|
const err = await new Response(proc.stderr).text();
|
|
1037
1138
|
v2.error(err || "bun install exit " + code);
|
|
@@ -1044,20 +1145,17 @@ async function main() {
|
|
|
1044
1145
|
await rename(projectPathNew, projectPath);
|
|
1045
1146
|
const startDev = !noStart && !noInstall;
|
|
1046
1147
|
if (startDev) {
|
|
1047
|
-
ge(
|
|
1048
|
-
|
|
1049
|
-
`));
|
|
1050
|
-
const devProc = Bun.spawn(["bun", "run", "dev"], {
|
|
1051
|
-
cwd: projectPath,
|
|
1052
|
-
stdio: "inherit"
|
|
1053
|
-
});
|
|
1054
|
-
await devProc.exited;
|
|
1148
|
+
ge(c2.cyan(ICON.rocket + " Starting dev server\u2026"));
|
|
1149
|
+
await runDevWithBanner(projectPath);
|
|
1055
1150
|
} else {
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1151
|
+
const outroLines = [
|
|
1152
|
+
c2.bold("Done"),
|
|
1153
|
+
"",
|
|
1154
|
+
c2.dim("Next steps:"),
|
|
1155
|
+
" " + c2.brand("cd " + name),
|
|
1156
|
+
" " + c2.brand("bun run dev")
|
|
1157
|
+
];
|
|
1158
|
+
ge(box(outroLines));
|
|
1061
1159
|
}
|
|
1062
1160
|
}
|
|
1063
1161
|
main().catch((e2) => {
|