@taujs/create-taujs 0.2.0 → 0.3.1
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/index.js +329 -44
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { execSync } from "child_process";
|
|
5
|
+
import { pathToFileURL } from "url";
|
|
5
6
|
import fs from "fs-extra";
|
|
6
7
|
import path from "path";
|
|
7
8
|
import pc from "picocolors";
|
|
@@ -44,16 +45,27 @@ var PACKAGE_MANAGERS = {
|
|
|
44
45
|
pnpm: "pnpm install",
|
|
45
46
|
yarn: "yarn install"
|
|
46
47
|
};
|
|
48
|
+
var FRAMEWORKS = ["react", "vue"];
|
|
47
49
|
function parseArgs() {
|
|
48
50
|
const rawArgs = process.argv.slice(2);
|
|
49
51
|
let projectName;
|
|
50
|
-
|
|
52
|
+
let framework;
|
|
53
|
+
for (let i = 0; i < rawArgs.length; i++) {
|
|
54
|
+
const arg = rawArgs[i];
|
|
55
|
+
if (arg === "--framework") {
|
|
56
|
+
framework = rawArgs[++i];
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (arg.startsWith("--framework=")) {
|
|
60
|
+
framework = arg.slice("--framework=".length);
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
51
63
|
if (!arg.startsWith("-") && !projectName) {
|
|
52
64
|
projectName = arg;
|
|
53
65
|
continue;
|
|
54
66
|
}
|
|
55
67
|
}
|
|
56
|
-
return { projectName };
|
|
68
|
+
return { projectName, framework };
|
|
57
69
|
}
|
|
58
70
|
function validateProjectName(value) {
|
|
59
71
|
if (!value) return "Project name is required";
|
|
@@ -62,9 +74,12 @@ function validateProjectName(value) {
|
|
|
62
74
|
}
|
|
63
75
|
return true;
|
|
64
76
|
}
|
|
77
|
+
function validateFramework(value) {
|
|
78
|
+
return FRAMEWORKS.includes(value) ? true : `Framework must be one of: ${FRAMEWORKS.join(", ")}`;
|
|
79
|
+
}
|
|
65
80
|
async function main() {
|
|
66
81
|
console.log(pc.cyan("\nWelcome to \u03C4js (taujs)\n"));
|
|
67
|
-
const { projectName: argName } = parseArgs();
|
|
82
|
+
const { projectName: argName, framework: argFramework } = parseArgs();
|
|
68
83
|
if (argName) {
|
|
69
84
|
const res = validateProjectName(argName);
|
|
70
85
|
if (res !== true) {
|
|
@@ -73,6 +88,14 @@ async function main() {
|
|
|
73
88
|
process.exit(1);
|
|
74
89
|
}
|
|
75
90
|
}
|
|
91
|
+
if (argFramework) {
|
|
92
|
+
const res = validateFramework(argFramework);
|
|
93
|
+
if (res !== true) {
|
|
94
|
+
console.log(pc.red(`
|
|
95
|
+
\u2716 Invalid framework "${argFramework}": ${res}`));
|
|
96
|
+
process.exit(1);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
76
99
|
const questions = [
|
|
77
100
|
{
|
|
78
101
|
type: argName ? null : "text",
|
|
@@ -81,6 +104,16 @@ async function main() {
|
|
|
81
104
|
initial: "my-taujs-app",
|
|
82
105
|
validate: validateProjectName
|
|
83
106
|
},
|
|
107
|
+
{
|
|
108
|
+
type: argFramework ? null : "select",
|
|
109
|
+
name: "framework",
|
|
110
|
+
message: "Framework:",
|
|
111
|
+
choices: [
|
|
112
|
+
{ title: "React", value: "react" },
|
|
113
|
+
{ title: "Vue", value: "vue" }
|
|
114
|
+
],
|
|
115
|
+
initial: 0
|
|
116
|
+
},
|
|
84
117
|
{
|
|
85
118
|
type: "select",
|
|
86
119
|
name: "packageManager",
|
|
@@ -116,10 +149,18 @@ async function main() {
|
|
|
116
149
|
console.log(pc.red("\n\u2716 Project name is required"));
|
|
117
150
|
process.exit(1);
|
|
118
151
|
}
|
|
152
|
+
const framework = argFramework ?? answers.framework;
|
|
153
|
+
const frameworkRes = validateFramework(framework);
|
|
154
|
+
if (frameworkRes !== true) {
|
|
155
|
+
console.log(pc.red(`
|
|
156
|
+
\u2716 Invalid framework "${framework}": ${frameworkRes}`));
|
|
157
|
+
process.exit(1);
|
|
158
|
+
}
|
|
119
159
|
const config = {
|
|
120
160
|
projectName,
|
|
121
161
|
packageManager: answers.packageManager,
|
|
122
|
-
installDeps: answers.installDeps
|
|
162
|
+
installDeps: answers.installDeps,
|
|
163
|
+
framework
|
|
123
164
|
};
|
|
124
165
|
await createProject(config);
|
|
125
166
|
}
|
|
@@ -174,30 +215,90 @@ async function createDirectoryStructure(targetDir) {
|
|
|
174
215
|
await fs.ensureDir(path.join(targetDir, dir));
|
|
175
216
|
}
|
|
176
217
|
}
|
|
218
|
+
function planFiles(config) {
|
|
219
|
+
const { projectName, packageManager, framework } = config;
|
|
220
|
+
const shared = [
|
|
221
|
+
{ path: "package.json", json: generatePackageJson(projectName, framework) },
|
|
222
|
+
{ path: "build.ts", content: generateBuildTs() },
|
|
223
|
+
{ path: "tsconfig.json", json: generateTsConfig(framework) },
|
|
224
|
+
{ path: "src/server/tsconfig.json", json: generateServerTsConfig() },
|
|
225
|
+
{ path: "taujs.config.ts", content: generateTaujsConfig(framework) },
|
|
226
|
+
{ path: ".gitignore", content: generateGitignore() },
|
|
227
|
+
{ path: "README.md", content: generateReadme(projectName, packageManager, framework) },
|
|
228
|
+
// Agent wiring (P1-04): pinned local-bin MCP config + a short CLAUDE.md pointer whose
|
|
229
|
+
// substance ships in @taujs/mcp.
|
|
230
|
+
{ path: ".mcp.json", json: generateMcpJson(packageManager) },
|
|
231
|
+
{ path: "CLAUDE.md", content: generateClaudeMd() },
|
|
232
|
+
{ path: "src/client/index.html", content: generateIndexHtml() },
|
|
233
|
+
{ path: "src/client/styles.css", content: generateStyles() },
|
|
234
|
+
// server (framework-independent — a single shared source)
|
|
235
|
+
{ path: "src/server/index.ts", content: generateServerIndex() },
|
|
236
|
+
{ path: "src/server/services/registry.ts", content: generateServiceRegistry() },
|
|
237
|
+
{ path: "src/server/services/example.service.ts", content: generateExampleService() },
|
|
238
|
+
{ path: "src/server/types.d.ts", content: generateServiceTypesAugmentation() },
|
|
239
|
+
{ path: "src/client/public/favicon.svg", content: generateFavicon() }
|
|
240
|
+
];
|
|
241
|
+
const client = framework === "vue" ? [
|
|
242
|
+
{ path: "src/client/App.vue", content: generateAppVue() },
|
|
243
|
+
{ path: "src/client/HomePage.vue", content: generateHomePageVue() },
|
|
244
|
+
{ path: "src/client/StreamingPage.vue", content: generateStreamingPageVue() },
|
|
245
|
+
{ path: "src/client/entry-client.ts", content: generateEntryClientVue() },
|
|
246
|
+
{ path: "src/client/entry-server.ts", content: generateEntryServerVue() },
|
|
247
|
+
{ path: "src/client/vite-env.d.ts", content: generateViteEnvVue() }
|
|
248
|
+
] : [
|
|
249
|
+
{ path: "src/client/App.tsx", content: generateAppComponent() },
|
|
250
|
+
{ path: "src/client/entry-client.tsx", content: generateEntryClient() },
|
|
251
|
+
{ path: "src/client/entry-server.tsx", content: generateEntryServer() },
|
|
252
|
+
{ path: "src/client/vite-env.d.ts", content: generateViteEnv() }
|
|
253
|
+
];
|
|
254
|
+
return [...shared, ...client];
|
|
255
|
+
}
|
|
177
256
|
async function generateFiles(targetDir, config) {
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
257
|
+
for (const entry of planFiles(config)) {
|
|
258
|
+
const full = path.join(targetDir, entry.path);
|
|
259
|
+
await fs.ensureDir(path.dirname(full));
|
|
260
|
+
if ("json" in entry) {
|
|
261
|
+
await fs.writeJSON(full, entry.json, { spaces: 2 });
|
|
262
|
+
} else {
|
|
263
|
+
await fs.writeFile(full, entry.content);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
function generatePackageJson(projectName, framework) {
|
|
268
|
+
if (framework === "vue") {
|
|
269
|
+
return {
|
|
270
|
+
name: projectName,
|
|
271
|
+
version: "0.1.0",
|
|
272
|
+
private: true,
|
|
273
|
+
type: "module",
|
|
274
|
+
scripts: {
|
|
275
|
+
dev: "cross-env NODE_ENV=development tsx watch --ignore vite.config.ts --trace-warnings --tsconfig ./src/server/tsconfig.json ./src/server/index.ts --loglevel verbose",
|
|
276
|
+
"build:client": "tsx build.ts",
|
|
277
|
+
"build:entry-server": "cross-env BUILD_MODE=ssr tsx build.ts",
|
|
278
|
+
"build:server": "esbuild src/server/index.ts --bundle --platform=node --format=esm --outfile=dist/server/index.js --external:fastify --external:@taujs/server --external:@taujs/vue",
|
|
279
|
+
build: "tsx build.ts && cross-env BUILD_MODE=ssr tsx build.ts && esbuild src/server/index.ts --bundle --platform=node --format=esm --outfile=dist/server/index.js --external:fastify --external:@taujs/server --external:@taujs/vue",
|
|
280
|
+
start: "cross-env NODE_ENV=production node dist/server/index.js",
|
|
281
|
+
lint: "vue-tsc --noEmit"
|
|
282
|
+
},
|
|
283
|
+
dependencies: {
|
|
284
|
+
"@taujs/server": "latest",
|
|
285
|
+
"@taujs/vue": "latest",
|
|
286
|
+
"@vue/server-renderer": "^3.5.0",
|
|
287
|
+
fastify: "^5.8.5",
|
|
288
|
+
vue: "^3.5.0"
|
|
289
|
+
},
|
|
290
|
+
devDependencies: {
|
|
291
|
+
"@taujs/mcp": "latest",
|
|
292
|
+
"@types/node": "^22.10.5",
|
|
293
|
+
"@vitejs/plugin-vue": "^6.0.0",
|
|
294
|
+
"cross-env": "^7.0.3",
|
|
295
|
+
tsx: "^4.19.3",
|
|
296
|
+
typescript: "^5.7.3",
|
|
297
|
+
vite: "^7.1.11",
|
|
298
|
+
"vue-tsc": "^2.1.10"
|
|
299
|
+
}
|
|
300
|
+
};
|
|
301
|
+
}
|
|
201
302
|
return {
|
|
202
303
|
name: projectName,
|
|
203
304
|
version: "0.1.0",
|
|
@@ -244,13 +345,14 @@ await taujsBuild({
|
|
|
244
345
|
});
|
|
245
346
|
`;
|
|
246
347
|
}
|
|
247
|
-
function generateTsConfig() {
|
|
348
|
+
function generateTsConfig(framework) {
|
|
248
349
|
return {
|
|
249
350
|
compilerOptions: {
|
|
250
351
|
target: "ES2022",
|
|
251
352
|
module: "ESNext",
|
|
252
353
|
lib: ["ES2022", "DOM", "DOM.Iterable"],
|
|
253
|
-
|
|
354
|
+
// Vue SFCs are typed by vue-tsc; React needs the automatic JSX runtime.
|
|
355
|
+
...framework === "react" ? { jsx: "react-jsx" } : {},
|
|
254
356
|
moduleResolution: "bundler",
|
|
255
357
|
resolveJsonModule: true,
|
|
256
358
|
allowImportingTsExtensions: true,
|
|
@@ -275,8 +377,12 @@ function generateServerTsConfig() {
|
|
|
275
377
|
include: ["./**/*"]
|
|
276
378
|
};
|
|
277
379
|
}
|
|
278
|
-
function generateTaujsConfig() {
|
|
279
|
-
|
|
380
|
+
function generateTaujsConfig(framework) {
|
|
381
|
+
const pluginImport = framework === "vue" ? `
|
|
382
|
+
import { pluginVue } from '@taujs/vue/plugin';` : "";
|
|
383
|
+
const pluginsLine = framework === "vue" ? `
|
|
384
|
+
plugins: [pluginVue()],` : "";
|
|
385
|
+
return `import { defineConfig } from '@taujs/server/config';${pluginImport}
|
|
280
386
|
|
|
281
387
|
export default defineConfig({
|
|
282
388
|
server: {
|
|
@@ -287,7 +393,7 @@ export default defineConfig({
|
|
|
287
393
|
apps: [
|
|
288
394
|
{
|
|
289
395
|
appId: 'main',
|
|
290
|
-
entryPoint: ''
|
|
396
|
+
entryPoint: '',${pluginsLine}
|
|
291
397
|
routes: [
|
|
292
398
|
{
|
|
293
399
|
path: '/',
|
|
@@ -366,8 +472,18 @@ coverage
|
|
|
366
472
|
.cache
|
|
367
473
|
`;
|
|
368
474
|
}
|
|
369
|
-
function generateReadme(projectName, packageManager) {
|
|
475
|
+
function generateReadme(projectName, packageManager, framework) {
|
|
370
476
|
const pmRun = packageManager === "npm" ? "npm run" : packageManager;
|
|
477
|
+
const clientTree = framework === "vue" ? `\u2502 \u2502 \u251C\u2500\u2500 App.vue # Root component (route switch)
|
|
478
|
+
\u2502 \u2502 \u251C\u2500\u2500 HomePage.vue # SSR route (useSSRData + v-if)
|
|
479
|
+
\u2502 \u2502 \u251C\u2500\u2500 StreamingPage.vue # Streaming route (await useSSRDataAsync)
|
|
480
|
+
\u2502 \u2502 \u251C\u2500\u2500 entry-client.ts # Client hydration entry
|
|
481
|
+
\u2502 \u2502 \u251C\u2500\u2500 entry-server.ts # SSR render entry` : `\u2502 \u2502 \u251C\u2500\u2500 App.tsx # Root component
|
|
482
|
+
\u2502 \u2502 \u251C\u2500\u2500 entry-client.tsx # Client hydration entry
|
|
483
|
+
\u2502 \u2502 \u251C\u2500\u2500 entry-server.tsx # SSR render entry`;
|
|
484
|
+
const mainUi = framework === "vue" ? "App.vue" : "App.tsx";
|
|
485
|
+
const clientExt = framework === "vue" ? "ts" : "tsx";
|
|
486
|
+
const frameworkDoc = framework === "vue" ? "- [Vue Documentation](https://vuejs.org)" : "- [React Documentation](https://react.dev)";
|
|
371
487
|
return `# ${projectName}
|
|
372
488
|
|
|
373
489
|
A \u03C4js (taujs) application with server-side rendering, streaming, and a type-safe service layer.
|
|
@@ -400,9 +516,7 @@ ${pmRun} start
|
|
|
400
516
|
${projectName}/
|
|
401
517
|
\u251C\u2500\u2500 src/
|
|
402
518
|
\u2502 \u251C\u2500\u2500 client/
|
|
403
|
-
|
|
404
|
-
\u2502 \u2502 \u251C\u2500\u2500 entry-client.tsx # Client hydration entry
|
|
405
|
-
\u2502 \u2502 \u251C\u2500\u2500 entry-server.tsx # SSR render entry
|
|
519
|
+
${clientTree}
|
|
406
520
|
\u2502 \u2502 \u251C\u2500\u2500 styles.css # Global styles
|
|
407
521
|
\u2502 \u2502 \u251C\u2500\u2500 vite-env.d.ts # Vite client types
|
|
408
522
|
\u2502 \u2502 \u2514\u2500\u2500 public/
|
|
@@ -421,10 +535,10 @@ ${projectName}/
|
|
|
421
535
|
|
|
422
536
|
## Editing the App
|
|
423
537
|
|
|
424
|
-
- Main UI: \`src/client
|
|
538
|
+
- Main UI: \`src/client/${mainUi}\`
|
|
425
539
|
- Styles: \`src/client/styles.css\`
|
|
426
|
-
- SSR entry: \`src/client/entry-server
|
|
427
|
-
- Client entry: \`src/client/entry-client
|
|
540
|
+
- SSR entry: \`src/client/entry-server.${clientExt}\`
|
|
541
|
+
- Client entry: \`src/client/entry-client.${clientExt}\`
|
|
428
542
|
- Routes: \`taujs.config.ts\`
|
|
429
543
|
- Services: \`src/server/services/\`
|
|
430
544
|
|
|
@@ -432,7 +546,7 @@ ${projectName}/
|
|
|
432
546
|
|
|
433
547
|
- [\u03C4js Documentation](https://taujs.dev)
|
|
434
548
|
- [Fastify Documentation](https://fastify.dev)
|
|
435
|
-
|
|
549
|
+
${frameworkDoc}
|
|
436
550
|
|
|
437
551
|
## License
|
|
438
552
|
|
|
@@ -763,6 +877,165 @@ function generateViteEnv() {
|
|
|
763
877
|
return `/// <reference types="vite/client" />
|
|
764
878
|
`;
|
|
765
879
|
}
|
|
880
|
+
function generateViteEnvVue() {
|
|
881
|
+
return `/// <reference types="vite/client" />
|
|
882
|
+
|
|
883
|
+
declare module '*.vue' {
|
|
884
|
+
import type { DefineComponent } from 'vue';
|
|
885
|
+
const component: DefineComponent<Record<string, unknown>, Record<string, unknown>, unknown>;
|
|
886
|
+
export default component;
|
|
887
|
+
}
|
|
888
|
+
`;
|
|
889
|
+
}
|
|
890
|
+
function generateAppVue() {
|
|
891
|
+
return `<script setup lang="ts">
|
|
892
|
+
import { computed } from 'vue';
|
|
893
|
+
|
|
894
|
+
import HomePage from './HomePage.vue';
|
|
895
|
+
import StreamingPage from './StreamingPage.vue';
|
|
896
|
+
|
|
897
|
+
import './styles.css';
|
|
898
|
+
|
|
899
|
+
const props = defineProps<{ location?: string; routeContext?: unknown }>();
|
|
900
|
+
|
|
901
|
+
// The server passes \`location\`; on the client fall back to the current path so hydration matches.
|
|
902
|
+
const path = computed(() => props.location ?? (typeof window !== 'undefined' ? window.location.pathname : '/'));
|
|
903
|
+
const isStreaming = computed(() => path.value.startsWith('/streaming'));
|
|
904
|
+
</script>
|
|
905
|
+
|
|
906
|
+
<template>
|
|
907
|
+
<div class="app">
|
|
908
|
+
<header class="app-header">
|
|
909
|
+
<h1 class="app-title">\u03C4js - Composing systems, not just apps</h1>
|
|
910
|
+
<p class="app-subtitle">Request-first application composition with explicit per-route rendering control.</p>
|
|
911
|
+
</header>
|
|
912
|
+
|
|
913
|
+
<Suspense v-if="isStreaming">
|
|
914
|
+
<template #default>
|
|
915
|
+
<StreamingPage />
|
|
916
|
+
</template>
|
|
917
|
+
<template #fallback>
|
|
918
|
+
<section class="card card--primary">
|
|
919
|
+
<p class="card-message">Loading greeting\u2026</p>
|
|
920
|
+
<p class="card-meta">Streaming data from the server.</p>
|
|
921
|
+
</section>
|
|
922
|
+
</template>
|
|
923
|
+
</Suspense>
|
|
924
|
+
<HomePage v-else />
|
|
925
|
+
|
|
926
|
+
<section class="section">
|
|
927
|
+
<h2 class="section-title">Quick start</h2>
|
|
928
|
+
<ul class="list">
|
|
929
|
+
<li>Edit <code>src/client/App.vue</code> to change this page.</li>
|
|
930
|
+
<li>Adjust styles in <code>src/client/styles.css</code>.</li>
|
|
931
|
+
<li>Configure routes in <code>taujs.config.ts</code>.</li>
|
|
932
|
+
<li>Visit <a href="/">/</a> for standard SSR and <a href="/streaming">/streaming</a> for streaming SSR.</li>
|
|
933
|
+
<li>Further information can be found at <a href="http://taujs.dev" target="_blank">\u03C4js Documentation and Guides</a>.</li>
|
|
934
|
+
</ul>
|
|
935
|
+
</section>
|
|
936
|
+
|
|
937
|
+
<section class="tip">
|
|
938
|
+
<p>
|
|
939
|
+
<strong>SSR:</strong> The <code>/</code> route resolves data on the server, then consumes it with
|
|
940
|
+
<code>useSSRData</code> + <code>v-if</code> (non-blocking fallback rendering).
|
|
941
|
+
</p>
|
|
942
|
+
<p>
|
|
943
|
+
<strong>STREAM:</strong> The <code>/streaming</code> route <code>await</code>s <code>useSSRDataAsync</code>
|
|
944
|
+
in async <code>setup</code> under <code><Suspense></code>, so the render blocks until data resolves.
|
|
945
|
+
</p>
|
|
946
|
+
</section>
|
|
947
|
+
|
|
948
|
+
<footer class="app-footer">
|
|
949
|
+
<p>
|
|
950
|
+
Built with
|
|
951
|
+
<a href="https://taujs.dev" target="_blank" rel="noopener">\u03C4js</a>
|
|
952
|
+
\xB7
|
|
953
|
+
<a href="https://fastify.dev" target="_blank" rel="noopener">Fastify</a>
|
|
954
|
+
\xB7
|
|
955
|
+
<a href="https://vuejs.org" target="_blank" rel="noopener">Vue</a>
|
|
956
|
+
</p>
|
|
957
|
+
</footer>
|
|
958
|
+
</div>
|
|
959
|
+
</template>
|
|
960
|
+
`;
|
|
961
|
+
}
|
|
962
|
+
function generateHomePageVue() {
|
|
963
|
+
return `<script setup lang="ts">
|
|
964
|
+
import { useSSRData } from '@taujs/vue';
|
|
965
|
+
|
|
966
|
+
type GreetingData = {
|
|
967
|
+
message: string;
|
|
968
|
+
timestamp: string;
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
// Fallback idiom: non-blocking; \`data\` is undefined until ready, guarded with v-if.
|
|
972
|
+
const data = useSSRData<GreetingData>();
|
|
973
|
+
</script>
|
|
974
|
+
|
|
975
|
+
<template>
|
|
976
|
+
<section v-if="data" class="card card--primary">
|
|
977
|
+
<p class="card-message">{{ data.message }}</p>
|
|
978
|
+
<p class="card-meta">Generated at: {{ new Date(data.timestamp).toLocaleString() }}</p>
|
|
979
|
+
</section>
|
|
980
|
+
<section v-else class="card card--primary">
|
|
981
|
+
<p class="card-message">Loading greeting\u2026</p>
|
|
982
|
+
<p class="card-meta">Resolving data on the server.</p>
|
|
983
|
+
</section>
|
|
984
|
+
</template>
|
|
985
|
+
`;
|
|
986
|
+
}
|
|
987
|
+
function generateStreamingPageVue() {
|
|
988
|
+
return `<script setup lang="ts">
|
|
989
|
+
import { useSSRDataAsync } from '@taujs/vue';
|
|
990
|
+
|
|
991
|
+
type GreetingData = {
|
|
992
|
+
message: string;
|
|
993
|
+
timestamp: string;
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
// Suspense idiom: async setup blocks on the data, so streamed routes deliver it in the payload.
|
|
997
|
+
const data = await useSSRDataAsync<GreetingData>();
|
|
998
|
+
</script>
|
|
999
|
+
|
|
1000
|
+
<template>
|
|
1001
|
+
<section class="card card--primary">
|
|
1002
|
+
<p class="card-message">{{ data.message }}</p>
|
|
1003
|
+
<p class="card-meta">Generated at: {{ new Date(data.timestamp).toLocaleString() }}</p>
|
|
1004
|
+
</section>
|
|
1005
|
+
</template>
|
|
1006
|
+
`;
|
|
1007
|
+
}
|
|
1008
|
+
function generateEntryClientVue() {
|
|
1009
|
+
return `import { hydrateApp } from '@taujs/vue';
|
|
1010
|
+
|
|
1011
|
+
import App from './App.vue';
|
|
1012
|
+
|
|
1013
|
+
hydrateApp({
|
|
1014
|
+
appComponent: App,
|
|
1015
|
+
rootElementId: 'root',
|
|
1016
|
+
enableDebug: import.meta.env.DEV,
|
|
1017
|
+
});
|
|
1018
|
+
`;
|
|
1019
|
+
}
|
|
1020
|
+
function generateEntryServerVue() {
|
|
1021
|
+
return `import { createRenderer } from '@taujs/vue';
|
|
1022
|
+
|
|
1023
|
+
import App from './App.vue';
|
|
1024
|
+
|
|
1025
|
+
export const { renderSSR, renderStream } = createRenderer({
|
|
1026
|
+
appComponent: App,
|
|
1027
|
+
headContent: ({ data, meta }) => \`
|
|
1028
|
+
<title>\${meta?.title || "\u03C4js - Composing systems, not just apps"}</title>
|
|
1029
|
+
<meta name="description" content="\${
|
|
1030
|
+
meta?.description ||
|
|
1031
|
+
(data as { message?: string })?.message ||
|
|
1032
|
+
"\u03C4js - Composing systems, not just apps"
|
|
1033
|
+
}">
|
|
1034
|
+
\`,
|
|
1035
|
+
enableDebug: process.env.NODE_ENV === "development",
|
|
1036
|
+
});
|
|
1037
|
+
`;
|
|
1038
|
+
}
|
|
766
1039
|
function generateEntryClient() {
|
|
767
1040
|
return `import { hydrateApp } from '@taujs/react';
|
|
768
1041
|
import { App } from './App';
|
|
@@ -873,7 +1146,19 @@ function generateFavicon() {
|
|
|
873
1146
|
</svg>
|
|
874
1147
|
`;
|
|
875
1148
|
}
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
}
|
|
1149
|
+
var invokedDirectly = (() => {
|
|
1150
|
+
try {
|
|
1151
|
+
return !!process.argv[1] && import.meta.url === pathToFileURL(fs.realpathSync(process.argv[1])).href;
|
|
1152
|
+
} catch {
|
|
1153
|
+
return false;
|
|
1154
|
+
}
|
|
1155
|
+
})();
|
|
1156
|
+
if (invokedDirectly) {
|
|
1157
|
+
main().catch((error) => {
|
|
1158
|
+
console.error(pc.red("\n\u2716 Error creating project:"), error);
|
|
1159
|
+
process.exit(1);
|
|
1160
|
+
});
|
|
1161
|
+
}
|
|
1162
|
+
export {
|
|
1163
|
+
planFiles
|
|
1164
|
+
};
|