@pylonsync/create-pylon 0.3.18 → 0.3.20
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/create-pylon.js +105 -11
- package/package.json +1 -1
package/bin/create-pylon.js
CHANGED
|
@@ -25,7 +25,7 @@ import { stdin, stdout, exit, argv, cwd } from "node:process";
|
|
|
25
25
|
// of the pylon stack).
|
|
26
26
|
// ---------------------------------------------------------------------------
|
|
27
27
|
|
|
28
|
-
const PYLON_VERSION = "0.3.
|
|
28
|
+
const PYLON_VERSION = "0.3.20";
|
|
29
29
|
|
|
30
30
|
// ---------------------------------------------------------------------------
|
|
31
31
|
// CLI args + interactive prompt
|
|
@@ -35,9 +35,9 @@ const args = argv.slice(2);
|
|
|
35
35
|
let projectName = args.find((a) => !a.startsWith("--"));
|
|
36
36
|
|
|
37
37
|
const flags = {
|
|
38
|
-
pm:
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
pm: args.find(
|
|
39
|
+
(a) => a === "--bun" || a === "--pnpm" || a === "--yarn" || a === "--npm",
|
|
40
|
+
)?.slice(2),
|
|
41
41
|
skipInstall: args.includes("--skip-install"),
|
|
42
42
|
help: args.includes("--help") || args.includes("-h"),
|
|
43
43
|
};
|
|
@@ -47,11 +47,35 @@ if (flags.help) {
|
|
|
47
47
|
exit(0);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
+
// Interactive prompts for project name + package manager. Default
|
|
51
|
+
// PM to bun: it handles `workspace:*` correctly out of the box,
|
|
52
|
+
// installs faster than the alternatives, and is what the
|
|
53
|
+
// @pylonsync/* packages are tested against. The user can pick
|
|
54
|
+
// anything though.
|
|
55
|
+
const rl = createInterface({ input: stdin, output: stdout });
|
|
50
56
|
if (!projectName) {
|
|
51
|
-
const rl = createInterface({ input: stdin, output: stdout });
|
|
52
57
|
projectName = (await rl.question("Project name: ")).trim() || "my-pylon-app";
|
|
53
|
-
rl.close();
|
|
54
58
|
}
|
|
59
|
+
if (!flags.pm) {
|
|
60
|
+
const detected = detectPackageManager();
|
|
61
|
+
const def = detected ?? "bun";
|
|
62
|
+
const choice = (
|
|
63
|
+
await rl.question(`Package manager (bun, pnpm, yarn, npm) [${def}]: `)
|
|
64
|
+
)
|
|
65
|
+
.trim()
|
|
66
|
+
.toLowerCase();
|
|
67
|
+
flags.pm = ["bun", "pnpm", "yarn", "npm"].includes(choice) ? choice : def;
|
|
68
|
+
}
|
|
69
|
+
rl.close();
|
|
70
|
+
|
|
71
|
+
// Some PMs reject the `workspace:` protocol. Bun/pnpm/yarn berry
|
|
72
|
+
// understand it and rewrite to the local sibling version at install
|
|
73
|
+
// time. npm errors EUNSUPPORTEDPROTOCOL ("Unsupported URL Type").
|
|
74
|
+
// For npm, emit "*" — npm's own workspaces feature still resolves
|
|
75
|
+
// it to the local sibling because the workspace package is in the
|
|
76
|
+
// root's `workspaces` list.
|
|
77
|
+
const usesWorkspaceProtocol = flags.pm !== "npm";
|
|
78
|
+
const workspaceDepSpec = usesWorkspaceProtocol ? "workspace:*" : "*";
|
|
55
79
|
|
|
56
80
|
const root = resolve(cwd(), projectName);
|
|
57
81
|
|
|
@@ -82,6 +106,12 @@ function writeJson(path, value) {
|
|
|
82
106
|
// Root workspace
|
|
83
107
|
// ---------------------------------------------------------------------------
|
|
84
108
|
|
|
109
|
+
// Per-PM script syntax: bun has its own --filter, pnpm uses --filter,
|
|
110
|
+
// npm/yarn use --workspace. Picking the right shape at scaffold time
|
|
111
|
+
// means `npm run dev` (or whichever PM) works without the user
|
|
112
|
+
// learning each PM's flag dialect.
|
|
113
|
+
const wsScripts = pmScripts(flags.pm);
|
|
114
|
+
|
|
85
115
|
writeJson("package.json", {
|
|
86
116
|
name: projectName,
|
|
87
117
|
private: true,
|
|
@@ -89,9 +119,9 @@ writeJson("package.json", {
|
|
|
89
119
|
workspaces: ["apps/*", "packages/*"],
|
|
90
120
|
scripts: {
|
|
91
121
|
dev: "npm-run-all --parallel dev:api dev:web",
|
|
92
|
-
"dev:api":
|
|
93
|
-
"dev:web":
|
|
94
|
-
build:
|
|
122
|
+
"dev:api": wsScripts.devApi,
|
|
123
|
+
"dev:web": wsScripts.devWeb,
|
|
124
|
+
build: wsScripts.build,
|
|
95
125
|
},
|
|
96
126
|
devDependencies: {
|
|
97
127
|
"npm-run-all": "^4.1.5",
|
|
@@ -526,7 +556,7 @@ writeJson("apps/web/package.json", {
|
|
|
526
556
|
lint: "next lint",
|
|
527
557
|
},
|
|
528
558
|
dependencies: {
|
|
529
|
-
[`@${projectName}/ui`]:
|
|
559
|
+
[`@${projectName}/ui`]: workspaceDepSpec,
|
|
530
560
|
"@pylonsync/sdk": `^${PYLON_VERSION}`,
|
|
531
561
|
"@pylonsync/react": `^${PYLON_VERSION}`,
|
|
532
562
|
"@pylonsync/next": `^${PYLON_VERSION}`,
|
|
@@ -574,7 +604,20 @@ write(
|
|
|
574
604
|
* Pylon's typed client + functions packages re-export across the
|
|
575
605
|
* server/client boundary AND the workspace UI package ships TSX.
|
|
576
606
|
* \`transpilePackages\` makes Next bundle them cleanly.
|
|
607
|
+
*
|
|
608
|
+
* \`rewrites\` proxies every Pylon-owned path (\`/api/fn/*\`,
|
|
609
|
+
* \`/api/auth/*\`, \`/api/sync/*\`, …) to the Pylon binary running
|
|
610
|
+
* on \`PYLON_API_URL\` (default http://localhost:4321). Without this,
|
|
611
|
+
* Next.js sees \`/api/fn/addTodo\` as a missing route and 404s before
|
|
612
|
+
* the request ever reaches Pylon.
|
|
613
|
+
*
|
|
614
|
+
* In production set \`PYLON_API_URL\` to wherever you've deployed the
|
|
615
|
+
* Pylon binary (Fly, Render, Railway, your own box). The browser
|
|
616
|
+
* still hits same-origin paths under your Next deployment, and Next
|
|
617
|
+
* forwards them server-side — no CORS, no extra DNS.
|
|
577
618
|
*/
|
|
619
|
+
const PYLON_API_URL = process.env.PYLON_API_URL ?? "http://localhost:4321";
|
|
620
|
+
|
|
578
621
|
const config: NextConfig = {
|
|
579
622
|
\ttranspilePackages: [
|
|
580
623
|
\t\t"@${projectName}/ui",
|
|
@@ -584,6 +627,14 @@ const config: NextConfig = {
|
|
|
584
627
|
\t\t"@pylonsync/functions",
|
|
585
628
|
\t\t"@pylonsync/sync",
|
|
586
629
|
\t],
|
|
630
|
+
\tasync rewrites() {
|
|
631
|
+
\t\treturn [
|
|
632
|
+
\t\t\t{ source: "/api/fn/:path*", destination: \`\${PYLON_API_URL}/api/fn/:path*\` },
|
|
633
|
+
\t\t\t{ source: "/api/auth/:path*", destination: \`\${PYLON_API_URL}/api/auth/:path*\` },
|
|
634
|
+
\t\t\t{ source: "/api/sync/:path*", destination: \`\${PYLON_API_URL}/api/sync/:path*\` },
|
|
635
|
+
\t\t\t{ source: "/api/:path*", destination: \`\${PYLON_API_URL}/api/:path*\` },
|
|
636
|
+
\t\t];
|
|
637
|
+
\t},
|
|
587
638
|
};
|
|
588
639
|
|
|
589
640
|
export default config;
|
|
@@ -816,7 +867,50 @@ function detectPackageManager() {
|
|
|
816
867
|
if (ua.startsWith("bun")) return "bun";
|
|
817
868
|
if (ua.startsWith("pnpm")) return "pnpm";
|
|
818
869
|
if (ua.startsWith("yarn")) return "yarn";
|
|
819
|
-
return "npm";
|
|
870
|
+
if (ua.startsWith("npm")) return "npm";
|
|
871
|
+
return null;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
/**
|
|
875
|
+
* Per-package-manager workspace script syntax. Each PM exposes
|
|
876
|
+
* "run X in workspace Y" differently:
|
|
877
|
+
* bun bun run --filter ./apps/api dev
|
|
878
|
+
* pnpm pnpm --filter ./apps/api run dev
|
|
879
|
+
* yarn yarn workspace @<name>/api run dev
|
|
880
|
+
* npm npm --workspace apps/api run dev
|
|
881
|
+
*
|
|
882
|
+
* The scaffold doesn't try to abstract the PM — it bakes the right
|
|
883
|
+
* syntax into the generated scripts so `<pm> run dev` works
|
|
884
|
+
* everywhere with no further config.
|
|
885
|
+
*/
|
|
886
|
+
function pmScripts(pm) {
|
|
887
|
+
switch (pm) {
|
|
888
|
+
case "bun":
|
|
889
|
+
return {
|
|
890
|
+
devApi: "bun run --filter './apps/api' dev",
|
|
891
|
+
devWeb: "bun run --filter './apps/web' dev",
|
|
892
|
+
build: "bun run --filter '*' build",
|
|
893
|
+
};
|
|
894
|
+
case "pnpm":
|
|
895
|
+
return {
|
|
896
|
+
devApi: "pnpm --filter './apps/api' run dev",
|
|
897
|
+
devWeb: "pnpm --filter './apps/web' run dev",
|
|
898
|
+
build: "pnpm --filter '*' run build",
|
|
899
|
+
};
|
|
900
|
+
case "yarn":
|
|
901
|
+
return {
|
|
902
|
+
devApi: `yarn workspace @${projectName}/api run dev`,
|
|
903
|
+
devWeb: `yarn workspace @${projectName}/web run dev`,
|
|
904
|
+
build: "yarn workspaces foreach -A run build",
|
|
905
|
+
};
|
|
906
|
+
case "npm":
|
|
907
|
+
default:
|
|
908
|
+
return {
|
|
909
|
+
devApi: "npm --workspace apps/api run dev",
|
|
910
|
+
devWeb: "npm --workspace apps/web run dev",
|
|
911
|
+
build: "npm --workspaces run build --if-present",
|
|
912
|
+
};
|
|
913
|
+
}
|
|
820
914
|
}
|
|
821
915
|
|
|
822
916
|
// ---------------------------------------------------------------------------
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pylonsync/create-pylon",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.20",
|
|
4
4
|
"description": "Scaffold a new Pylon app — realtime backend + Next.js frontend in one command. Run via `npm create @pylonsync/pylon@latest`.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|