bosia 0.2.2 → 0.3.0
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/README.md +39 -39
- package/package.json +56 -53
- package/src/ambient.d.ts +31 -0
- package/src/cli/add.ts +120 -114
- package/src/cli/build.ts +10 -10
- package/src/cli/create.ts +142 -137
- package/src/cli/dev.ts +8 -8
- package/src/cli/feat.ts +291 -132
- package/src/cli/index.ts +51 -42
- package/src/cli/registry.ts +136 -115
- package/src/cli/start.ts +17 -17
- package/src/cli/test.ts +25 -0
- package/src/core/build.ts +72 -56
- package/src/core/client/App.svelte +177 -153
- package/src/core/client/appState.svelte.ts +57 -0
- package/src/core/client/enhance.ts +112 -0
- package/src/core/client/hydrate.ts +97 -65
- package/src/core/client/prefetch.ts +101 -94
- package/src/core/client/router.svelte.ts +64 -51
- package/src/core/cookies.ts +70 -66
- package/src/core/cors.ts +44 -35
- package/src/core/csrf.ts +38 -38
- package/src/core/dedup.ts +17 -17
- package/src/core/dev.ts +165 -168
- package/src/core/env.ts +155 -128
- package/src/core/envCodegen.ts +73 -73
- package/src/core/errors.ts +48 -49
- package/src/core/hooks.ts +50 -50
- package/src/core/html.ts +192 -139
- package/src/core/matcher.ts +130 -121
- package/src/core/paths.ts +8 -10
- package/src/core/plugin.ts +113 -107
- package/src/core/prerender.ts +191 -118
- package/src/core/renderer.ts +359 -265
- package/src/core/routeFile.ts +140 -127
- package/src/core/routeTypes.ts +144 -83
- package/src/core/scanner.ts +125 -95
- package/src/core/server.ts +543 -370
- package/src/core/types.ts +25 -20
- package/src/lib/client.ts +12 -0
- package/src/lib/index.ts +8 -8
- package/src/lib/utils.ts +44 -30
- package/templates/default/.prettierignore +5 -0
- package/templates/default/.prettierrc.json +9 -0
- package/templates/default/README.md +5 -5
- package/templates/default/package.json +22 -18
- package/templates/default/src/app.css +80 -80
- package/templates/default/src/app.d.ts +3 -3
- package/templates/default/src/routes/+error.svelte +7 -10
- package/templates/default/src/routes/+layout.svelte +2 -2
- package/templates/default/src/routes/+page.svelte +31 -29
- package/templates/default/src/routes/about/+page.svelte +3 -3
- package/templates/default/tsconfig.json +20 -20
- package/templates/demo/.prettierignore +5 -0
- package/templates/demo/.prettierrc.json +9 -0
- package/templates/demo/README.md +9 -9
- package/templates/demo/package.json +22 -17
- package/templates/demo/src/app.css +80 -80
- package/templates/demo/src/app.d.ts +3 -3
- package/templates/demo/src/hooks.server.ts +9 -9
- package/templates/demo/src/routes/(public)/+layout.svelte +45 -23
- package/templates/demo/src/routes/(public)/+page.svelte +96 -67
- package/templates/demo/src/routes/(public)/about/+page.svelte +13 -25
- package/templates/demo/src/routes/(public)/all/[...catchall]/+page.svelte +24 -28
- package/templates/demo/src/routes/(public)/blog/+page.svelte +55 -46
- package/templates/demo/src/routes/(public)/blog/[slug]/+page.server.ts +36 -38
- package/templates/demo/src/routes/(public)/blog/[slug]/+page.svelte +60 -42
- package/templates/demo/src/routes/+error.svelte +10 -7
- package/templates/demo/src/routes/+layout.server.ts +4 -4
- package/templates/demo/src/routes/+layout.svelte +2 -2
- package/templates/demo/src/routes/actions-test/+page.server.ts +16 -16
- package/templates/demo/src/routes/actions-test/+page.svelte +49 -49
- package/templates/demo/src/routes/api/hello/+server.ts +25 -25
- package/templates/demo/tsconfig.json +20 -20
- package/templates/todo/.prettierignore +5 -0
- package/templates/todo/.prettierrc.json +9 -0
- package/templates/todo/README.md +9 -9
- package/templates/todo/package.json +22 -17
- package/templates/todo/src/app.css +80 -80
- package/templates/todo/src/app.d.ts +7 -7
- package/templates/todo/src/hooks.server.ts +9 -9
- package/templates/todo/src/routes/+error.svelte +10 -7
- package/templates/todo/src/routes/+layout.server.ts +4 -4
- package/templates/todo/src/routes/+layout.svelte +2 -2
- package/templates/todo/src/routes/+page.svelte +44 -44
- package/templates/todo/template.json +1 -1
- package/templates/todo/tsconfig.json +20 -20
package/src/cli/create.ts
CHANGED
|
@@ -12,157 +12,162 @@ const BOSIA_PKG = JSON.parse(readFileSync(resolve(import.meta.dir, "../../packag
|
|
|
12
12
|
const BOSIA_VERSION: string = BOSIA_PKG.version;
|
|
13
13
|
|
|
14
14
|
const TEMPLATE_DESCRIPTIONS: Record<string, string> = {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
default: "Minimal starter with routing and Tailwind",
|
|
16
|
+
demo: "Full-featured demo with hooks, API routes, form actions, and more",
|
|
17
|
+
todo: "Todo app with PostgreSQL + Drizzle ORM",
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export async function runCreate(name: string | undefined, args: string[] = []) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
21
|
+
if (!name) {
|
|
22
|
+
console.error("❌ Please provide a project name.\n Usage: bosia create my-app");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const targetDir = resolve(process.cwd(), name);
|
|
27
|
+
|
|
28
|
+
if (existsSync(targetDir)) {
|
|
29
|
+
console.error(`❌ Directory already exists: ${targetDir}`);
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Parse --template flag
|
|
34
|
+
let template: string | undefined;
|
|
35
|
+
const templateIdx = args.indexOf("--template");
|
|
36
|
+
if (templateIdx !== -1 && args[templateIdx + 1]) {
|
|
37
|
+
template = args[templateIdx + 1];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Parse --local flag
|
|
41
|
+
const isLocal = args.includes("--local");
|
|
42
|
+
|
|
43
|
+
// If no --template flag, prompt interactively
|
|
44
|
+
if (!template) {
|
|
45
|
+
template = await promptTemplate();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Validate template exists
|
|
49
|
+
const templateDir = resolve(TEMPLATES_DIR, template);
|
|
50
|
+
if (!existsSync(templateDir)) {
|
|
51
|
+
const available = getAvailableTemplates().join(", ");
|
|
52
|
+
console.error(`❌ Unknown template: "${template}"\n Available: ${available}`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log(`\n⬡ Creating Bosia project: ${basename(targetDir)} (template: ${template})\n`);
|
|
57
|
+
|
|
58
|
+
copyDir(templateDir, targetDir, name, isLocal);
|
|
59
|
+
|
|
60
|
+
if (existsSync(join(targetDir, ".env.example"))) {
|
|
61
|
+
writeFileSync(
|
|
62
|
+
join(targetDir, ".env"),
|
|
63
|
+
readFileSync(join(targetDir, ".env.example"), "utf-8"),
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Install template features from registry
|
|
68
|
+
const templateConfigPath = join(templateDir, "template.json");
|
|
69
|
+
if (existsSync(templateConfigPath)) {
|
|
70
|
+
const config = JSON.parse(readFileSync(templateConfigPath, "utf-8"));
|
|
71
|
+
if (config.features?.length) {
|
|
72
|
+
let localRegistry: string | null = null;
|
|
73
|
+
try {
|
|
74
|
+
localRegistry = resolveLocalRegistry();
|
|
75
|
+
} catch {
|
|
76
|
+
// Local registry not found — will use remote
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
await initAddRegistry(localRegistry);
|
|
80
|
+
initFeatRegistry(localRegistry);
|
|
81
|
+
|
|
82
|
+
for (const feat of config.features) {
|
|
83
|
+
await installFeature(feat, true, {
|
|
84
|
+
skipInstall: true,
|
|
85
|
+
skipPrompts: true,
|
|
86
|
+
cwd: targetDir,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
console.log(`\n✅ Project created at ${targetDir}\n`);
|
|
93
|
+
|
|
94
|
+
console.log("Installing dependencies...");
|
|
95
|
+
const proc = spawn(["bun", "install"], {
|
|
96
|
+
stdout: "inherit",
|
|
97
|
+
stderr: "inherit",
|
|
98
|
+
cwd: targetDir,
|
|
99
|
+
});
|
|
100
|
+
const exitCode = await proc.exited;
|
|
101
|
+
if (exitCode !== 0) {
|
|
102
|
+
console.warn("⚠️ bun install failed — run it manually.");
|
|
103
|
+
} else {
|
|
104
|
+
console.log(`\n🎉 Ready!\n\ncd ${name}`);
|
|
105
|
+
|
|
106
|
+
const instPath = join(templateDir, "instructions.txt");
|
|
107
|
+
if (existsSync(instPath)) {
|
|
108
|
+
const instructions = readFileSync(instPath, "utf-8").trimEnd();
|
|
109
|
+
if (instructions) console.log(instructions);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
console.log(`bun x bosia dev\n`);
|
|
113
|
+
}
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
function getAvailableTemplates(): string[] {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
return readdirSync(TEMPLATES_DIR, { withFileTypes: true })
|
|
118
|
+
.filter((d) => d.isDirectory())
|
|
119
|
+
.map((d) => d.name)
|
|
120
|
+
.sort((a, b) => (a === "default" ? -1 : b === "default" ? 1 : a.localeCompare(b)));
|
|
118
121
|
}
|
|
119
122
|
|
|
120
123
|
async function promptTemplate(): Promise<string> {
|
|
121
|
-
|
|
124
|
+
const templates = getAvailableTemplates();
|
|
122
125
|
|
|
123
|
-
|
|
126
|
+
if (templates.length === 1) return templates[0];
|
|
124
127
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
128
|
+
const selected = await p.select({
|
|
129
|
+
message: "Which template?",
|
|
130
|
+
options: templates.map((t) => ({
|
|
131
|
+
value: t,
|
|
132
|
+
label: t,
|
|
133
|
+
hint: TEMPLATE_DESCRIPTIONS[t],
|
|
134
|
+
})),
|
|
135
|
+
});
|
|
133
136
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
137
|
+
if (p.isCancel(selected)) {
|
|
138
|
+
p.cancel("Operation cancelled.");
|
|
139
|
+
process.exit(0);
|
|
140
|
+
}
|
|
138
141
|
|
|
139
|
-
|
|
142
|
+
return selected as string;
|
|
140
143
|
}
|
|
141
144
|
|
|
142
145
|
function copyDir(src: string, dest: string, projectName: string, isLocal: boolean) {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
146
|
+
mkdirSync(dest, { recursive: true });
|
|
147
|
+
for (const entry of readdirSync(src, { withFileTypes: true })) {
|
|
148
|
+
const srcPath = join(src, entry.name);
|
|
149
|
+
const destPath = join(dest, entry.name);
|
|
150
|
+
|
|
151
|
+
// Do not copy instructions.txt or template.json to the final project
|
|
152
|
+
if (entry.name === "instructions.txt" || entry.name === "template.json") continue;
|
|
153
|
+
|
|
154
|
+
if (entry.isDirectory()) {
|
|
155
|
+
copyDir(srcPath, destPath, projectName, isLocal);
|
|
156
|
+
} else {
|
|
157
|
+
let content = readFileSync(srcPath, "utf-8").replaceAll(
|
|
158
|
+
"{{PROJECT_NAME}}",
|
|
159
|
+
projectName,
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
if (entry.name === "package.json" && isLocal) {
|
|
163
|
+
const bosiaPath = resolve(import.meta.dir, "../../");
|
|
164
|
+
const relPath = relative(dest, bosiaPath);
|
|
165
|
+
content = content.replaceAll('"^{{BOSIA_VERSION}}"', `"file:${relPath}"`);
|
|
166
|
+
} else {
|
|
167
|
+
content = content.replaceAll("{{BOSIA_VERSION}}", BOSIA_VERSION);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
writeFileSync(destPath, content, "utf-8");
|
|
171
|
+
}
|
|
172
|
+
}
|
|
168
173
|
}
|
package/src/cli/dev.ts
CHANGED
|
@@ -3,12 +3,12 @@ import { resolve } from "path";
|
|
|
3
3
|
import { loadEnv } from "../core/env.ts";
|
|
4
4
|
|
|
5
5
|
export async function runDev() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
6
|
+
loadEnv("development");
|
|
7
|
+
const devScript = resolve(import.meta.dir, "../core/dev.ts");
|
|
8
|
+
const proc = spawn(["bun", "run", devScript], {
|
|
9
|
+
stdout: "inherit",
|
|
10
|
+
stderr: "inherit",
|
|
11
|
+
cwd: process.cwd(),
|
|
12
|
+
});
|
|
13
|
+
await proc.exited;
|
|
14
14
|
}
|