create-theokit 0.1.0-alpha.3 → 0.1.0-alpha.6
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/dist/cli.js +314 -72
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
- package/templates/api-only/.nvmrc +1 -0
- package/templates/api-only/index.html +1 -1
- package/templates/api-only/package.json.tmpl +5 -2
- package/templates/api-only/public/favicon.ico +0 -0
- package/templates/dashboard/.nvmrc +1 -0
- package/templates/dashboard/index.html +1 -1
- package/templates/dashboard/package.json.tmpl +5 -2
- package/templates/dashboard/public/favicon.ico +0 -0
- package/templates/default/.nvmrc +1 -0
- package/templates/default/README.md.tmpl +73 -0
- package/templates/default/app/layout.tsx +84 -2
- package/templates/default/app/page.tsx +266 -87
- package/templates/default/index.html +1 -1
- package/templates/default/package.json.tmpl +14 -5
- package/templates/default/public/favicon.ico +0 -0
- package/templates/default/server/routes/chat.ts +53 -47
- package/templates/default/types/jobs.d.ts +25 -0
- package/templates/postgres/.nvmrc +1 -0
- package/templates/postgres/index.html +1 -1
- package/templates/postgres/package.json.tmpl +2 -1
- package/templates/postgres/public/favicon.ico +0 -0
- package/templates/saas/.env.example +7 -0
- package/templates/saas/.nvmrc +1 -0
- package/templates/saas/_gitignore +5 -0
- package/templates/saas/app/layout.tsx +5 -0
- package/templates/saas/app/page.tsx +104 -0
- package/templates/saas/db/index.ts +6 -0
- package/templates/saas/db/schema.ts +20 -0
- package/templates/saas/drizzle.config.ts +10 -0
- package/templates/saas/index.html +12 -0
- package/templates/saas/package.json.tmpl +32 -0
- package/templates/saas/public/.gitkeep +0 -0
- package/templates/saas/public/favicon.ico +0 -0
- package/templates/saas/server/context.ts +37 -0
- package/templates/saas/server/routes/agent.ts +21 -0
- package/templates/saas/server/routes/login.ts +25 -0
- package/templates/saas/server/routes/logout.ts +10 -0
- package/templates/saas/server/routes/me.ts +10 -0
- package/templates/saas/theo.config.ts +5 -0
- package/templates/saas/tsconfig.json +15 -0
- package/templates/services/agent-node/Dockerfile.tmpl +20 -0
- package/templates/services/agent-node/README.md +38 -0
- package/templates/services/agent-node/package.json.tmpl +18 -0
- package/templates/services/agent-node/src/index.ts +58 -0
- package/templates/services/agent-node/tsconfig.json +13 -0
- package/templates/services/agent-python/Dockerfile.tmpl +20 -0
- package/templates/services/agent-python/README.md +37 -0
- package/templates/services/agent-python/main.py +77 -0
- package/templates/services/agent-python/pyproject.toml.tmpl +16 -0
package/dist/cli.js
CHANGED
|
@@ -1,25 +1,227 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli.ts
|
|
4
|
-
import { resolve as
|
|
4
|
+
import { resolve as resolve3 } from "path";
|
|
5
5
|
|
|
6
|
-
// src/
|
|
6
|
+
// src/install.ts
|
|
7
|
+
import spawn from "cross-spawn";
|
|
8
|
+
function runInstall(cwd, pkgManager) {
|
|
9
|
+
const result = spawn.sync(pkgManager, ["install"], {
|
|
10
|
+
cwd,
|
|
11
|
+
stdio: "inherit",
|
|
12
|
+
env: { ...process.env, NODE_ENV: "development" }
|
|
13
|
+
});
|
|
14
|
+
if (result.status !== 0) {
|
|
15
|
+
throw new Error(`Failed to install dependencies with ${pkgManager}`);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/pkg-manager.ts
|
|
20
|
+
function detectPkgManager() {
|
|
21
|
+
const ua = process.env.npm_config_user_agent ?? "";
|
|
22
|
+
if (ua.startsWith("yarn")) return "yarn";
|
|
23
|
+
if (ua.startsWith("pnpm")) return "pnpm";
|
|
24
|
+
if (ua.startsWith("bun")) return "bun";
|
|
25
|
+
return "npm";
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/preflight-node.ts
|
|
29
|
+
var MIN_NODE_VERSION = "22.12.0";
|
|
30
|
+
function compareSemver(a, b) {
|
|
31
|
+
const parse = (raw) => {
|
|
32
|
+
const stripped = raw.replace(/^v/, "").split("-")[0] ?? "0.0.0";
|
|
33
|
+
const parts = stripped.split(".").map((s) => Number.parseInt(s, 10) || 0);
|
|
34
|
+
return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0];
|
|
35
|
+
};
|
|
36
|
+
const [aMaj, aMin, aPat] = parse(a);
|
|
37
|
+
const [bMaj, bMin, bPat] = parse(b);
|
|
38
|
+
if (aMaj !== bMaj) return aMaj - bMaj;
|
|
39
|
+
if (aMin !== bMin) return aMin - bMin;
|
|
40
|
+
return aPat - bPat;
|
|
41
|
+
}
|
|
42
|
+
function assertNodeVersion(currentRaw, minimum = MIN_NODE_VERSION) {
|
|
43
|
+
const current = currentRaw.replace(/^v/, "");
|
|
44
|
+
if (compareSemver(currentRaw, minimum) < 0) {
|
|
45
|
+
throw new Error(
|
|
46
|
+
`create-theokit requires Node ${minimum} or later (the @usetheo/sdk peer engines floor).
|
|
47
|
+
Detected: Node ${current}
|
|
48
|
+
Fix: nvm install 22 && nvm use 22
|
|
49
|
+
(or your version manager equivalent \u2014 fnm, volta, asdf, nvs)
|
|
50
|
+
`
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/scaffold-services.ts
|
|
7
56
|
import {
|
|
8
|
-
existsSync as existsSync2,
|
|
9
57
|
cpSync,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
renameSync,
|
|
13
|
-
unlinkSync as unlinkSync2,
|
|
58
|
+
existsSync,
|
|
59
|
+
readFileSync,
|
|
14
60
|
readdirSync,
|
|
15
|
-
|
|
61
|
+
statSync,
|
|
62
|
+
writeFileSync,
|
|
63
|
+
unlinkSync
|
|
16
64
|
} from "fs";
|
|
17
|
-
import {
|
|
65
|
+
import { dirname, join, resolve } from "path";
|
|
18
66
|
import { fileURLToPath } from "url";
|
|
67
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
68
|
+
var VALID_BACKENDS = ["python", "node"];
|
|
69
|
+
function parseBackendFlags(args) {
|
|
70
|
+
const out = [];
|
|
71
|
+
for (let i = 0; i < args.length; i++) {
|
|
72
|
+
const a = args[i] ?? "";
|
|
73
|
+
let value;
|
|
74
|
+
if (a === "--backend") {
|
|
75
|
+
value = args[i + 1];
|
|
76
|
+
i++;
|
|
77
|
+
} else if (a.startsWith("--backend=")) {
|
|
78
|
+
value = a.slice("--backend=".length);
|
|
79
|
+
}
|
|
80
|
+
if (value === void 0) continue;
|
|
81
|
+
if (!VALID_BACKENDS.includes(value)) {
|
|
82
|
+
throw new Error(
|
|
83
|
+
`unknown --backend value: '${value}'. Valid options: ${VALID_BACKENDS.join(", ")}.`
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
out.push(value);
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
var BACKEND_CONFIG = {
|
|
91
|
+
python: {
|
|
92
|
+
templateDir: "agent-python",
|
|
93
|
+
serviceName: "agent",
|
|
94
|
+
port: 8001,
|
|
95
|
+
proxy: "/api/agent",
|
|
96
|
+
dev: "uvicorn main:app --reload --port 8001",
|
|
97
|
+
start: "uvicorn main:app --port 8001 --workers 4"
|
|
98
|
+
},
|
|
99
|
+
node: {
|
|
100
|
+
templateDir: "agent-node",
|
|
101
|
+
serviceName: "worker",
|
|
102
|
+
port: 8002,
|
|
103
|
+
proxy: "/api/worker",
|
|
104
|
+
dev: "pnpm dev",
|
|
105
|
+
start: "pnpm start"
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
function getServiceTemplateDir(kind) {
|
|
109
|
+
return resolve(__dirname, "../templates/services", BACKEND_CONFIG[kind].templateDir);
|
|
110
|
+
}
|
|
111
|
+
function substituteTmpls(dir, projectName) {
|
|
112
|
+
for (const entry of readdirSync(dir)) {
|
|
113
|
+
const full = join(dir, entry);
|
|
114
|
+
const stat = statSync(full);
|
|
115
|
+
if (stat.isDirectory()) {
|
|
116
|
+
substituteTmpls(full, projectName);
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
if (entry.endsWith(".tmpl")) {
|
|
120
|
+
const content = readFileSync(full, "utf-8").replace(/\{\{name\}\}/g, projectName);
|
|
121
|
+
const dest = full.replace(/\.tmpl$/, "");
|
|
122
|
+
writeFileSync(dest, content);
|
|
123
|
+
unlinkSync(full);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function buildServicesSnippet(selections) {
|
|
128
|
+
if (selections.length === 0) return "";
|
|
129
|
+
const blocks = selections.map(({ name, entry }) => {
|
|
130
|
+
return ` ${name}: {
|
|
131
|
+
runtime: '${entry.runtime}',
|
|
132
|
+
port: ${String(entry.port)},
|
|
133
|
+
proxy: '${entry.proxy}',
|
|
134
|
+
dev: ${JSON.stringify(entry.dev)},
|
|
135
|
+
start: ${JSON.stringify(entry.start)},
|
|
136
|
+
},`;
|
|
137
|
+
});
|
|
138
|
+
return ` services: {
|
|
139
|
+
${blocks.join("\n")}
|
|
140
|
+
},
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
function injectServicesIntoConfig(configSource, snippet) {
|
|
144
|
+
if (snippet.length === 0) return configSource;
|
|
145
|
+
if (configSource.includes("services:")) return configSource;
|
|
146
|
+
const re = /defineConfig\(\{([\s\S]*?)\}\)/m;
|
|
147
|
+
const match = re.exec(configSource);
|
|
148
|
+
if (!match) return configSource;
|
|
149
|
+
const inner = match[1];
|
|
150
|
+
let trimEnd = inner.length;
|
|
151
|
+
while (trimEnd > 0 && /\s/.test(inner.charAt(trimEnd - 1))) {
|
|
152
|
+
trimEnd--;
|
|
153
|
+
}
|
|
154
|
+
const trimmed = inner.slice(0, trimEnd);
|
|
155
|
+
const sep = trimmed.length > 0 && !trimmed.endsWith(",") ? ",\n" : "\n";
|
|
156
|
+
const newInner = `${trimmed}${sep}${snippet}`;
|
|
157
|
+
return configSource.replace(re, `defineConfig({${newInner}})`);
|
|
158
|
+
}
|
|
159
|
+
function injectHeyApiDep(packageJsonSource) {
|
|
160
|
+
const pkg = JSON.parse(packageJsonSource);
|
|
161
|
+
pkg.dependencies = pkg.dependencies ?? {};
|
|
162
|
+
if (!("@hey-api/client-fetch" in pkg.dependencies)) {
|
|
163
|
+
pkg.dependencies["@hey-api/client-fetch"] = "^0.6.0";
|
|
164
|
+
}
|
|
165
|
+
return JSON.stringify(pkg, null, 2) + "\n";
|
|
166
|
+
}
|
|
167
|
+
function scaffoldServices(options) {
|
|
168
|
+
if (options.backends.length === 0) return;
|
|
169
|
+
const selections = [];
|
|
170
|
+
for (const kind of options.backends) {
|
|
171
|
+
const cfg = BACKEND_CONFIG[kind];
|
|
172
|
+
const src = getServiceTemplateDir(kind);
|
|
173
|
+
const dest = join(options.targetDir, "services", cfg.serviceName);
|
|
174
|
+
if (!existsSync(src)) {
|
|
175
|
+
throw new Error(`service template not found: ${src}`);
|
|
176
|
+
}
|
|
177
|
+
cpSync(src, dest, { recursive: true });
|
|
178
|
+
substituteTmpls(dest, options.projectName);
|
|
179
|
+
selections.push({
|
|
180
|
+
name: cfg.serviceName,
|
|
181
|
+
entry: {
|
|
182
|
+
runtime: kind,
|
|
183
|
+
port: cfg.port,
|
|
184
|
+
proxy: cfg.proxy,
|
|
185
|
+
dev: cfg.dev,
|
|
186
|
+
start: cfg.start
|
|
187
|
+
}
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
const configPath = join(options.targetDir, "theo.config.ts");
|
|
191
|
+
if (existsSync(configPath)) {
|
|
192
|
+
const cfgSrc = readFileSync(configPath, "utf-8");
|
|
193
|
+
const snippet = buildServicesSnippet(selections);
|
|
194
|
+
const updated = injectServicesIntoConfig(cfgSrc, snippet);
|
|
195
|
+
if (updated !== cfgSrc) {
|
|
196
|
+
writeFileSync(configPath, updated);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
const pkgPath = join(options.targetDir, "package.json");
|
|
200
|
+
if (existsSync(pkgPath)) {
|
|
201
|
+
const pkgSrc = readFileSync(pkgPath, "utf-8");
|
|
202
|
+
const updated = injectHeyApiDep(pkgSrc);
|
|
203
|
+
writeFileSync(pkgPath, updated);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/index.ts
|
|
208
|
+
import {
|
|
209
|
+
existsSync as existsSync3,
|
|
210
|
+
cpSync as cpSync2,
|
|
211
|
+
readFileSync as readFileSync3,
|
|
212
|
+
writeFileSync as writeFileSync3,
|
|
213
|
+
renameSync,
|
|
214
|
+
unlinkSync as unlinkSync3,
|
|
215
|
+
readdirSync as readdirSync2,
|
|
216
|
+
rmSync,
|
|
217
|
+
statSync as statSync2
|
|
218
|
+
} from "fs";
|
|
219
|
+
import { resolve as resolve2, join as join3, dirname as dirname2 } from "path";
|
|
220
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
19
221
|
|
|
20
222
|
// src/bare-transform.ts
|
|
21
|
-
import { existsSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
22
|
-
import { join } from "path";
|
|
223
|
+
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2, unlinkSync as unlinkSync2 } from "fs";
|
|
224
|
+
import { join as join2 } from "path";
|
|
23
225
|
var HELLO_PAGE = `export default function Page() {
|
|
24
226
|
return <h1>Hello Theo</h1>
|
|
25
227
|
}
|
|
@@ -28,28 +230,45 @@ function applyBareTransform(targetDir, options = {}) {
|
|
|
28
230
|
if (options._testForceError) {
|
|
29
231
|
throw new Error(`Forced transform failure: ${options._testForceError}`);
|
|
30
232
|
}
|
|
31
|
-
const pkgPath =
|
|
32
|
-
if (
|
|
33
|
-
const pkg = JSON.parse(
|
|
34
|
-
if (pkg.dependencies
|
|
233
|
+
const pkgPath = join2(targetDir, "package.json");
|
|
234
|
+
if (existsSync2(pkgPath)) {
|
|
235
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
236
|
+
if (pkg.dependencies) {
|
|
35
237
|
delete pkg.dependencies["@usetheo/ui"];
|
|
238
|
+
delete pkg.dependencies["@usetheo/sdk"];
|
|
239
|
+
delete pkg.dependencies["lucide-react"];
|
|
36
240
|
}
|
|
37
|
-
|
|
241
|
+
if (pkg.devDependencies) {
|
|
242
|
+
delete pkg.devDependencies.tailwindcss;
|
|
243
|
+
delete pkg.devDependencies["tailwindcss-animate"];
|
|
244
|
+
delete pkg.devDependencies.postcss;
|
|
245
|
+
delete pkg.devDependencies.autoprefixer;
|
|
246
|
+
}
|
|
247
|
+
writeFileSync2(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
248
|
+
`);
|
|
38
249
|
}
|
|
39
|
-
const pagePath =
|
|
40
|
-
if (
|
|
41
|
-
|
|
250
|
+
const pagePath = join2(targetDir, "app/page.tsx");
|
|
251
|
+
if (existsSync2(pagePath)) {
|
|
252
|
+
writeFileSync2(pagePath, HELLO_PAGE);
|
|
42
253
|
}
|
|
43
|
-
const chatPath =
|
|
44
|
-
if (
|
|
45
|
-
|
|
254
|
+
const chatPath = join2(targetDir, "server/routes/chat.ts");
|
|
255
|
+
if (existsSync2(chatPath)) {
|
|
256
|
+
unlinkSync2(chatPath);
|
|
257
|
+
}
|
|
258
|
+
const tailwindCfg = join2(targetDir, "tailwind.config.ts");
|
|
259
|
+
if (existsSync2(tailwindCfg)) {
|
|
260
|
+
unlinkSync2(tailwindCfg);
|
|
261
|
+
}
|
|
262
|
+
const postcssCfg = join2(targetDir, "postcss.config.js");
|
|
263
|
+
if (existsSync2(postcssCfg)) {
|
|
264
|
+
unlinkSync2(postcssCfg);
|
|
46
265
|
}
|
|
47
266
|
}
|
|
48
267
|
|
|
49
268
|
// src/index.ts
|
|
50
|
-
var
|
|
269
|
+
var __dirname2 = dirname2(fileURLToPath2(import.meta.url));
|
|
51
270
|
function getTemplateDir(templateName = "default") {
|
|
52
|
-
return
|
|
271
|
+
return resolve2(__dirname2, "../templates", templateName);
|
|
53
272
|
}
|
|
54
273
|
function isValidProjectName(name) {
|
|
55
274
|
return /^[a-z0-9][a-z0-9._-]*$/.test(name);
|
|
@@ -61,9 +280,9 @@ function scaffold(targetDir, projectName, templateName = "default", options = {}
|
|
|
61
280
|
);
|
|
62
281
|
}
|
|
63
282
|
const templateDir = getTemplateDir(templateName);
|
|
64
|
-
if (!
|
|
283
|
+
if (!existsSync3(templateDir)) {
|
|
65
284
|
throw new Error(
|
|
66
|
-
`Template "${templateName}" not found. Available templates: default, dashboard, api-only, postgres`
|
|
285
|
+
`Template "${templateName}" not found. Available templates: default, dashboard, api-only, postgres, saas`
|
|
67
286
|
);
|
|
68
287
|
}
|
|
69
288
|
if (!isValidProjectName(projectName)) {
|
|
@@ -71,26 +290,28 @@ function scaffold(targetDir, projectName, templateName = "default", options = {}
|
|
|
71
290
|
`Invalid project name "${projectName}". Use lowercase letters, numbers, hyphens, and dots. Must start with a letter or number.`
|
|
72
291
|
);
|
|
73
292
|
}
|
|
74
|
-
if (
|
|
75
|
-
const contents =
|
|
293
|
+
if (existsSync3(targetDir)) {
|
|
294
|
+
const contents = readdirSync2(targetDir);
|
|
76
295
|
if (contents.length > 0) {
|
|
77
|
-
throw new Error(
|
|
78
|
-
`Directory "${targetDir}" is not empty. Please use an empty directory.`
|
|
79
|
-
);
|
|
296
|
+
throw new Error(`Directory "${targetDir}" is not empty. Please use an empty directory.`);
|
|
80
297
|
}
|
|
81
298
|
}
|
|
82
|
-
|
|
83
|
-
const gitignoreSrc =
|
|
84
|
-
const gitignoreDest =
|
|
85
|
-
if (
|
|
299
|
+
cpSync2(templateDir, targetDir, { recursive: true });
|
|
300
|
+
const gitignoreSrc = join3(targetDir, "_gitignore");
|
|
301
|
+
const gitignoreDest = join3(targetDir, ".gitignore");
|
|
302
|
+
if (existsSync3(gitignoreSrc)) {
|
|
86
303
|
renameSync(gitignoreSrc, gitignoreDest);
|
|
87
304
|
}
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
const
|
|
305
|
+
for (const entry of readdirSync2(targetDir)) {
|
|
306
|
+
if (!entry.endsWith(".tmpl")) continue;
|
|
307
|
+
const src = join3(targetDir, entry);
|
|
308
|
+
const stat = statSync2(src);
|
|
309
|
+
if (!stat.isFile()) continue;
|
|
310
|
+
const dst = join3(targetDir, entry.slice(0, -".tmpl".length));
|
|
311
|
+
const content = readFileSync3(src, "utf-8");
|
|
91
312
|
const replaced = content.replace(/\{\{name\}\}/g, projectName);
|
|
92
|
-
|
|
93
|
-
|
|
313
|
+
writeFileSync3(dst, replaced);
|
|
314
|
+
unlinkSync3(src);
|
|
94
315
|
}
|
|
95
316
|
if (options.bare) {
|
|
96
317
|
try {
|
|
@@ -108,62 +329,83 @@ Original error: ${original}`
|
|
|
108
329
|
}
|
|
109
330
|
}
|
|
110
331
|
|
|
111
|
-
// src/pkg-manager.ts
|
|
112
|
-
function detectPkgManager() {
|
|
113
|
-
const ua = process.env.npm_config_user_agent ?? "";
|
|
114
|
-
if (ua.startsWith("yarn")) return "yarn";
|
|
115
|
-
if (ua.startsWith("pnpm")) return "pnpm";
|
|
116
|
-
if (ua.startsWith("bun")) return "bun";
|
|
117
|
-
return "npm";
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// src/install.ts
|
|
121
|
-
import spawn from "cross-spawn";
|
|
122
|
-
function runInstall(cwd, pkgManager) {
|
|
123
|
-
const result = spawn.sync(pkgManager, ["install"], {
|
|
124
|
-
cwd,
|
|
125
|
-
stdio: "inherit",
|
|
126
|
-
env: { ...process.env, NODE_ENV: "development" }
|
|
127
|
-
});
|
|
128
|
-
if (result.status !== 0) {
|
|
129
|
-
throw new Error(`Failed to install dependencies with ${pkgManager}`);
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
332
|
// src/cli.ts
|
|
134
333
|
function main() {
|
|
334
|
+
try {
|
|
335
|
+
assertNodeVersion(process.version);
|
|
336
|
+
} catch (err) {
|
|
337
|
+
console.error("");
|
|
338
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
339
|
+
process.exit(1);
|
|
340
|
+
}
|
|
135
341
|
const args = process.argv.slice(2);
|
|
136
342
|
const positionalArgs = args.filter((a) => !a.startsWith("--"));
|
|
137
343
|
const projectName = positionalArgs[0];
|
|
138
344
|
if (!projectName) {
|
|
139
|
-
console.error(
|
|
345
|
+
console.error(
|
|
346
|
+
"Usage: create-theokit <project-name> [--template=name] [--bare] [--skip-install]"
|
|
347
|
+
);
|
|
140
348
|
console.error("");
|
|
141
|
-
console.error("
|
|
142
|
-
console.error("
|
|
349
|
+
console.error("Templates: default, dashboard, api-only, postgres, saas");
|
|
350
|
+
console.error("");
|
|
351
|
+
console.error("Recipes:");
|
|
352
|
+
console.error(
|
|
353
|
+
" npx create-theokit my-app Full TheoUI + agent surface (requires @usetheo/sdk on npm)"
|
|
354
|
+
);
|
|
355
|
+
console.error(
|
|
356
|
+
" npx create-theokit my-app --bare Minimal Hello Theo (no @usetheo/* deps \u2014 always works)"
|
|
357
|
+
);
|
|
143
358
|
console.error(" npx create-theokit my-app --template=dashboard");
|
|
144
|
-
console.error(
|
|
359
|
+
console.error(
|
|
360
|
+
" npx create-theokit my-app --skip-install Scaffold files only, run install manually"
|
|
361
|
+
);
|
|
145
362
|
process.exit(1);
|
|
146
363
|
}
|
|
147
364
|
const templateFlag = args.find((a) => a.startsWith("--template="));
|
|
148
365
|
const templateName = templateFlag ? templateFlag.split("=")[1] : "default";
|
|
149
366
|
const bare = args.includes("--bare");
|
|
150
|
-
const
|
|
367
|
+
const skipInstall = args.includes("--skip-install");
|
|
368
|
+
let backends = [];
|
|
369
|
+
try {
|
|
370
|
+
backends = parseBackendFlags(args);
|
|
371
|
+
} catch (err) {
|
|
372
|
+
console.error("");
|
|
373
|
+
console.error(err instanceof Error ? err.message : String(err));
|
|
374
|
+
process.exit(1);
|
|
375
|
+
}
|
|
376
|
+
const targetDir = resolve3(process.cwd(), projectName);
|
|
151
377
|
try {
|
|
152
378
|
const suffix = bare ? " [--bare: skipping TheoUI defaults]" : "";
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
`
|
|
379
|
+
const backendsSuffix = backends.length > 0 ? ` [+services: ${backends.join(", ")}]` : "";
|
|
380
|
+
console.log(
|
|
381
|
+
`
|
|
382
|
+
Creating TheoKit project "${projectName}" (template: ${templateName})${suffix}${backendsSuffix}...
|
|
383
|
+
`
|
|
384
|
+
);
|
|
156
385
|
scaffold(targetDir, projectName, templateName, { bare });
|
|
386
|
+
if (backends.length > 0) {
|
|
387
|
+
scaffoldServices({ targetDir, projectName, backends });
|
|
388
|
+
console.log(` \u2713 Scaffolded ${String(backends.length)} service(s): ${backends.join(", ")}
|
|
389
|
+
`);
|
|
390
|
+
}
|
|
157
391
|
const pkgManager = detectPkgManager();
|
|
158
|
-
|
|
392
|
+
if (skipInstall) {
|
|
393
|
+
console.log(`Skipping install (--skip-install). Run \`${pkgManager} install\` manually.
|
|
159
394
|
`);
|
|
160
|
-
|
|
395
|
+
} else {
|
|
396
|
+
console.log(`Installing dependencies with ${pkgManager}...
|
|
397
|
+
`);
|
|
398
|
+
runInstall(targetDir, pkgManager);
|
|
399
|
+
}
|
|
161
400
|
console.log(`
|
|
162
401
|
\u2713 Project created at ${targetDir}
|
|
163
402
|
`);
|
|
164
403
|
console.log(` Next steps:
|
|
165
404
|
`);
|
|
166
405
|
console.log(` cd ${projectName}`);
|
|
406
|
+
if (skipInstall) {
|
|
407
|
+
console.log(` ${pkgManager} install`);
|
|
408
|
+
}
|
|
167
409
|
console.log(` ${pkgManager === "npm" ? "npx" : pkgManager} theokit dev
|
|
168
410
|
`);
|
|
169
411
|
} catch (err) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/index.ts","../src/bare-transform.ts","../src/pkg-manager.ts","../src/install.ts"],"sourcesContent":["import { resolve } from 'node:path'\nimport { scaffold } from './index.js'\nimport { detectPkgManager } from './pkg-manager.js'\nimport { runInstall } from './install.js'\n\nexport function main(): void {\n const args = process.argv.slice(2)\n const positionalArgs = args.filter((a) => !a.startsWith('--'))\n const projectName = positionalArgs[0]\n\n if (!projectName) {\n console.error('Usage: create-theokit <project-name> [--template=name] [--bare]')\n console.error('')\n console.error('Example:')\n console.error(' npx create-theokit my-app')\n console.error(' npx create-theokit my-app --template=dashboard')\n console.error(' npx create-theokit my-app --bare (skip @usetheo/ui defaults)')\n process.exit(1)\n }\n\n // Parse --template flag\n const templateFlag = args.find((a) => a.startsWith('--template='))\n const templateName = templateFlag ? templateFlag.split('=')[1] : 'default'\n\n // Parse --bare flag (only applies to default template)\n const bare = args.includes('--bare')\n\n const targetDir = resolve(process.cwd(), projectName)\n\n try {\n const suffix = bare ? ' [--bare: skipping TheoUI defaults]' : ''\n console.log(`\\nCreating TheoKit project \"${projectName}\" (template: ${templateName})${suffix}...\\n`)\n\n scaffold(targetDir, projectName, templateName, { bare })\n\n const pkgManager = detectPkgManager()\n console.log(`Installing dependencies with ${pkgManager}...\\n`)\n runInstall(targetDir, pkgManager)\n\n console.log(`\\n ✓ Project created at ${targetDir}\\n`)\n console.log(` Next steps:\\n`)\n console.log(` cd ${projectName}`)\n console.log(` ${pkgManager === 'npm' ? 'npx' : pkgManager} theokit dev\\n`)\n } catch (err) {\n console.error(`\\n ✗ ${(err as Error).message}\\n`)\n process.exit(1)\n }\n}\n\n// Auto-execute when run as script\nmain()\n","import {\n existsSync,\n cpSync,\n readFileSync,\n writeFileSync,\n renameSync,\n unlinkSync,\n readdirSync,\n rmSync,\n} from 'node:fs'\nimport { resolve, join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { applyBareTransform } from './bare-transform.js'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nfunction getTemplateDir(templateName = 'default'): string {\n return resolve(__dirname, '../templates', templateName)\n}\n\nfunction isValidProjectName(name: string): boolean {\n return /^[a-z0-9][a-z0-9._-]*$/.test(name)\n}\n\nexport interface ScaffoldOptions {\n bare?: boolean\n /** Test-only — force the bare transform to throw to validate EC-4 rollback. */\n _testForceTransformError?: string\n}\n\nexport function scaffold(\n targetDir: string,\n projectName: string,\n templateName = 'default',\n options: ScaffoldOptions = {},\n): void {\n // EC-4 + ADR D5: --bare only applies to default template\n if (options.bare && templateName !== 'default') {\n throw new Error(\n `--bare flag only applies to the default template; got \"${templateName}\". ` +\n `Use \\`npx create-theokit <name> --template=default --bare\\` or pick a different template.`,\n )\n }\n\n const templateDir = getTemplateDir(templateName)\n\n if (!existsSync(templateDir)) {\n throw new Error(\n `Template \"${templateName}\" not found. Available templates: default, dashboard, api-only, postgres`,\n )\n }\n\n if (!isValidProjectName(projectName)) {\n throw new Error(\n `Invalid project name \"${projectName}\". ` +\n `Use lowercase letters, numbers, hyphens, and dots. Must start with a letter or number.`,\n )\n }\n\n if (existsSync(targetDir)) {\n const contents = readdirSync(targetDir)\n if (contents.length > 0) {\n throw new Error(\n `Directory \"${targetDir}\" is not empty. Please use an empty directory.`,\n )\n }\n }\n\n cpSync(templateDir, targetDir, { recursive: true })\n\n const gitignoreSrc = join(targetDir, '_gitignore')\n const gitignoreDest = join(targetDir, '.gitignore')\n if (existsSync(gitignoreSrc)) {\n renameSync(gitignoreSrc, gitignoreDest)\n }\n\n const tmplPath = join(targetDir, 'package.json.tmpl')\n if (existsSync(tmplPath)) {\n const content = readFileSync(tmplPath, 'utf-8')\n const replaced = content.replace(/\\{\\{name\\}\\}/g, projectName)\n writeFileSync(join(targetDir, 'package.json'), replaced)\n unlinkSync(tmplPath)\n }\n\n // T4.1 — Apply --bare transform with EC-4 atomic rollback\n if (options.bare) {\n try {\n applyBareTransform(targetDir, {\n _testForceError: options._testForceTransformError,\n })\n } catch (err) {\n // EC-4: roll back partial state\n rmSync(targetDir, { recursive: true, force: true })\n const original = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Scaffold rolled back: bare transform failed. Check filesystem perms.\\nOriginal error: ${original}`,\n )\n }\n }\n}\n","/**\n * T4.1 — `--bare` transformation.\n *\n * Applied AFTER the default template is copied. Removes:\n * - `@usetheo/ui` from `package.json` dependencies\n * - `app/page.tsx` agent-surface content (replaces with Hello Theo)\n * - `server/routes/chat.ts` (mock chat — depends on TheoUI events)\n *\n * EC-4: callers MUST wrap this in try/catch + `rmSync` rollback so a partial\n * transform never leaves the target dir in a broken state.\n */\n\nimport { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs'\nimport { join } from 'node:path'\n\nconst HELLO_PAGE = `export default function Page() {\n return <h1>Hello Theo</h1>\n}\n`\n\nexport interface BareTransformOptions {\n /** Test-only — force a synthetic write failure to validate rollback path. */\n _testForceError?: string\n}\n\nexport function applyBareTransform(\n targetDir: string,\n options: BareTransformOptions = {},\n): void {\n if (options._testForceError) {\n throw new Error(`Forced transform failure: ${options._testForceError}`)\n }\n\n // 1. Remove @usetheo/ui from package.json deps\n const pkgPath = join(targetDir, 'package.json')\n if (existsSync(pkgPath)) {\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'))\n if (pkg.dependencies && '@usetheo/ui' in pkg.dependencies) {\n delete pkg.dependencies['@usetheo/ui']\n }\n writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + '\\n')\n }\n\n // 2. Replace app/page.tsx with Hello Theo\n const pagePath = join(targetDir, 'app/page.tsx')\n if (existsSync(pagePath)) {\n writeFileSync(pagePath, HELLO_PAGE)\n }\n\n // 3. Remove mock chat route (depends on AgentEvent type and TheoUI deps)\n const chatPath = join(targetDir, 'server/routes/chat.ts')\n if (existsSync(chatPath)) {\n unlinkSync(chatPath)\n }\n}\n","export type PkgManager = 'npm' | 'pnpm' | 'yarn' | 'bun'\n\nexport function detectPkgManager(): PkgManager {\n const ua = process.env.npm_config_user_agent ?? ''\n if (ua.startsWith('yarn')) return 'yarn'\n if (ua.startsWith('pnpm')) return 'pnpm'\n if (ua.startsWith('bun')) return 'bun'\n return 'npm'\n}\n","import spawn from 'cross-spawn'\nimport type { PkgManager } from './pkg-manager.js'\n\nexport function runInstall(cwd: string, pkgManager: PkgManager): void {\n const result = spawn.sync(pkgManager, ['install'], {\n cwd,\n stdio: 'inherit',\n env: { ...process.env, NODE_ENV: 'development' },\n })\n\n if (result.status !== 0) {\n throw new Error(`Failed to install dependencies with ${pkgManager}`)\n }\n}\n"],"mappings":"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","names":["resolve","existsSync","readFileSync","writeFileSync","unlinkSync","join","existsSync","join","readFileSync","writeFileSync","unlinkSync","resolve"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/install.ts","../src/pkg-manager.ts","../src/preflight-node.ts","../src/scaffold-services.ts","../src/index.ts","../src/bare-transform.ts"],"sourcesContent":["import { resolve } from 'node:path'\n\nimport { runInstall } from './install.js'\nimport { detectPkgManager } from './pkg-manager.js'\nimport { assertNodeVersion } from './preflight-node.js'\nimport { parseBackendFlags, scaffoldServices, type BackendKind } from './scaffold-services.js'\n\nimport { scaffold } from './index.js'\n\nexport function main(): void {\n // Preflight FIRST — refuses to write any files if Node is below the SDK floor.\n // SDK requires Node ≥ 22.12; cryptic node:sqlite ABI errors otherwise.\n try {\n assertNodeVersion(process.version)\n } catch (err) {\n console.error('')\n console.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n\n const args = process.argv.slice(2)\n const positionalArgs = args.filter((a) => !a.startsWith('--'))\n const projectName = positionalArgs[0]\n\n if (!projectName) {\n console.error(\n 'Usage: create-theokit <project-name> [--template=name] [--bare] [--skip-install]',\n )\n console.error('')\n console.error('Templates: default, dashboard, api-only, postgres, saas')\n console.error('')\n console.error('Recipes:')\n console.error(\n ' npx create-theokit my-app Full TheoUI + agent surface (requires @usetheo/sdk on npm)',\n )\n console.error(\n ' npx create-theokit my-app --bare Minimal Hello Theo (no @usetheo/* deps — always works)',\n )\n console.error(' npx create-theokit my-app --template=dashboard')\n console.error(\n ' npx create-theokit my-app --skip-install Scaffold files only, run install manually',\n )\n process.exit(1)\n }\n\n // Parse --template flag\n const templateFlag = args.find((a) => a.startsWith('--template='))\n const templateName = templateFlag ? templateFlag.split('=')[1] : 'default'\n\n // Parse --bare flag (only applies to default template)\n const bare = args.includes('--bare')\n\n // Parse --skip-install — useful for smoke testing, monorepo dogfood, air-gapped envs.\n const skipInstall = args.includes('--skip-install')\n\n // Parse --backend python | --backend node (Wave 2; multi-value supported)\n let backends: BackendKind[] = []\n try {\n backends = parseBackendFlags(args)\n } catch (err) {\n console.error('')\n console.error(err instanceof Error ? err.message : String(err))\n process.exit(1)\n }\n\n const targetDir = resolve(process.cwd(), projectName)\n\n try {\n const suffix = bare ? ' [--bare: skipping TheoUI defaults]' : ''\n const backendsSuffix = backends.length > 0 ? ` [+services: ${backends.join(', ')}]` : ''\n console.log(\n `\\nCreating TheoKit project \"${projectName}\" (template: ${templateName})${suffix}${backendsSuffix}...\\n`,\n )\n\n scaffold(targetDir, projectName, templateName, { bare })\n\n // Wave 2 — scaffold polyglot services AFTER main scaffold\n if (backends.length > 0) {\n scaffoldServices({ targetDir, projectName, backends })\n console.log(` ✓ Scaffolded ${String(backends.length)} service(s): ${backends.join(', ')}\\n`)\n }\n\n const pkgManager = detectPkgManager()\n if (skipInstall) {\n console.log(`Skipping install (--skip-install). Run \\`${pkgManager} install\\` manually.\\n`)\n } else {\n console.log(`Installing dependencies with ${pkgManager}...\\n`)\n runInstall(targetDir, pkgManager)\n }\n\n console.log(`\\n ✓ Project created at ${targetDir}\\n`)\n console.log(` Next steps:\\n`)\n console.log(` cd ${projectName}`)\n if (skipInstall) {\n console.log(` ${pkgManager} install`)\n }\n console.log(` ${pkgManager === 'npm' ? 'npx' : pkgManager} theokit dev\\n`)\n } catch (err) {\n console.error(`\\n ✗ ${(err as Error).message}\\n`)\n process.exit(1)\n }\n}\n\n// Auto-execute when run as script\nmain()\n","import spawn from 'cross-spawn'\n\nimport type { PkgManager } from './pkg-manager.js'\n\nexport function runInstall(cwd: string, pkgManager: PkgManager): void {\n const result = spawn.sync(pkgManager, ['install'], {\n cwd,\n stdio: 'inherit',\n env: { ...process.env, NODE_ENV: 'development' },\n })\n\n if (result.status !== 0) {\n throw new Error(`Failed to install dependencies with ${pkgManager}`)\n }\n}\n","export type PkgManager = 'npm' | 'pnpm' | 'yarn' | 'bun'\n\nexport function detectPkgManager(): PkgManager {\n const ua = process.env.npm_config_user_agent ?? ''\n if (ua.startsWith('yarn')) return 'yarn'\n if (ua.startsWith('pnpm')) return 'pnpm'\n if (ua.startsWith('bun')) return 'bun'\n return 'npm'\n}\n","/**\n * Node version preflight for `create-theokit`.\n *\n * `@usetheo/sdk` declares `engines.node: \">=22.12.0\"`. Users on older Node\n * hit cryptic `node:sqlite` / `better-sqlite3` ABI errors mid-chat without\n * any actionable diagnostic. This preflight runs at scaffold start, prints\n * a clear error, and exits before any FS write (ADR D4 of the plan).\n *\n * Zero-dep semver comparator — no `semver` package needed.\n */\n\n/** Minimum Node version required by `@usetheo/sdk`. */\nexport const MIN_NODE_VERSION = '22.12.0'\n\n/**\n * Compare two semver strings (major.minor.patch). Strips leading `v` from\n * either side. Pre-release suffixes (e.g., `-rc.1`, `-nightly...`) are\n * parsed as the base patch — acceptable for a preflight (we're not gating\n * on exact pre-release ordering).\n *\n * Returns:\n * <0 when a < b\n * 0 when a == b\n * >0 when a > b\n */\nexport function compareSemver(a: string, b: string): number {\n const parse = (raw: string): [number, number, number] => {\n const stripped = raw.replace(/^v/, '').split('-')[0] ?? '0.0.0'\n const parts = stripped.split('.').map((s) => Number.parseInt(s, 10) || 0)\n return [parts[0] ?? 0, parts[1] ?? 0, parts[2] ?? 0]\n }\n const [aMaj, aMin, aPat] = parse(a)\n const [bMaj, bMin, bPat] = parse(b)\n if (aMaj !== bMaj) return aMaj - bMaj\n if (aMin !== bMin) return aMin - bMin\n return aPat - bPat\n}\n\n/**\n * Throw with an actionable message if `currentRaw` is below `minimum`.\n * Default minimum is `MIN_NODE_VERSION` (22.12.0).\n *\n * Called as the first line of `create-theokit`'s `main` so the preflight\n * fires before any directory is written.\n */\nexport function assertNodeVersion(currentRaw: string, minimum: string = MIN_NODE_VERSION): void {\n const current = currentRaw.replace(/^v/, '')\n if (compareSemver(currentRaw, minimum) < 0) {\n throw new Error(\n `create-theokit requires Node ${minimum} or later (the @usetheo/sdk peer engines floor).\\n` +\n ` Detected: Node ${current}\\n` +\n ` Fix: nvm install 22 && nvm use 22\\n` +\n ` (or your version manager equivalent — fnm, volta, asdf, nvs)\\n`,\n )\n }\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scaffold helper. All write paths derived from the trusted\n * targetDir (CLI argument, resolved absolute). Read paths are the\n * bundled service templates shipped with this package.\n */\n/**\n * Phase 4 — `--backend python|node` scaffolding (T4.1, T4.2).\n *\n * After the main TheoKit scaffold runs, this helper:\n * - Copies the requested service template(s) under `<target>/services/<name>/`\n * - Substitutes `{{name}}` in `.tmpl` files\n * - Renames `.tmpl` files to drop the suffix\n * - Injects services config into the user's `theo.config.ts`\n * - Injects `@hey-api/client-fetch` into the user's package.json (EC-10)\n */\nimport {\n cpSync,\n existsSync,\n readFileSync,\n readdirSync,\n statSync,\n writeFileSync,\n unlinkSync,\n} from 'node:fs'\nimport { dirname, join, resolve } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nexport type BackendKind = 'python' | 'node'\n\nconst VALID_BACKENDS = ['python', 'node'] as const\n\n/**\n * Parse `--backend python` / `--backend node` (multi-value) from argv.\n *\n * Accepts:\n * --backend python\n * --backend=python\n * --backend python --backend node\n *\n * Throws on unknown backend name.\n */\nexport function parseBackendFlags(args: string[]): BackendKind[] {\n const out: BackendKind[] = []\n for (let i = 0; i < args.length; i++) {\n const a = args[i] ?? ''\n let value: string | undefined\n if (a === '--backend') {\n value = args[i + 1]\n i++\n } else if (a.startsWith('--backend=')) {\n value = a.slice('--backend='.length)\n }\n if (value === undefined) continue\n if (!(VALID_BACKENDS as readonly string[]).includes(value)) {\n throw new Error(\n `unknown --backend value: '${value}'. Valid options: ${VALID_BACKENDS.join(', ')}.`,\n )\n }\n out.push(value as BackendKind)\n }\n return out\n}\n\nconst BACKEND_CONFIG: Record<\n BackendKind,\n {\n templateDir: string\n serviceName: string\n port: number\n proxy: string\n dev: string\n start: string\n }\n> = {\n python: {\n templateDir: 'agent-python',\n serviceName: 'agent',\n port: 8001,\n proxy: '/api/agent',\n dev: 'uvicorn main:app --reload --port 8001',\n start: 'uvicorn main:app --port 8001 --workers 4',\n },\n node: {\n templateDir: 'agent-node',\n serviceName: 'worker',\n port: 8002,\n proxy: '/api/worker',\n dev: 'pnpm dev',\n start: 'pnpm start',\n },\n}\n\nfunction getServiceTemplateDir(kind: BackendKind): string {\n return resolve(__dirname, '../templates/services', BACKEND_CONFIG[kind].templateDir)\n}\n\nfunction substituteTmpls(dir: string, projectName: string): void {\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry)\n const stat = statSync(full)\n if (stat.isDirectory()) {\n substituteTmpls(full, projectName)\n continue\n }\n if (entry.endsWith('.tmpl')) {\n const content = readFileSync(full, 'utf-8').replace(/\\{\\{name\\}\\}/g, projectName)\n const dest = full.replace(/\\.tmpl$/, '')\n writeFileSync(dest, content)\n unlinkSync(full)\n }\n }\n}\n\ninterface ServiceEntry {\n runtime: BackendKind\n port: number\n proxy: string\n dev: string\n start: string\n}\n\n/**\n * Build the `services: {}` snippet to inject into `theo.config.ts`.\n * Returns the inner record literal — caller wraps in `services: { ... }`.\n */\nexport function buildServicesSnippet(selections: { name: string; entry: ServiceEntry }[]): string {\n if (selections.length === 0) return ''\n const blocks = selections.map(({ name, entry }) => {\n return ` ${name}: {\n runtime: '${entry.runtime}',\n port: ${String(entry.port)},\n proxy: '${entry.proxy}',\n dev: ${JSON.stringify(entry.dev)},\n start: ${JSON.stringify(entry.start)},\n },`\n })\n return ` services: {\\n${blocks.join('\\n')}\\n },\\n`\n}\n\n/**\n * Insert the services block into an existing `theo.config.ts`.\n * Strategy: find `defineConfig({` and append the services block before the closing brace.\n */\nexport function injectServicesIntoConfig(configSource: string, snippet: string): string {\n if (snippet.length === 0) return configSource\n if (configSource.includes('services:')) return configSource // already present\n\n // Match the LAST `}` before the closing of defineConfig({...})\n const re = /defineConfig\\(\\{([\\s\\S]*?)\\}\\)/m\n const match = re.exec(configSource)\n if (!match) return configSource\n\n const inner = match[1]\n // Strip trailing whitespace without backtracking-prone \\s+$ regex.\n let trimEnd = inner.length\n while (trimEnd > 0 && /\\s/.test(inner.charAt(trimEnd - 1))) {\n trimEnd--\n }\n const trimmed = inner.slice(0, trimEnd)\n const sep = trimmed.length > 0 && !trimmed.endsWith(',') ? ',\\n' : '\\n'\n const newInner = `${trimmed}${sep}${snippet}`\n return configSource.replace(re, `defineConfig({${newInner}})`)\n}\n\nexport function injectHeyApiDep(packageJsonSource: string): string {\n const pkg = JSON.parse(packageJsonSource) as {\n dependencies?: Record<string, string>\n }\n pkg.dependencies = pkg.dependencies ?? {}\n if (!('@hey-api/client-fetch' in pkg.dependencies)) {\n pkg.dependencies['@hey-api/client-fetch'] = '^0.6.0'\n }\n return JSON.stringify(pkg, null, 2) + '\\n'\n}\n\nexport interface ScaffoldServicesOptions {\n /** Target project directory (already scaffolded with the TS template). */\n targetDir: string\n /** Project name (substituted into .tmpl files). */\n projectName: string\n /** Which backends to scaffold. */\n backends: BackendKind[]\n}\n\nexport function scaffoldServices(options: ScaffoldServicesOptions): void {\n if (options.backends.length === 0) return\n\n const selections: { name: string; entry: ServiceEntry }[] = []\n\n for (const kind of options.backends) {\n const cfg = BACKEND_CONFIG[kind]\n const src = getServiceTemplateDir(kind)\n // Schema contract: dev/start commands run from `services/<serviceName>/` cwd\n // (services/schema/schema.ts line 35). The destination MUST equal serviceName\n // so the orchestrator's cwd resolution matches the on-disk directory.\n const dest = join(options.targetDir, 'services', cfg.serviceName)\n if (!existsSync(src)) {\n throw new Error(`service template not found: ${src}`)\n }\n cpSync(src, dest, { recursive: true })\n substituteTmpls(dest, options.projectName)\n\n selections.push({\n name: cfg.serviceName,\n entry: {\n runtime: kind,\n port: cfg.port,\n proxy: cfg.proxy,\n dev: cfg.dev,\n start: cfg.start,\n },\n })\n }\n\n // Inject services into theo.config.ts\n const configPath = join(options.targetDir, 'theo.config.ts')\n if (existsSync(configPath)) {\n const cfgSrc = readFileSync(configPath, 'utf-8')\n const snippet = buildServicesSnippet(selections)\n const updated = injectServicesIntoConfig(cfgSrc, snippet)\n if (updated !== cfgSrc) {\n writeFileSync(configPath, updated)\n }\n }\n\n // EC-10: inject @hey-api/client-fetch into user's package.json\n const pkgPath = join(options.targetDir, 'package.json')\n if (existsSync(pkgPath)) {\n const pkgSrc = readFileSync(pkgPath, 'utf-8')\n const updated = injectHeyApiDep(pkgSrc)\n writeFileSync(pkgPath, updated)\n }\n\n // Rename .gitignore for services if needed (none currently shipped, but reserved hook)\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * `create-theokit` scaffold tool. All write paths are derived from the\n * user-supplied target directory (CLI argument, resolved to absolute).\n * Read paths are the bundled `templates/` shipped with this package.\n * Build-time tool — no HTTP input.\n */\nimport {\n existsSync,\n cpSync,\n readFileSync,\n writeFileSync,\n renameSync,\n unlinkSync,\n readdirSync,\n rmSync,\n statSync,\n} from 'node:fs'\nimport { resolve, join, dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nimport { applyBareTransform } from './bare-transform.js'\n\nconst __dirname = dirname(fileURLToPath(import.meta.url))\n\nfunction getTemplateDir(templateName = 'default'): string {\n return resolve(__dirname, '../templates', templateName)\n}\n\nfunction isValidProjectName(name: string): boolean {\n return /^[a-z0-9][a-z0-9._-]*$/.test(name)\n}\n\nexport interface ScaffoldOptions {\n bare?: boolean\n /** Test-only — force the bare transform to throw to validate EC-4 rollback. */\n _testForceTransformError?: string\n}\n\n// eslint-disable-next-line complexity -- scaffold orchestrator: validate → copy → rename _gitignore → template-substitute all *.tmpl → optional --bare transform with rollback. Branches are linear, not nested.\nexport function scaffold(\n targetDir: string,\n projectName: string,\n templateName = 'default',\n options: ScaffoldOptions = {},\n): void {\n // EC-4 + ADR D5: --bare only applies to default template\n if (options.bare && templateName !== 'default') {\n throw new Error(\n `--bare flag only applies to the default template; got \"${templateName}\". ` +\n `Use \\`npx create-theokit <name> --template=default --bare\\` or pick a different template.`,\n )\n }\n\n const templateDir = getTemplateDir(templateName)\n\n if (!existsSync(templateDir)) {\n throw new Error(\n `Template \"${templateName}\" not found. Available templates: default, dashboard, api-only, postgres, saas`,\n )\n }\n\n if (!isValidProjectName(projectName)) {\n throw new Error(\n `Invalid project name \"${projectName}\". ` +\n `Use lowercase letters, numbers, hyphens, and dots. Must start with a letter or number.`,\n )\n }\n\n if (existsSync(targetDir)) {\n const contents = readdirSync(targetDir)\n if (contents.length > 0) {\n throw new Error(`Directory \"${targetDir}\" is not empty. Please use an empty directory.`)\n }\n }\n\n cpSync(templateDir, targetDir, { recursive: true })\n\n const gitignoreSrc = join(targetDir, '_gitignore')\n const gitignoreDest = join(targetDir, '.gitignore')\n if (existsSync(gitignoreSrc)) {\n renameSync(gitignoreSrc, gitignoreDest)\n }\n\n // Apply {{name}} substitution to every `*.tmpl` file in the target dir.\n // Each `foo.tmpl` becomes `foo` with placeholders replaced. Walks only\n // the project root (deeper subfolders don't currently need templating).\n for (const entry of readdirSync(targetDir)) {\n if (!entry.endsWith('.tmpl')) continue\n const src = join(targetDir, entry)\n const stat = statSync(src)\n if (!stat.isFile()) continue\n const dst = join(targetDir, entry.slice(0, -'.tmpl'.length))\n const content = readFileSync(src, 'utf-8')\n const replaced = content.replace(/\\{\\{name\\}\\}/g, projectName)\n writeFileSync(dst, replaced)\n unlinkSync(src)\n }\n\n // T4.1 — Apply --bare transform with EC-4 atomic rollback\n if (options.bare) {\n try {\n applyBareTransform(targetDir, {\n _testForceError: options._testForceTransformError,\n })\n } catch (err) {\n // EC-4: roll back partial state\n rmSync(targetDir, { recursive: true, force: true })\n const original = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Scaffold rolled back: bare transform failed. Check filesystem perms.\\nOriginal error: ${original}`,\n )\n }\n }\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Scaffold transform. Mutates files inside the freshly-created target\n * directory whose absolute path is the function input. No HTTP input.\n */\n/**\n * T4.1 — `--bare` transformation.\n *\n * Applied AFTER the default template is copied. Removes:\n * - `@usetheo/ui` from `package.json` dependencies (TheoUI bundled components)\n * - `@usetheo/sdk` from `package.json` dependencies (agent SDK — see below)\n * - `app/page.tsx` agent-surface content (replaces with Hello Theo)\n * - `server/routes/chat.ts` (mock chat — depends on SDK + TheoUI events)\n * - `tailwind.config.ts` + `postcss.config.js` (Tailwind toolchain — only\n * needed by the @usetheo/ui-driven default surface)\n * - tailwind* + postcss* from devDependencies (toolchain cleanup)\n *\n * Why SDK removal is in --bare:\n * `@usetheo/sdk` is not yet on the public npm registry (operator-deferred\n * publish per macro roadmap item #3). A user running `npx create-theokit`\n * without `--bare` hits `npm install` → 404. The `--bare` path produces a\n * scaffold that ALWAYS works without registry dependencies — Hello Theo\n * with a clean structure to grow into.\n *\n * EC-4: callers MUST wrap this in try/catch + `rmSync` rollback so a partial\n * transform never leaves the target dir in a broken state.\n */\n\nimport { existsSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs'\nimport { join } from 'node:path'\n\nconst HELLO_PAGE = `export default function Page() {\n return <h1>Hello Theo</h1>\n}\n`\n\nexport interface BareTransformOptions {\n /** Test-only — force a synthetic write failure to validate rollback path. */\n _testForceError?: string\n}\n\nexport function applyBareTransform(targetDir: string, options: BareTransformOptions = {}): void {\n if (options._testForceError) {\n throw new Error(`Forced transform failure: ${options._testForceError}`)\n }\n\n // 1. Remove @usetheo/ui + @usetheo/sdk + tailwind toolchain from deps\n const pkgPath = join(targetDir, 'package.json')\n if (existsSync(pkgPath)) {\n interface PartialPackageJson {\n dependencies?: Record<string, string>\n devDependencies?: Record<string, string>\n [key: string]: unknown\n }\n const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8')) as PartialPackageJson\n if (pkg.dependencies) {\n delete pkg.dependencies['@usetheo/ui']\n // Drop SDK — operator-deferred npm publish (macro roadmap item #3).\n // Without removal, `npm install` hits 404 for any consumer outside\n // the workspace.\n delete pkg.dependencies['@usetheo/sdk']\n // lucide-react ships with the TheoUI surface; --bare doesn't render\n // any icons so it's safe to drop.\n delete pkg.dependencies['lucide-react']\n }\n if (pkg.devDependencies) {\n // Tailwind toolchain is only needed by the @usetheo/ui-driven default\n // surface. --bare ships unstyled Hello Theo; no Tailwind required.\n delete pkg.devDependencies.tailwindcss\n delete pkg.devDependencies['tailwindcss-animate']\n delete pkg.devDependencies.postcss\n delete pkg.devDependencies.autoprefixer\n }\n writeFileSync(pkgPath, `${JSON.stringify(pkg, null, 2)}\\n`)\n }\n\n // 2. Replace app/page.tsx with Hello Theo\n const pagePath = join(targetDir, 'app/page.tsx')\n if (existsSync(pagePath)) {\n writeFileSync(pagePath, HELLO_PAGE)\n }\n\n // 3. Remove mock chat route (depends on AgentEvent type and TheoUI deps)\n const chatPath = join(targetDir, 'server/routes/chat.ts')\n if (existsSync(chatPath)) {\n unlinkSync(chatPath)\n }\n\n // 4. Remove tailwind + postcss config files (toolchain dropped from devDeps)\n const tailwindCfg = join(targetDir, 'tailwind.config.ts')\n if (existsSync(tailwindCfg)) {\n unlinkSync(tailwindCfg)\n }\n const postcssCfg = join(targetDir, 'postcss.config.js')\n if (existsSync(postcssCfg)) {\n unlinkSync(postcssCfg)\n }\n}\n"],"mappings":"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","names":["resolve","existsSync","cpSync","readFileSync","writeFileSync","unlinkSync","readdirSync","statSync","resolve","join","dirname","fileURLToPath","existsSync","readFileSync","writeFileSync","unlinkSync","join","__dirname","dirname","fileURLToPath","resolve","existsSync","readdirSync","cpSync","join","statSync","readFileSync","writeFileSync","unlinkSync","resolve"]}
|
package/package.json
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22.12
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"dev": "theokit dev"
|
|
7
|
+
"dev": "theokit dev",
|
|
8
|
+
"build": "theokit build",
|
|
9
|
+
"start": "theokit start",
|
|
10
|
+
"typecheck": "tsc --noEmit"
|
|
8
11
|
},
|
|
9
12
|
"dependencies": {
|
|
10
|
-
"theokit": "^0.1.0-alpha.
|
|
13
|
+
"theokit": "^0.1.0-alpha.6",
|
|
11
14
|
"react": "^19.0.0",
|
|
12
15
|
"react-dom": "^19.0.0"
|
|
13
16
|
},
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22.12
|
|
@@ -4,10 +4,13 @@
|
|
|
4
4
|
"private": true,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
|
-
"dev": "theokit dev"
|
|
7
|
+
"dev": "theokit dev",
|
|
8
|
+
"build": "theokit build",
|
|
9
|
+
"start": "theokit start",
|
|
10
|
+
"typecheck": "tsc --noEmit"
|
|
8
11
|
},
|
|
9
12
|
"dependencies": {
|
|
10
|
-
"theokit": "^0.1.0-alpha.
|
|
13
|
+
"theokit": "^0.1.0-alpha.6",
|
|
11
14
|
"react": "^19.0.0",
|
|
12
15
|
"react-dom": "^19.0.0"
|
|
13
16
|
},
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
22.12
|