create-spacefn 0.1.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/bin/create-space-app.js +4 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +129 -0
- package/dist/templates/minimal/configs/oxfmt.ts +8 -0
- package/dist/templates/minimal/configs/oxlint.ts +8 -0
- package/dist/templates/minimal/package.json +18 -0
- package/dist/templates/minimal/src/main.ts +6 -0
- package/dist/templates/minimal/src/pages/index.page.ts +9 -0
- package/dist/templates/minimal/src/pages/index.server.ts +5 -0
- package/dist/templates/minimal/src/pages/index.test.ts +22 -0
- package/dist/templates/minimal/src/routes/index.ts +14 -0
- package/dist/templates/minimal/tsconfig.json +14 -0
- package/dist/templates/minimal/vite.config.ts +9 -0
- package/dist/templates/minimal/vitest.config.ts +7 -0
- package/dist/templates/minimal/wrangler.toml +1 -0
- package/package.json +23 -0
- package/src/index.ts +169 -0
- package/src/templates/minimal/configs/oxfmt.ts +8 -0
- package/src/templates/minimal/configs/oxlint.ts +8 -0
- package/src/templates/minimal/package.json +18 -0
- package/src/templates/minimal/src/main.ts +6 -0
- package/src/templates/minimal/src/pages/index.page.ts +9 -0
- package/src/templates/minimal/src/pages/index.server.ts +5 -0
- package/src/templates/minimal/src/pages/index.test.ts +22 -0
- package/src/templates/minimal/src/routes/index.ts +14 -0
- package/src/templates/minimal/tsconfig.json +14 -0
- package/src/templates/minimal/vite.config.ts +9 -0
- package/src/templates/minimal/vitest.config.ts +7 -0
- package/src/templates/minimal/wrangler.toml +1 -0
- package/tsconfig.json +15 -0
- package/tsup.config.ts +8 -0
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { execSync } from "child_process";
|
|
3
|
+
import { existsSync } from "fs";
|
|
4
|
+
import { mkdir, writeFile, cp, readFile } from "fs/promises";
|
|
5
|
+
import * as p from "@clack/prompts";
|
|
6
|
+
import { defineCommand, runMain } from "citty";
|
|
7
|
+
import { resolve, join } from "pathe";
|
|
8
|
+
import pc from "picocolors";
|
|
9
|
+
var TEMPLATES = ["minimal"];
|
|
10
|
+
var TEMPLATE_DIR = join(import.meta.dirname, "templates");
|
|
11
|
+
var PKG_MANAGERS = [
|
|
12
|
+
{ value: "pnpm", label: "pnpm", install: "pnpm add", addDev: "pnpm add -D" },
|
|
13
|
+
{ value: "npm", label: "npm", install: "npm i", addDev: "npm i -D" },
|
|
14
|
+
{ value: "yarn", label: "yarn", install: "yarn add", addDev: "yarn add -D" },
|
|
15
|
+
{ value: "bun", label: "bun", install: "bun add", addDev: "bun add -d" }
|
|
16
|
+
];
|
|
17
|
+
async function writeTemplate(targetDir, template, projectName) {
|
|
18
|
+
const srcDir = join(TEMPLATE_DIR, template);
|
|
19
|
+
await cp(srcDir, targetDir, { recursive: true });
|
|
20
|
+
const files = ["package.json", "wrangler.toml"];
|
|
21
|
+
for (const file of files) {
|
|
22
|
+
const filePath = join(targetDir, file);
|
|
23
|
+
if (existsSync(filePath)) {
|
|
24
|
+
const content = await readFile(filePath, "utf-8");
|
|
25
|
+
await writeFile(filePath, content.replaceAll("{{app_name}}", projectName));
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function install(targetDir, pm, deps, devDeps) {
|
|
30
|
+
const mgr = PKG_MANAGERS.find((m) => m.value === pm);
|
|
31
|
+
if (deps.length > 0) {
|
|
32
|
+
execSync(`${mgr.install} ${deps.join(" ")}`, { cwd: targetDir, stdio: "inherit" });
|
|
33
|
+
}
|
|
34
|
+
if (devDeps.length > 0) {
|
|
35
|
+
execSync(`${mgr.addDev} ${devDeps.join(" ")}`, { cwd: targetDir, stdio: "inherit" });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
var main = defineCommand({
|
|
39
|
+
meta: {
|
|
40
|
+
name: "create-spacefn",
|
|
41
|
+
description: "Scaffold a new Space project",
|
|
42
|
+
version: "0.1.0"
|
|
43
|
+
},
|
|
44
|
+
args: {
|
|
45
|
+
name: {
|
|
46
|
+
type: "positional",
|
|
47
|
+
description: "Project name",
|
|
48
|
+
required: false
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
async run({ args }) {
|
|
52
|
+
p.intro(pc.bold(pc.cyan("Create Space App")));
|
|
53
|
+
let projectName = args.name;
|
|
54
|
+
if (!projectName) {
|
|
55
|
+
const name = await p.text({
|
|
56
|
+
message: "Project name?",
|
|
57
|
+
placeholder: "my-space-app",
|
|
58
|
+
validate(value) {
|
|
59
|
+
if (!value) return "Project name is required";
|
|
60
|
+
if (!/^[a-z0-9-_]+$/.test(value))
|
|
61
|
+
return "Use lowercase, numbers, hyphens, or underscores";
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
if (p.isCancel(name)) {
|
|
65
|
+
p.cancel("Cancelled");
|
|
66
|
+
process.exit(0);
|
|
67
|
+
}
|
|
68
|
+
projectName = name || "my-space-app";
|
|
69
|
+
}
|
|
70
|
+
const pm = await p.select({
|
|
71
|
+
message: "Package manager?",
|
|
72
|
+
options: PKG_MANAGERS.map((m) => ({
|
|
73
|
+
value: m.value,
|
|
74
|
+
label: m.label
|
|
75
|
+
})),
|
|
76
|
+
initialValue: "npm"
|
|
77
|
+
});
|
|
78
|
+
if (p.isCancel(pm)) {
|
|
79
|
+
p.cancel("Cancelled");
|
|
80
|
+
process.exit(0);
|
|
81
|
+
}
|
|
82
|
+
const template = await p.select({
|
|
83
|
+
message: "Template?",
|
|
84
|
+
options: TEMPLATES.map((t) => ({
|
|
85
|
+
value: t,
|
|
86
|
+
label: t,
|
|
87
|
+
hint: t === "minimal" ? "Basic routing and HTML" : void 0
|
|
88
|
+
})),
|
|
89
|
+
initialValue: "minimal"
|
|
90
|
+
});
|
|
91
|
+
if (p.isCancel(template)) {
|
|
92
|
+
p.cancel("Cancelled");
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
const targetDir = resolve(process.cwd(), projectName);
|
|
96
|
+
if (existsSync(targetDir)) {
|
|
97
|
+
p.cancel(`Directory ${projectName} already exists`);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
const s = p.spinner();
|
|
101
|
+
s.start("Creating project...");
|
|
102
|
+
await mkdir(targetDir, { recursive: true });
|
|
103
|
+
await writeTemplate(targetDir, template, projectName);
|
|
104
|
+
s.stop("Project created");
|
|
105
|
+
const installDeps = await p.confirm({
|
|
106
|
+
message: "Install dependencies?",
|
|
107
|
+
initialValue: true
|
|
108
|
+
});
|
|
109
|
+
if (p.isCancel(installDeps)) {
|
|
110
|
+
p.cancel("Cancelled");
|
|
111
|
+
process.exit(0);
|
|
112
|
+
}
|
|
113
|
+
if (installDeps) {
|
|
114
|
+
const s2 = p.spinner();
|
|
115
|
+
s2.start("Installing @space packages...");
|
|
116
|
+
install(
|
|
117
|
+
targetDir,
|
|
118
|
+
pm,
|
|
119
|
+
["@spacefn/html", "@spacefn/server", "@spacefn/datastar"],
|
|
120
|
+
["wrangler", "oxlint", "oxfmt", "vite", "vitest"]
|
|
121
|
+
);
|
|
122
|
+
s2.stop("Dependencies installed");
|
|
123
|
+
}
|
|
124
|
+
p.outro(pc.green("Done!"));
|
|
125
|
+
p.note(`cd ${projectName}
|
|
126
|
+
${pm} dev`, "Next steps");
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
runMain(main);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{app_name}}",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "spacefn dev",
|
|
7
|
+
"build": "spacefn build",
|
|
8
|
+
"test": "vitest run",
|
|
9
|
+
"fmt": "oxfmt -c configs/oxfmt.ts",
|
|
10
|
+
"fmt:check": "oxfmt -c configs/oxfmt.ts --check",
|
|
11
|
+
"lint": "oxlint -c configs/oxlint.ts",
|
|
12
|
+
"lint:fix": "oxlint -c configs/oxlint.ts --fix"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@spacefn/server": "latest",
|
|
16
|
+
"vitest": "^3.0.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createTestHandler } from "@spacefn/server/test";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
|
|
4
|
+
import Page from "./index.page";
|
|
5
|
+
import { loader } from "./index.server";
|
|
6
|
+
|
|
7
|
+
const handler = createTestHandler({ loader, page: Page });
|
|
8
|
+
|
|
9
|
+
describe("Home page", () => {
|
|
10
|
+
it("renders with loader data", async () => {
|
|
11
|
+
const res = await handler(new Request("http://localhost/"));
|
|
12
|
+
const html = await res.text();
|
|
13
|
+
|
|
14
|
+
expect(res.status).toBe(200);
|
|
15
|
+
expect(html).toContain("Hello World!");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("returns HTML content type", async () => {
|
|
19
|
+
const res = await handler(new Request("http://localhost/"));
|
|
20
|
+
expect(res.headers.get("Content-Type")).toBe("text/html");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { h, render } from "@spacefn/html";
|
|
2
|
+
|
|
3
|
+
export default function () {
|
|
4
|
+
return new Response(
|
|
5
|
+
render(
|
|
6
|
+
h.html(
|
|
7
|
+
{},
|
|
8
|
+
h.head({}, h.title({}, "Home")),
|
|
9
|
+
h.body({}, h.main({}, h.h1({}, "Hello from Space"), h.p({}, "Your app is running."))),
|
|
10
|
+
),
|
|
11
|
+
),
|
|
12
|
+
{ headers: { "Content-Type": "text/html" } },
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
name = "{{app_name}}"
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-spacefn",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"bin": {
|
|
5
|
+
"create-spacefn": "./bin/create-space-app.js"
|
|
6
|
+
},
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"build": "rm -rf dist && tsup && cp -r src/templates dist/templates",
|
|
10
|
+
"typecheck": "tsc --noEmit"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@clack/prompts": "^0.9.0",
|
|
14
|
+
"citty": "^0.1.0",
|
|
15
|
+
"pathe": "^2.0.0",
|
|
16
|
+
"picocolors": "^1.1.0"
|
|
17
|
+
},
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^22.0.0",
|
|
20
|
+
"tsup": "^8.0.0",
|
|
21
|
+
"typescript": "^5.5.0"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
// --- Create Space App ---------------------------------------------------------
|
|
4
|
+
// Scaffold a new Space project
|
|
5
|
+
import { mkdir, writeFile, cp, readFile } from "node:fs/promises";
|
|
6
|
+
|
|
7
|
+
import * as p from "@clack/prompts";
|
|
8
|
+
import { defineCommand, runMain } from "citty";
|
|
9
|
+
import { resolve, join } from "pathe";
|
|
10
|
+
import pc from "picocolors";
|
|
11
|
+
|
|
12
|
+
// --- Templates ----------------------------------------------------------------
|
|
13
|
+
|
|
14
|
+
const TEMPLATES = ["minimal"] as const;
|
|
15
|
+
type Template = (typeof TEMPLATES)[number];
|
|
16
|
+
|
|
17
|
+
const TEMPLATE_DIR = join(import.meta.dirname, "templates");
|
|
18
|
+
|
|
19
|
+
// --- Package Manager -----------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
type PackageManager = "pnpm" | "npm" | "yarn" | "bun";
|
|
22
|
+
|
|
23
|
+
const PKG_MANAGERS: { value: PackageManager; label: string; install: string; addDev: string }[] = [
|
|
24
|
+
{ value: "pnpm", label: "pnpm", install: "pnpm add", addDev: "pnpm add -D" },
|
|
25
|
+
{ value: "npm", label: "npm", install: "npm i", addDev: "npm i -D" },
|
|
26
|
+
{ value: "yarn", label: "yarn", install: "yarn add", addDev: "yarn add -D" },
|
|
27
|
+
{ value: "bun", label: "bun", install: "bun add", addDev: "bun add -d" },
|
|
28
|
+
];
|
|
29
|
+
|
|
30
|
+
// --- Helpers ------------------------------------------------------------------
|
|
31
|
+
|
|
32
|
+
async function writeTemplate(
|
|
33
|
+
targetDir: string,
|
|
34
|
+
template: Template,
|
|
35
|
+
projectName: string,
|
|
36
|
+
): Promise<void> {
|
|
37
|
+
const srcDir = join(TEMPLATE_DIR, template);
|
|
38
|
+
await cp(srcDir, targetDir, { recursive: true });
|
|
39
|
+
|
|
40
|
+
// Replace {{app_name}} placeholder in template files
|
|
41
|
+
const files = ["package.json", "wrangler.toml"];
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
const filePath = join(targetDir, file);
|
|
44
|
+
if (existsSync(filePath)) {
|
|
45
|
+
const content = await readFile(filePath, "utf-8");
|
|
46
|
+
await writeFile(filePath, content.replaceAll("{{app_name}}", projectName));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function install(targetDir: string, pm: PackageManager, deps: string[], devDeps: string[]): void {
|
|
52
|
+
const mgr = PKG_MANAGERS.find((m) => m.value === pm)!;
|
|
53
|
+
if (deps.length > 0) {
|
|
54
|
+
execSync(`${mgr.install} ${deps.join(" ")}`, { cwd: targetDir, stdio: "inherit" });
|
|
55
|
+
}
|
|
56
|
+
if (devDeps.length > 0) {
|
|
57
|
+
execSync(`${mgr.addDev} ${devDeps.join(" ")}`, { cwd: targetDir, stdio: "inherit" });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// --- CLI ----------------------------------------------------------------------
|
|
62
|
+
|
|
63
|
+
const main = defineCommand({
|
|
64
|
+
meta: {
|
|
65
|
+
name: "create-spacefn",
|
|
66
|
+
description: "Scaffold a new Space project",
|
|
67
|
+
version: "0.1.0",
|
|
68
|
+
},
|
|
69
|
+
args: {
|
|
70
|
+
name: {
|
|
71
|
+
type: "positional",
|
|
72
|
+
description: "Project name",
|
|
73
|
+
required: false,
|
|
74
|
+
},
|
|
75
|
+
},
|
|
76
|
+
async run({ args }) {
|
|
77
|
+
p.intro(pc.bold(pc.cyan("Create Space App")));
|
|
78
|
+
|
|
79
|
+
// Project name
|
|
80
|
+
let projectName = args.name as string;
|
|
81
|
+
if (!projectName) {
|
|
82
|
+
const name = await p.text({
|
|
83
|
+
message: "Project name?",
|
|
84
|
+
placeholder: "my-space-app",
|
|
85
|
+
validate(value) {
|
|
86
|
+
if (!value) return "Project name is required";
|
|
87
|
+
if (!/^[a-z0-9-_]+$/.test(value))
|
|
88
|
+
return "Use lowercase, numbers, hyphens, or underscores";
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
if (p.isCancel(name)) {
|
|
92
|
+
p.cancel("Cancelled");
|
|
93
|
+
process.exit(0);
|
|
94
|
+
}
|
|
95
|
+
projectName = name || "my-space-app";
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Package manager
|
|
99
|
+
const pm = await p.select({
|
|
100
|
+
message: "Package manager?",
|
|
101
|
+
options: PKG_MANAGERS.map((m) => ({
|
|
102
|
+
value: m.value,
|
|
103
|
+
label: m.label,
|
|
104
|
+
})),
|
|
105
|
+
initialValue: "npm",
|
|
106
|
+
});
|
|
107
|
+
if (p.isCancel(pm)) {
|
|
108
|
+
p.cancel("Cancelled");
|
|
109
|
+
process.exit(0);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Template
|
|
113
|
+
const template = await p.select({
|
|
114
|
+
message: "Template?",
|
|
115
|
+
options: TEMPLATES.map((t) => ({
|
|
116
|
+
value: t,
|
|
117
|
+
label: t,
|
|
118
|
+
hint: t === "minimal" ? "Basic routing and HTML" : undefined,
|
|
119
|
+
})),
|
|
120
|
+
initialValue: "minimal",
|
|
121
|
+
});
|
|
122
|
+
if (p.isCancel(template)) {
|
|
123
|
+
p.cancel("Cancelled");
|
|
124
|
+
process.exit(0);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Target directory
|
|
128
|
+
const targetDir = resolve(process.cwd(), projectName);
|
|
129
|
+
if (existsSync(targetDir)) {
|
|
130
|
+
p.cancel(`Directory ${projectName} already exists`);
|
|
131
|
+
process.exit(1);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Create project
|
|
135
|
+
const s = p.spinner();
|
|
136
|
+
s.start("Creating project...");
|
|
137
|
+
await mkdir(targetDir, { recursive: true });
|
|
138
|
+
await writeTemplate(targetDir, template as Template, projectName);
|
|
139
|
+
s.stop("Project created");
|
|
140
|
+
|
|
141
|
+
// Install dependencies
|
|
142
|
+
const installDeps = await p.confirm({
|
|
143
|
+
message: "Install dependencies?",
|
|
144
|
+
initialValue: true,
|
|
145
|
+
});
|
|
146
|
+
if (p.isCancel(installDeps)) {
|
|
147
|
+
p.cancel("Cancelled");
|
|
148
|
+
process.exit(0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (installDeps) {
|
|
152
|
+
const s2 = p.spinner();
|
|
153
|
+
s2.start("Installing @space packages...");
|
|
154
|
+
install(
|
|
155
|
+
targetDir,
|
|
156
|
+
pm as PackageManager,
|
|
157
|
+
["@spacefn/html", "@spacefn/server", "@spacefn/datastar"],
|
|
158
|
+
["wrangler", "oxlint", "oxfmt", "vite", "vitest"],
|
|
159
|
+
);
|
|
160
|
+
s2.stop("Dependencies installed");
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Done
|
|
164
|
+
p.outro(pc.green("Done!"));
|
|
165
|
+
p.note(`cd ${projectName}\n${pm} dev`, "Next steps");
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
runMain(main);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{app_name}}",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"dev": "spacefn dev",
|
|
7
|
+
"build": "spacefn build",
|
|
8
|
+
"test": "vitest run",
|
|
9
|
+
"fmt": "oxfmt -c configs/oxfmt.ts",
|
|
10
|
+
"fmt:check": "oxfmt -c configs/oxfmt.ts --check",
|
|
11
|
+
"lint": "oxlint -c configs/oxlint.ts",
|
|
12
|
+
"lint:fix": "oxlint -c configs/oxlint.ts --fix"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@spacefn/server": "latest",
|
|
16
|
+
"vitest": "^3.0.0"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createTestHandler } from "@spacefn/server/test";
|
|
2
|
+
import { describe, it, expect } from "vitest";
|
|
3
|
+
|
|
4
|
+
import Page from "./index.page";
|
|
5
|
+
import { loader } from "./index.server";
|
|
6
|
+
|
|
7
|
+
const handler = createTestHandler({ loader, page: Page });
|
|
8
|
+
|
|
9
|
+
describe("Home page", () => {
|
|
10
|
+
it("renders with loader data", async () => {
|
|
11
|
+
const res = await handler(new Request("http://localhost/"));
|
|
12
|
+
const html = await res.text();
|
|
13
|
+
|
|
14
|
+
expect(res.status).toBe(200);
|
|
15
|
+
expect(html).toContain("Hello World!");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("returns HTML content type", async () => {
|
|
19
|
+
const res = await handler(new Request("http://localhost/"));
|
|
20
|
+
expect(res.headers.get("Content-Type")).toBe("text/html");
|
|
21
|
+
});
|
|
22
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { h, render } from "@spacefn/html";
|
|
2
|
+
|
|
3
|
+
export default function () {
|
|
4
|
+
return new Response(
|
|
5
|
+
render(
|
|
6
|
+
h.html(
|
|
7
|
+
{},
|
|
8
|
+
h.head({}, h.title({}, "Home")),
|
|
9
|
+
h.body({}, h.main({}, h.h1({}, "Hello from Space"), h.p({}, "Your app is running."))),
|
|
10
|
+
),
|
|
11
|
+
),
|
|
12
|
+
{ headers: { "Content-Type": "text/html" } },
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
name = "{{app_name}}"
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"strict": true,
|
|
7
|
+
"esModuleInterop": true,
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
"declaration": true,
|
|
10
|
+
"outDir": "./dist",
|
|
11
|
+
"types": ["node"]
|
|
12
|
+
},
|
|
13
|
+
"include": ["src"],
|
|
14
|
+
"exclude": ["src/templates"]
|
|
15
|
+
}
|