@taujs/create-taujs 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/LICENSE +23 -0
- package/README.md +3 -0
- package/dist/index.js +893 -0
- package/package.json +53 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
τjs [ taujs ] Orchestration System
|
|
4
|
+
Author: John Smith
|
|
5
|
+
Copyright (c) Aoede Ltd 2024-present
|
|
6
|
+
|
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
8
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
9
|
+
in the Software without restriction, including without limitation the rights
|
|
10
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
11
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
12
|
+
furnished to do so, subject to the following conditions:
|
|
13
|
+
|
|
14
|
+
The above copyright notice and this permission notice shall be included in all
|
|
15
|
+
copies or substantial portions of the Software.
|
|
16
|
+
|
|
17
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
18
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
19
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
20
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
21
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
22
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
23
|
+
SOFTWARE.
|
package/README.md
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,893 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import fs from "fs-extra";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import pc from "picocolors";
|
|
8
|
+
import prompts from "prompts";
|
|
9
|
+
var PACKAGE_MANAGERS = {
|
|
10
|
+
npm: "npm install",
|
|
11
|
+
pnpm: "pnpm install",
|
|
12
|
+
yarn: "yarn",
|
|
13
|
+
bun: "bun install"
|
|
14
|
+
};
|
|
15
|
+
function parseArgs() {
|
|
16
|
+
const rawArgs = process.argv.slice(2);
|
|
17
|
+
let projectName;
|
|
18
|
+
for (const arg of rawArgs) {
|
|
19
|
+
if (!arg.startsWith("-") && !projectName) {
|
|
20
|
+
projectName = arg;
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { projectName };
|
|
25
|
+
}
|
|
26
|
+
async function main() {
|
|
27
|
+
console.log(pc.cyan("\nWelcome to \u03C4js (taujs)\n"));
|
|
28
|
+
const { projectName: argName } = parseArgs();
|
|
29
|
+
const questions = [
|
|
30
|
+
{
|
|
31
|
+
type: argName ? null : "text",
|
|
32
|
+
name: "projectName",
|
|
33
|
+
message: "Project name:",
|
|
34
|
+
initial: "my-taujs-app",
|
|
35
|
+
validate: (value) => {
|
|
36
|
+
if (!value) return "Project name is required";
|
|
37
|
+
if (!/^[a-z0-9-_]+$/.test(value)) {
|
|
38
|
+
return "Project name can only contain lowercase letters, numbers, hyphens, and underscores";
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
type: "select",
|
|
45
|
+
name: "packageManager",
|
|
46
|
+
message: "Package manager:",
|
|
47
|
+
choices: [
|
|
48
|
+
{ title: "npm", value: "npm" },
|
|
49
|
+
{ title: "pnpm", value: "pnpm" },
|
|
50
|
+
{ title: "yarn", value: "yarn" },
|
|
51
|
+
{ title: "bun", value: "bun" }
|
|
52
|
+
],
|
|
53
|
+
initial: 0
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
type: "confirm",
|
|
57
|
+
name: "installDeps",
|
|
58
|
+
message: "Install dependencies now?",
|
|
59
|
+
initial: true
|
|
60
|
+
}
|
|
61
|
+
];
|
|
62
|
+
const answers = await prompts(questions, {
|
|
63
|
+
onCancel: () => {
|
|
64
|
+
console.log(pc.red("\n\u2716 Operation cancelled"));
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
const config = {
|
|
69
|
+
projectName: argName || answers.projectName,
|
|
70
|
+
packageManager: answers.packageManager,
|
|
71
|
+
installDeps: answers.installDeps
|
|
72
|
+
};
|
|
73
|
+
await createProject(config);
|
|
74
|
+
}
|
|
75
|
+
async function createProject(config) {
|
|
76
|
+
const { projectName, packageManager, installDeps } = config;
|
|
77
|
+
const targetDir = path.resolve(process.cwd(), projectName);
|
|
78
|
+
if (fs.existsSync(targetDir)) {
|
|
79
|
+
console.log(pc.red(`
|
|
80
|
+
\u2716 Directory ${projectName} already exists`));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
console.log(pc.cyan(`
|
|
84
|
+
Creating project in ${pc.bold(targetDir)}...
|
|
85
|
+
`));
|
|
86
|
+
await fs.ensureDir(targetDir);
|
|
87
|
+
await createDirectoryStructure(targetDir);
|
|
88
|
+
await generateFiles(targetDir, config);
|
|
89
|
+
console.log(pc.green("Project files created"));
|
|
90
|
+
if (installDeps) {
|
|
91
|
+
console.log(
|
|
92
|
+
pc.cyan(`
|
|
93
|
+
Installing dependencies with ${packageManager}...
|
|
94
|
+
`)
|
|
95
|
+
);
|
|
96
|
+
try {
|
|
97
|
+
execSync(PACKAGE_MANAGERS[packageManager], {
|
|
98
|
+
cwd: targetDir,
|
|
99
|
+
stdio: "inherit"
|
|
100
|
+
});
|
|
101
|
+
console.log(pc.green("\nDependencies installed"));
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.log(
|
|
104
|
+
pc.yellow(
|
|
105
|
+
"\n\u26A0 Failed to install dependencies. You can install them manually."
|
|
106
|
+
)
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
console.log(
|
|
111
|
+
pc.green(`
|
|
112
|
+
\u2713 Project ${pc.bold(projectName)} created successfully!
|
|
113
|
+
`)
|
|
114
|
+
);
|
|
115
|
+
console.log(pc.cyan("Next steps:\n"));
|
|
116
|
+
console.log(` cd ${projectName}`);
|
|
117
|
+
if (!installDeps) {
|
|
118
|
+
console.log(` ${PACKAGE_MANAGERS[packageManager]}`);
|
|
119
|
+
}
|
|
120
|
+
console.log(` ${packageManager} run dev
|
|
121
|
+
`);
|
|
122
|
+
console.log(pc.dim("Documentation: https://taujs.dev\n"));
|
|
123
|
+
}
|
|
124
|
+
async function createDirectoryStructure(targetDir) {
|
|
125
|
+
const dirs = [
|
|
126
|
+
"src/server/services",
|
|
127
|
+
"src/client",
|
|
128
|
+
"src/client/public"
|
|
129
|
+
];
|
|
130
|
+
for (const dir of dirs) {
|
|
131
|
+
await fs.ensureDir(path.join(targetDir, dir));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
async function generateFiles(targetDir, config) {
|
|
135
|
+
const { projectName, packageManager } = config;
|
|
136
|
+
await fs.writeJSON(
|
|
137
|
+
path.join(targetDir, "package.json"),
|
|
138
|
+
generatePackageJson(projectName, packageManager),
|
|
139
|
+
{ spaces: 2 }
|
|
140
|
+
);
|
|
141
|
+
await fs.writeFile(path.join(targetDir, "build.ts"), generateBuildTs());
|
|
142
|
+
await fs.writeJSON(
|
|
143
|
+
path.join(targetDir, "tsconfig.json"),
|
|
144
|
+
generateTsConfig(),
|
|
145
|
+
{ spaces: 2 }
|
|
146
|
+
);
|
|
147
|
+
await fs.writeJSON(
|
|
148
|
+
path.join(targetDir, "src/server/tsconfig.json"),
|
|
149
|
+
generateServerTsConfig(),
|
|
150
|
+
{ spaces: 2 }
|
|
151
|
+
);
|
|
152
|
+
await fs.writeFile(
|
|
153
|
+
path.join(targetDir, "taujs.config.ts"),
|
|
154
|
+
generateTaujsConfig()
|
|
155
|
+
);
|
|
156
|
+
await fs.writeFile(path.join(targetDir, ".gitignore"), generateGitignore());
|
|
157
|
+
await fs.writeFile(
|
|
158
|
+
path.join(targetDir, "README.md"),
|
|
159
|
+
generateReadme(projectName, packageManager)
|
|
160
|
+
);
|
|
161
|
+
await fs.writeFile(
|
|
162
|
+
path.join(targetDir, "src/client/index.html"),
|
|
163
|
+
generateIndexHtml("\u03C4js - Composing systems, not just apps")
|
|
164
|
+
);
|
|
165
|
+
await fs.writeFile(
|
|
166
|
+
path.join(targetDir, "src/client/App.tsx"),
|
|
167
|
+
generateAppComponent()
|
|
168
|
+
);
|
|
169
|
+
await fs.writeFile(
|
|
170
|
+
path.join(targetDir, "src/client/entry-client.tsx"),
|
|
171
|
+
generateEntryClient()
|
|
172
|
+
);
|
|
173
|
+
await fs.writeFile(
|
|
174
|
+
path.join(targetDir, "src/client/entry-server.tsx"),
|
|
175
|
+
generateEntryServer()
|
|
176
|
+
);
|
|
177
|
+
await fs.writeFile(
|
|
178
|
+
path.join(targetDir, "src/client/styles.css"),
|
|
179
|
+
generateStyles()
|
|
180
|
+
);
|
|
181
|
+
await fs.writeFile(
|
|
182
|
+
path.join(targetDir, "src/client/vite-env.d.ts"),
|
|
183
|
+
generateViteEnv()
|
|
184
|
+
);
|
|
185
|
+
await fs.writeFile(
|
|
186
|
+
path.join(targetDir, "src/server/index.ts"),
|
|
187
|
+
generateServerIndex()
|
|
188
|
+
);
|
|
189
|
+
await fs.writeFile(
|
|
190
|
+
path.join(targetDir, "src/server/services/registry.ts"),
|
|
191
|
+
generateServiceRegistry()
|
|
192
|
+
);
|
|
193
|
+
await fs.writeFile(
|
|
194
|
+
path.join(targetDir, "src/server/services/example.service.ts"),
|
|
195
|
+
generateExampleService()
|
|
196
|
+
);
|
|
197
|
+
await fs.writeFile(
|
|
198
|
+
path.join(targetDir, "src/server/types.d.ts"),
|
|
199
|
+
generateServiceTypesAugmentation()
|
|
200
|
+
);
|
|
201
|
+
await fs.writeFile(
|
|
202
|
+
path.join(targetDir, "src/client/public/favicon.svg"),
|
|
203
|
+
generateFavicon()
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
function generatePackageJson(projectName, packageManager) {
|
|
207
|
+
return {
|
|
208
|
+
name: projectName,
|
|
209
|
+
version: "0.1.0",
|
|
210
|
+
private: true,
|
|
211
|
+
type: "module",
|
|
212
|
+
scripts: {
|
|
213
|
+
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",
|
|
214
|
+
"build:client": "tsx build.ts",
|
|
215
|
+
"build:entry-server": "BUILD_MODE=ssr tsx build.ts",
|
|
216
|
+
"build:server": "esbuild src/server/index.ts --bundle --platform=node --format=esm --outfile=dist/server/index.js --external:fastify --external:@taujs/server --external:@taujs/react",
|
|
217
|
+
build: "npm run build:client && npm run build:entry-server && npm run build:server",
|
|
218
|
+
start: "cross-env NODE_ENV=production node dist/server/index.js",
|
|
219
|
+
lint: "tsc --noEmit"
|
|
220
|
+
},
|
|
221
|
+
dependencies: {
|
|
222
|
+
"@taujs/react": "latest",
|
|
223
|
+
"@taujs/server": "latest",
|
|
224
|
+
fastify: "^5.6.1",
|
|
225
|
+
react: "^19.0.0",
|
|
226
|
+
"react-dom": "^19.0.0"
|
|
227
|
+
},
|
|
228
|
+
devDependencies: {
|
|
229
|
+
"@types/node": "^22.10.5",
|
|
230
|
+
"@types/react": "^19.0.2",
|
|
231
|
+
"@types/react-dom": "^19.0.2",
|
|
232
|
+
"@vitejs/plugin-react": "^4.6.0",
|
|
233
|
+
tsx: "^4.19.3",
|
|
234
|
+
typescript: "^5.7.3",
|
|
235
|
+
vite: "^7.1.11",
|
|
236
|
+
"cross-env": "^7.0.3"
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
function generateBuildTs() {
|
|
241
|
+
return `import path from "node:path";
|
|
242
|
+
import { fileURLToPath } from "node:url";
|
|
243
|
+
|
|
244
|
+
import { taujsBuild } from "@taujs/server";
|
|
245
|
+
|
|
246
|
+
import config from "./taujs.config.ts";
|
|
247
|
+
|
|
248
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
249
|
+
|
|
250
|
+
await taujsBuild({
|
|
251
|
+
clientBaseDir: path.resolve(__dirname, "src/client"),
|
|
252
|
+
config,
|
|
253
|
+
projectRoot: __dirname,
|
|
254
|
+
mode: process.env.BUILD_MODE === 'ssr' ? 'ssr' : 'client',
|
|
255
|
+
});
|
|
256
|
+
`;
|
|
257
|
+
}
|
|
258
|
+
function generateTsConfig() {
|
|
259
|
+
return {
|
|
260
|
+
compilerOptions: {
|
|
261
|
+
target: "ES2022",
|
|
262
|
+
module: "ESNext",
|
|
263
|
+
lib: ["ES2022", "DOM", "DOM.Iterable"],
|
|
264
|
+
jsx: "react-jsx",
|
|
265
|
+
moduleResolution: "bundler",
|
|
266
|
+
resolveJsonModule: true,
|
|
267
|
+
allowImportingTsExtensions: true,
|
|
268
|
+
noEmit: true,
|
|
269
|
+
isolatedModules: true,
|
|
270
|
+
esModuleInterop: true,
|
|
271
|
+
forceConsistentCasingInFileNames: true,
|
|
272
|
+
strict: true,
|
|
273
|
+
skipLibCheck: true,
|
|
274
|
+
types: [],
|
|
275
|
+
paths: {
|
|
276
|
+
"@client/*": ["./src/client/*"],
|
|
277
|
+
"@server/*": ["./src/server/*"]
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
include: ["src/client/**/*", "src/server/**/*", "taujs.config.ts"]
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
function generateServerTsConfig() {
|
|
284
|
+
return {
|
|
285
|
+
extends: "../../tsconfig.json",
|
|
286
|
+
include: ["./**/*"]
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
function generateTaujsConfig() {
|
|
290
|
+
return `import { defineConfig } from '@taujs/server/config';
|
|
291
|
+
|
|
292
|
+
export default defineConfig({
|
|
293
|
+
server: {
|
|
294
|
+
port: 5173,
|
|
295
|
+
host: 'localhost',
|
|
296
|
+
hmrPort: 5174,
|
|
297
|
+
},
|
|
298
|
+
apps: [
|
|
299
|
+
{
|
|
300
|
+
appId: 'main',
|
|
301
|
+
entryPoint: '',
|
|
302
|
+
routes: [
|
|
303
|
+
{
|
|
304
|
+
path: '/',
|
|
305
|
+
attr: {
|
|
306
|
+
render: 'ssr',
|
|
307
|
+
hydrate: true,
|
|
308
|
+
// Direct service invocation: standard SSR
|
|
309
|
+
data: async (params, ctx) => {
|
|
310
|
+
return ctx.call('example', 'greet', { name: 'SSR' });
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
path: '/streaming',
|
|
316
|
+
attr: {
|
|
317
|
+
render: 'streaming',
|
|
318
|
+
hydrate: true,
|
|
319
|
+
// Descriptor-based data: resolved by the server
|
|
320
|
+
data: async (params) => ({
|
|
321
|
+
args: { name: 'Streaming' },
|
|
322
|
+
serviceName: 'example',
|
|
323
|
+
serviceMethod: 'greet',
|
|
324
|
+
}),
|
|
325
|
+
// meta recommended for streaming routes for SEO/social and render timing
|
|
326
|
+
meta: {
|
|
327
|
+
title: '\u03C4js [taujs] - streaming',
|
|
328
|
+
description: 'Streaming page description from route meta',
|
|
329
|
+
},
|
|
330
|
+
},
|
|
331
|
+
},
|
|
332
|
+
],
|
|
333
|
+
},
|
|
334
|
+
],
|
|
335
|
+
});
|
|
336
|
+
`;
|
|
337
|
+
}
|
|
338
|
+
function generateGitignore() {
|
|
339
|
+
return `# Dependencies
|
|
340
|
+
node_modules
|
|
341
|
+
.pnp
|
|
342
|
+
.pnp.js
|
|
343
|
+
|
|
344
|
+
# Production
|
|
345
|
+
dist
|
|
346
|
+
build
|
|
347
|
+
|
|
348
|
+
# Environment
|
|
349
|
+
.env
|
|
350
|
+
.env.local
|
|
351
|
+
.env.*.local
|
|
352
|
+
|
|
353
|
+
# Logs
|
|
354
|
+
logs
|
|
355
|
+
*.log
|
|
356
|
+
npm-debug.log*
|
|
357
|
+
yarn-debug.log*
|
|
358
|
+
yarn-error.log*
|
|
359
|
+
pnpm-debug.log*
|
|
360
|
+
|
|
361
|
+
# Editor
|
|
362
|
+
.vscode
|
|
363
|
+
.idea
|
|
364
|
+
*.swp
|
|
365
|
+
*.swo
|
|
366
|
+
*~
|
|
367
|
+
|
|
368
|
+
# OS
|
|
369
|
+
.DS_Store
|
|
370
|
+
Thumbs.db
|
|
371
|
+
|
|
372
|
+
# Testing
|
|
373
|
+
coverage
|
|
374
|
+
|
|
375
|
+
# Misc
|
|
376
|
+
.cache
|
|
377
|
+
`;
|
|
378
|
+
}
|
|
379
|
+
function generateReadme(projectName, packageManager) {
|
|
380
|
+
const pmRun = packageManager === "npm" ? "npm run" : packageManager;
|
|
381
|
+
return `# ${projectName}
|
|
382
|
+
|
|
383
|
+
A \u03C4js (taujs) application with server-side rendering, streaming, and a type-safe service layer.
|
|
384
|
+
|
|
385
|
+
## Getting Started
|
|
386
|
+
|
|
387
|
+
### Development
|
|
388
|
+
|
|
389
|
+
\`\`\`bash
|
|
390
|
+
${pmRun} dev
|
|
391
|
+
\`\`\`
|
|
392
|
+
|
|
393
|
+
Visit [http://localhost:5173](http://localhost:5173)
|
|
394
|
+
|
|
395
|
+
### Build for Production
|
|
396
|
+
|
|
397
|
+
\`\`\`bash
|
|
398
|
+
${pmRun} build
|
|
399
|
+
\`\`\`
|
|
400
|
+
|
|
401
|
+
### Start Production Server
|
|
402
|
+
|
|
403
|
+
\`\`\`bash
|
|
404
|
+
${pmRun} start
|
|
405
|
+
\`\`\`
|
|
406
|
+
|
|
407
|
+
## Project Structure
|
|
408
|
+
|
|
409
|
+
\`\`\`
|
|
410
|
+
${projectName}/
|
|
411
|
+
\u251C\u2500\u2500 src/
|
|
412
|
+
\u2502 \u251C\u2500\u2500 client/
|
|
413
|
+
\u2502 \u2502 \u251C\u2500\u2500 App.tsx # Root component
|
|
414
|
+
\u2502 \u2502 \u251C\u2500\u2500 entry-client.tsx # Client hydration entry
|
|
415
|
+
\u2502 \u2502 \u251C\u2500\u2500 entry-server.tsx # SSR render entry
|
|
416
|
+
\u2502 \u2502 \u251C\u2500\u2500 styles.css # Global styles
|
|
417
|
+
\u2502 \u2502 \u251C\u2500\u2500 vite-env.d.ts # Vite client types
|
|
418
|
+
\u2502 \u2502 \u2514\u2500\u2500 public/
|
|
419
|
+
\u2502 \u2502 \u2514\u2500\u2500 favicon.svg # App icon
|
|
420
|
+
\u2502 \u2514\u2500\u2500 server/
|
|
421
|
+
\u2502 \u251C\u2500\u2500 index.ts # Server entry point
|
|
422
|
+
\u2502 \u251C\u2500\u2500 tsconfig.json # Server-only TS config (used by tsx watch)
|
|
423
|
+
\u2502 \u251C\u2500\u2500 types.d.ts # ServiceContext augmentation
|
|
424
|
+
\u2502 \u2514\u2500\u2500 services/
|
|
425
|
+
\u2502 \u251C\u2500\u2500 registry.ts # Service registry
|
|
426
|
+
\u2502 \u2514\u2500\u2500 example.service.ts # Example service
|
|
427
|
+
\u251C\u2500\u2500 build.ts # Production build entry point
|
|
428
|
+
\u251C\u2500\u2500 taujs.config.ts # \u03C4js configuration
|
|
429
|
+
\u2514\u2500\u2500 package.json
|
|
430
|
+
\`\`\`
|
|
431
|
+
|
|
432
|
+
## Editing the App
|
|
433
|
+
|
|
434
|
+
- Main UI: \`src/client/App.tsx\`
|
|
435
|
+
- Styles: \`src/client/styles.css\`
|
|
436
|
+
- SSR entry: \`src/client/entry-server.tsx\`
|
|
437
|
+
- Client entry: \`src/client/entry-client.tsx\`
|
|
438
|
+
- Routes: \`taujs.config.ts\`
|
|
439
|
+
- Services: \`src/server/services/\`
|
|
440
|
+
|
|
441
|
+
## Documentation
|
|
442
|
+
|
|
443
|
+
- [\u03C4js Documentation](https://taujs.dev)
|
|
444
|
+
- [Fastify Documentation](https://fastify.dev)
|
|
445
|
+
- [React Documentation](https://react.dev)
|
|
446
|
+
|
|
447
|
+
## License
|
|
448
|
+
|
|
449
|
+
MIT
|
|
450
|
+
`;
|
|
451
|
+
}
|
|
452
|
+
function generateIndexHtml(title) {
|
|
453
|
+
return `<!DOCTYPE html>
|
|
454
|
+
<html lang="en">
|
|
455
|
+
<head>
|
|
456
|
+
<meta charset="UTF-8" />
|
|
457
|
+
<meta
|
|
458
|
+
name="viewport"
|
|
459
|
+
content="width=device-width, initial-scale=1.0"
|
|
460
|
+
/>
|
|
461
|
+
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
|
462
|
+
<link rel="stylesheet" href="/styles.css" />
|
|
463
|
+
<title>${title}</title>
|
|
464
|
+
</head>
|
|
465
|
+
<body>
|
|
466
|
+
<main id="root"></main>
|
|
467
|
+
</body>
|
|
468
|
+
</html>
|
|
469
|
+
`;
|
|
470
|
+
}
|
|
471
|
+
function generateAppComponent() {
|
|
472
|
+
return `import { Suspense } from 'react';
|
|
473
|
+
import { useSSRStore } from '@taujs/react';
|
|
474
|
+
|
|
475
|
+
type GreetingData = {
|
|
476
|
+
message: string;
|
|
477
|
+
timestamp: string;
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
function GreetingCard() {
|
|
481
|
+
const data = useSSRStore<GreetingData>();
|
|
482
|
+
|
|
483
|
+
return (
|
|
484
|
+
<section className="card card--primary">
|
|
485
|
+
<p className="card-message">{data.message}</p>
|
|
486
|
+
<p className="card-meta">
|
|
487
|
+
Generated at: {new Date(data.timestamp).toLocaleString()}
|
|
488
|
+
</p>
|
|
489
|
+
</section>
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
export function App() {
|
|
494
|
+
return (
|
|
495
|
+
<div className="app">
|
|
496
|
+
<header className="app-header">
|
|
497
|
+
<h1 className="app-title">\u03C4js - Composing systems, not just apps</h1>
|
|
498
|
+
<p className="app-subtitle">
|
|
499
|
+
Server-first application composition with explicit per-route rendering control.
|
|
500
|
+
</p>
|
|
501
|
+
</header>
|
|
502
|
+
|
|
503
|
+
<Suspense
|
|
504
|
+
fallback={
|
|
505
|
+
<section className="card card--primary">
|
|
506
|
+
<p className="card-message">Loading greeting\u2026</p>
|
|
507
|
+
<p className="card-meta">Streaming data from the server.</p>
|
|
508
|
+
</section>
|
|
509
|
+
}
|
|
510
|
+
>
|
|
511
|
+
<GreetingCard />
|
|
512
|
+
</Suspense>
|
|
513
|
+
|
|
514
|
+
<section className="section">
|
|
515
|
+
<h2 className="section-title">Quick start</h2>
|
|
516
|
+
<ul className="list">
|
|
517
|
+
<li>Edit <code>src/client/App.tsx</code> to change this page.</li>
|
|
518
|
+
<li>Adjust styles in <code>src/client/styles.css</code>.</li>
|
|
519
|
+
<li>Configure routes in <code>taujs.config.ts</code>.</li>
|
|
520
|
+
<li>
|
|
521
|
+
Visit <a href="/">/</a> for standard SSR and{" "}
|
|
522
|
+
<a href="/streaming">/streaming</a> for streaming SSR.
|
|
523
|
+
</li>
|
|
524
|
+
<li>Further infomration can be found at <a href="http://taujs.dev" target="_blank">\u03C4js Documentation and Guides</a>.</li>
|
|
525
|
+
</ul>
|
|
526
|
+
</section>
|
|
527
|
+
|
|
528
|
+
<section className="tip">
|
|
529
|
+
<p>
|
|
530
|
+
<strong>SSR:</strong> The <code>/</code> route resolves all data on the server
|
|
531
|
+
before sending HTML. You get a complete, fully rendered document on first byte,
|
|
532
|
+
which is ideal for predictable latency and caching.
|
|
533
|
+
</p>
|
|
534
|
+
<p>
|
|
535
|
+
<strong>STREAM:</strong> The <code>/streaming</code> route uses a service descriptor
|
|
536
|
+
and returns a Promise. The <code><Suspense></code> boundary above shows
|
|
537
|
+
a fallback while the server resolves it, then progressively streams the final content.
|
|
538
|
+
</p>
|
|
539
|
+
</section>
|
|
540
|
+
|
|
541
|
+
<footer className="app-footer">
|
|
542
|
+
<p>
|
|
543
|
+
Built with{" "}
|
|
544
|
+
<a href="https://taujs.dev" target="_blank" rel="noopener">
|
|
545
|
+
\u03C4js
|
|
546
|
+
</a>
|
|
547
|
+
{" \xB7 "}
|
|
548
|
+
<a href="https://fastify.dev" target="_blank" rel="noopener">
|
|
549
|
+
Fastify
|
|
550
|
+
</a>
|
|
551
|
+
{" \xB7 "}
|
|
552
|
+
<a href="https://react.dev" target="_blank" rel="noopener">
|
|
553
|
+
React
|
|
554
|
+
</a>
|
|
555
|
+
</p>
|
|
556
|
+
</footer>
|
|
557
|
+
</div>
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
`;
|
|
561
|
+
}
|
|
562
|
+
function generateStyles() {
|
|
563
|
+
return `:root {
|
|
564
|
+
--accent: #38bdf8;
|
|
565
|
+
--accent-soft: #0ea5e9;
|
|
566
|
+
--accent-soft-bg: #0b1120;
|
|
567
|
+
--bg: #020617;
|
|
568
|
+
--bg-dark: #000;
|
|
569
|
+
--bg-elevated: #020617;
|
|
570
|
+
--border-subtle: #1e293b;
|
|
571
|
+
--color-accent-rgb: 56, 189, 248; /* #38bdf8 */
|
|
572
|
+
--color-app-title-rgb: 229, 231, 235; /* #e5e7eb */
|
|
573
|
+
--color-border-subtle-rgb: 30, 41, 59; /* #1e293b */
|
|
574
|
+
--color-code-border-rgb: 51, 65, 85; /* rgba(51, 65, 85, 0.9) */
|
|
575
|
+
--color-code-bg-rgb: 15, 23, 42; /* rgba(15, 23, 42, 0.9) */
|
|
576
|
+
--color-tip-border-rgb: 148, 163, 184; /* rgba(148, 163, 184, 0.9) */
|
|
577
|
+
--color-tip-bg-rgb: 15, 23, 42; /* rgba(15, 23, 42, 0.95) */
|
|
578
|
+
--color-footer-border-rgb: 30, 64, 175; /* rgba(30, 64, 175, 0.7) */
|
|
579
|
+
--radius-lg: 12px;
|
|
580
|
+
--radius-xl: 16px;
|
|
581
|
+
--shadow-soft: 0 18px 45px rgba(15, 23, 42, 0.7);
|
|
582
|
+
--text: #f9fafb;
|
|
583
|
+
--text-muted: #cbd5f5;
|
|
584
|
+
--text-soft: #9ca3af;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
*,
|
|
588
|
+
*::before,
|
|
589
|
+
*::after {
|
|
590
|
+
box-sizing: border-box;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
html,
|
|
594
|
+
body {
|
|
595
|
+
margin: 0;
|
|
596
|
+
min-height: 100%;
|
|
597
|
+
padding: 0;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
body {
|
|
601
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, "SF Pro Text",
|
|
602
|
+
"Segoe UI", sans-serif;
|
|
603
|
+
background: radial-gradient(
|
|
604
|
+
circle at top left,
|
|
605
|
+
var(--border-subtle) 0,
|
|
606
|
+
var(--bg) 38%,
|
|
607
|
+
var(--bg-dark) 85%
|
|
608
|
+
);
|
|
609
|
+
color: var(--text);
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
a {
|
|
613
|
+
color: var(--accent);
|
|
614
|
+
text-decoration: none;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
a:hover,
|
|
618
|
+
a:focus-visible {
|
|
619
|
+
text-decoration: underline;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
code {
|
|
623
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
|
|
624
|
+
"Liberation Mono", "Courier New", monospace;
|
|
625
|
+
font-size: 0.9em;
|
|
626
|
+
padding: 0.15rem 0.35rem;
|
|
627
|
+
border-radius: 4px;
|
|
628
|
+
background: rgba(var(--color-code-bg-rgb), 0.9);
|
|
629
|
+
border: 1px solid rgba(var(--color-code-border-rgb), 0.9);
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.app {
|
|
633
|
+
margin: 0 auto;
|
|
634
|
+
max-width: 960px;
|
|
635
|
+
padding: 3rem 1.5rem 4rem;
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
@media (min-width: 768px) {
|
|
639
|
+
.app {
|
|
640
|
+
padding: 4rem 2rem 5rem;
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
.app-header {
|
|
645
|
+
margin-bottom: 2.5rem;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
.app-title {
|
|
649
|
+
color: rgb(var(--color-app-title-rgb));
|
|
650
|
+
font-size: clamp(2rem, 2.7vw + 1.5rem, 2.8rem);
|
|
651
|
+
letter-spacing: -0.04em;
|
|
652
|
+
margin: 0;
|
|
653
|
+
padding: 0 0 0 60px;
|
|
654
|
+
position: relative;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
.app-title::before {
|
|
658
|
+
background: url("favicon.svg") no-repeat;
|
|
659
|
+
background-size: 50px 50px;
|
|
660
|
+
content: "";
|
|
661
|
+
border-radius: 4px;
|
|
662
|
+
display: block;
|
|
663
|
+
height: 50px;
|
|
664
|
+
left: 0;
|
|
665
|
+
position: absolute;
|
|
666
|
+
top: 0;
|
|
667
|
+
width: 50px;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.app-subtitle {
|
|
671
|
+
color: var(--text-soft);
|
|
672
|
+
font-size: 0.95rem;
|
|
673
|
+
margin: 0.8rem 0 0;
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
.card {
|
|
677
|
+
background: radial-gradient(
|
|
678
|
+
circle at top left,
|
|
679
|
+
var(--accent-soft-bg) 0,
|
|
680
|
+
var(--bg) 45%
|
|
681
|
+
);
|
|
682
|
+
border: 1px solid rgba(var(--color-accent-rgb), 0.7);
|
|
683
|
+
border-radius: var(--radius-xl);
|
|
684
|
+
box-shadow: var(--shadow-soft);
|
|
685
|
+
overflow: hidden;
|
|
686
|
+
padding: 1.75rem 1.5rem;
|
|
687
|
+
position: relative;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
.card::before {
|
|
691
|
+
content: "";
|
|
692
|
+
position: absolute;
|
|
693
|
+
inset: -40%;
|
|
694
|
+
background:
|
|
695
|
+
radial-gradient(
|
|
696
|
+
circle at 0 0,
|
|
697
|
+
rgba(var(--color-accent-rgb), 0.16),
|
|
698
|
+
transparent 60%
|
|
699
|
+
),
|
|
700
|
+
radial-gradient(
|
|
701
|
+
circle at 100% 0,
|
|
702
|
+
rgba(59, 130, 246, 0.2),
|
|
703
|
+
transparent 65%
|
|
704
|
+
);
|
|
705
|
+
opacity: 0.9;
|
|
706
|
+
pointer-events: none;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
.card > * {
|
|
710
|
+
position: relative;
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
.card-message {
|
|
714
|
+
color: var(--text);
|
|
715
|
+
font-size: 1.25rem;
|
|
716
|
+
margin: 0;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
.card-meta {
|
|
720
|
+
color: var(--text-soft);
|
|
721
|
+
font-size: 0.85rem;
|
|
722
|
+
margin: 0.6rem 0 0;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
.section {
|
|
726
|
+
background: rgba(var(--color-code-bg-rgb), 0.9);
|
|
727
|
+
border: 1px solid var(--border-subtle);
|
|
728
|
+
border-radius: var(--radius-lg);
|
|
729
|
+
margin-top: 2rem;
|
|
730
|
+
padding: 1.6rem 1.5rem;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
.section-title {
|
|
734
|
+
color: rgb(var(--color-app-title-rgb));
|
|
735
|
+
font-size: 1.1rem;
|
|
736
|
+
margin: 0 0 0.75rem;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
.list {
|
|
740
|
+
color: var(--text-muted);
|
|
741
|
+
font-size: 0.95rem;
|
|
742
|
+
line-height: 1.8;
|
|
743
|
+
margin: 0;
|
|
744
|
+
padding-left: 1.1rem;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
.tip {
|
|
748
|
+
background: rgba(var(--color-tip-bg-rgb), 0.95);
|
|
749
|
+
border: 1px solid rgba(var(--color-tip-border-rgb), 0.9);
|
|
750
|
+
border-radius: 10px;
|
|
751
|
+
color: var(--text);
|
|
752
|
+
font-size: 0.9rem;
|
|
753
|
+
line-height: 1.6;
|
|
754
|
+
margin-top: 1.6rem;
|
|
755
|
+
padding: 1.1rem 1.3rem 1.25rem;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
.tip p {
|
|
759
|
+
margin: 0 0 0.6rem;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
.tip p:last-child {
|
|
763
|
+
margin-bottom: 0;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
.app-footer {
|
|
767
|
+
border-top: 1px solid rgba(var(--color-footer-border-rgb), 0.7);
|
|
768
|
+
color: var(--text-soft);
|
|
769
|
+
font-size: 0.85rem;
|
|
770
|
+
margin-top: 3rem;
|
|
771
|
+
padding-top: 1.4rem;
|
|
772
|
+
text-align: center;
|
|
773
|
+
}`;
|
|
774
|
+
}
|
|
775
|
+
function generateViteEnv() {
|
|
776
|
+
return `/// <reference types="vite/client" />
|
|
777
|
+
`;
|
|
778
|
+
}
|
|
779
|
+
function generateEntryClient() {
|
|
780
|
+
return `import { hydrateApp } from '@taujs/react';
|
|
781
|
+
import { App } from './App';
|
|
782
|
+
|
|
783
|
+
hydrateApp({
|
|
784
|
+
appComponent: <App />,
|
|
785
|
+
rootElementId: 'root',
|
|
786
|
+
enableDebug: import.meta.env.DEV,
|
|
787
|
+
});
|
|
788
|
+
`;
|
|
789
|
+
}
|
|
790
|
+
function generateEntryServer() {
|
|
791
|
+
return `import { createRenderer } from '@taujs/react';
|
|
792
|
+
import { App } from './App';
|
|
793
|
+
|
|
794
|
+
export const { renderSSR, renderStream } = createRenderer({
|
|
795
|
+
appComponent: () => <App />,
|
|
796
|
+
headContent: ({ data }) => \`
|
|
797
|
+
<meta charset="UTF-8">
|
|
798
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
799
|
+
<meta name="description" content="A \u03C4js template application">
|
|
800
|
+
<title>\${data?.message || "\u03C4js - Composing systems, not just apps"}</title>
|
|
801
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml"/>
|
|
802
|
+
\`,
|
|
803
|
+
enableDebug: process.env.NODE_ENV === "development",
|
|
804
|
+
});
|
|
805
|
+
`;
|
|
806
|
+
}
|
|
807
|
+
function generateServerIndex() {
|
|
808
|
+
return `import { createServer } from '@taujs/server';
|
|
809
|
+
import config from '../../taujs.config.ts';
|
|
810
|
+
import { serviceRegistry } from './services/registry.ts';
|
|
811
|
+
|
|
812
|
+
const { app, net } = await createServer({
|
|
813
|
+
config,
|
|
814
|
+
serviceRegistry,
|
|
815
|
+
clientRoot: './src/client',
|
|
816
|
+
debug: !!process.env.DEBUG,
|
|
817
|
+
});
|
|
818
|
+
|
|
819
|
+
if (app) {
|
|
820
|
+
await app.listen({
|
|
821
|
+
host: net.host,
|
|
822
|
+
port: net.port,
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
`;
|
|
826
|
+
}
|
|
827
|
+
function generateServiceRegistry() {
|
|
828
|
+
return `import { defineServiceRegistry } from '@taujs/server/config';
|
|
829
|
+
import { exampleService } from './example.service.ts';
|
|
830
|
+
|
|
831
|
+
export const serviceRegistry = defineServiceRegistry({
|
|
832
|
+
example: exampleService,
|
|
833
|
+
});
|
|
834
|
+
|
|
835
|
+
export type ServiceRegistry = typeof serviceRegistry;
|
|
836
|
+
`;
|
|
837
|
+
}
|
|
838
|
+
function generateServiceTypesAugmentation() {
|
|
839
|
+
return `import type { RegistryCaller } from '@taujs/server/config';
|
|
840
|
+
import type { serviceRegistry } from './registry';
|
|
841
|
+
|
|
842
|
+
declare module '@taujs/server/config' {
|
|
843
|
+
interface ServiceContext {
|
|
844
|
+
call: RegistryCaller<typeof serviceRegistry>;
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
`;
|
|
848
|
+
}
|
|
849
|
+
function generateExampleService() {
|
|
850
|
+
return `import { defineService } from '@taujs/server/config';
|
|
851
|
+
|
|
852
|
+
export const exampleService = defineService({
|
|
853
|
+
async greet(params: { name: string }) {
|
|
854
|
+
// Simulate async operation
|
|
855
|
+
await new Promise((resolve) => setTimeout(resolve, 750));
|
|
856
|
+
|
|
857
|
+
const modeDescription =
|
|
858
|
+
params.name === 'Streaming'
|
|
859
|
+
? 'via service descriptors.'
|
|
860
|
+
: 'via direct ctx.call.';
|
|
861
|
+
|
|
862
|
+
return {
|
|
863
|
+
message: \`Hello, \${params.name}. Response provided by a \u03C4js service \${modeDescription}\`,
|
|
864
|
+
timestamp: new Date().toISOString(),
|
|
865
|
+
};
|
|
866
|
+
},
|
|
867
|
+
|
|
868
|
+
async getData(params: { id: string }) {
|
|
869
|
+
return {
|
|
870
|
+
id: params.id,
|
|
871
|
+
data: 'Example data from service',
|
|
872
|
+
timestamp: new Date().toISOString(),
|
|
873
|
+
};
|
|
874
|
+
},
|
|
875
|
+
});
|
|
876
|
+
`;
|
|
877
|
+
}
|
|
878
|
+
function generateFavicon() {
|
|
879
|
+
return `<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
|
|
880
|
+
<g transform="matrix(1.203376054763794, 0, 0, 1.203376054763794, -47.249202728271484, -58.526153564453125)">
|
|
881
|
+
<ellipse style="stroke: rgb(0, 0, 0); fill: rgb(255, 250, 250);" cx="245.728" cy="256.598" rx="171.553" ry="171.553"/>
|
|
882
|
+
<path d="M 221.7 53.324 C 210 55.024 199.4 57.324 186.1 61.424 C 157.3 70.124 136.8 80.824 114.2 99.024 C 41.1 157.824 18.8 260.524 60.7 345.424 C 67.2 358.624 83.7 382.824 94.7 395.124 C 107.2 409.224 129.3 426.424 147.7 436.424 C 162.7 444.624 187.8 453.624 205.9 457.324 C 226.8 461.624 261.4 461.824 282.7 457.824 C 315.4 451.624 353.3 434.324 375.7 415.424 C 385.3 407.424 399.8 392.224 403.3 386.724 C 404.3 385.124 406.7 381.924 408.7 379.724 C 415.4 371.824 418.7 367.524 419.9 364.624 C 420.6 363.124 422.8 359.324 424.8 356.324 C 428.3 351.024 436.7 333.524 438.2 328.324 C 438.6 326.924 440 323.924 441.3 321.724 C 444.5 316.324 450.2 291.424 451.7 276.824 C 453.4 260.624 452.5 231.724 449.9 218.824 C 444.9 194.024 436.6 172.424 424.6 152.524 C 408 125.224 387.6 103.924 361.5 86.424 C 339.6 71.824 308.9 59.824 280.2 54.724 C 270.6 52.924 231 52.024 221.7 53.324 Z M 271.2 98.324 C 296.7 101.824 323.2 112.324 344.2 127.124 C 352.8 133.224 374.6 154.424 381.4 163.324 C 391 175.924 400.4 197.524 406.4 220.824 C 410.1 235.624 410.2 236.124 410.2 254.324 C 410.1 275.524 408.6 285.624 403.1 302.324 C 392.6 333.724 374.7 359.324 347.2 382.124 C 326.6 399.124 295.4 412.124 266.7 415.524 C 255.1 416.824 229.3 416.024 217.8 413.924 C 179.9 406.924 146.7 388.924 123.2 362.524 C 103.1 339.924 89.2 312.024 83.6 283.024 C 78.9 259.124 81.6 227.024 90.2 202.024 C 92.7 195.024 95.3 188.324 96.1 187.024 C 97 185.824 98.3 182.924 99.1 180.724 C 102.8 170.224 122.6 145.824 135.2 136.424 C 153.1 123.024 158.5 119.524 169.2 114.324 C 190.2 104.124 207.1 99.424 230.7 97.324 C 241.7 96.324 259.7 96.824 271.2 98.324 Z"/>
|
|
883
|
+
<path d="M 278.7 156.424 C 256.4 156.724 222.2 156.824 202.7 156.524 C 160.8 155.924 164.4 155.024 149.6 169.424 C 138.6 180.324 125.7 197.124 125.7 200.824 C 125.7 201.124 148 201.224 175.2 201.124 L 224.7 200.824 L 224.4 292.824 L 224.2 384.724 L 237.2 385.124 C 244.4 385.324 253.9 385.224 258.5 384.824 L 266.7 384.124 L 266.7 292.424 L 266.7 200.724 L 316.2 200.824 C 373.4 200.824 367.8 202.424 359.5 188.324 C 351.3 174.424 343.7 164.524 338.8 161.324 C 333.8 157.924 325.7 155.224 321.8 155.524 C 320.4 155.624 301 156.024 278.7 156.424 Z"/>
|
|
884
|
+
<path d="M 113.7 249.324 C 113.7 256.724 113.4 267.124 113.1 272.324 L 112.4 281.824 L 131.5 281.524 L 150.5 281.224 L 151.2 287.424 C 151.9 293.624 151.1 334.524 150.1 339.524 C 149.4 343.124 154.1 348.224 166.6 357.624 C 175.8 364.524 190.4 373.324 192.7 373.324 C 193.5 373.324 193.7 354.224 193.5 304.824 L 193.2 236.324 L 153.4 236.024 L 113.7 235.824 L 113.7 249.324 Z"/>
|
|
885
|
+
<path d="M 298.2 281.224 C 298.2 347.124 298.6 373.324 299.6 373.324 C 300.8 373.324 317.1 363.324 322.3 359.324 C 324.8 357.424 330 352.824 333.8 349.124 L 340.8 342.324 L 340.7 337.124 C 340.6 334.224 340.6 320.424 340.6 306.524 L 340.7 281.324 L 359.7 281.324 L 378.7 281.324 L 378.6 260.024 C 378.6 248.424 378.3 238.124 377.9 237.324 C 377.3 236.024 371.8 235.824 337.7 235.724 L 298.2 235.624 L 298.2 281.224 Z"/>
|
|
886
|
+
</g>
|
|
887
|
+
</svg>
|
|
888
|
+
`;
|
|
889
|
+
}
|
|
890
|
+
main().catch((error) => {
|
|
891
|
+
console.error(pc.red("\n\u2716 Error creating project:"), error);
|
|
892
|
+
process.exit(1);
|
|
893
|
+
});
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@taujs/create-taujs",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Scaffold a new τjs application",
|
|
5
|
+
"author": "Aoede <taujs@aoede.uk.net> (https://www.aoede.uk.net)",
|
|
6
|
+
"homepage": "https://taujs.dev/",
|
|
7
|
+
"license": "MIT",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"bin": {
|
|
10
|
+
"create-taujs": "dist/index.js"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dist"
|
|
14
|
+
],
|
|
15
|
+
"scripts": {
|
|
16
|
+
"build": "tsup",
|
|
17
|
+
"ci": "npm run build && npm run lint",
|
|
18
|
+
"lint": "tsc",
|
|
19
|
+
"dev": "tsup --watch",
|
|
20
|
+
"prepublishOnly": "npm run ci",
|
|
21
|
+
"local-release": "npm run ci && changeset version && changeset publish"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@changesets/cli": "^2.29.8",
|
|
25
|
+
"fs-extra": "^11.2.0",
|
|
26
|
+
"picocolors": "^1.0.0",
|
|
27
|
+
"prompts": "^2.4.2"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/fs-extra": "^11.0.4",
|
|
31
|
+
"@types/node": "^20.11.0",
|
|
32
|
+
"@types/prompts": "^2.4.9",
|
|
33
|
+
"tsup": "^8.0.0",
|
|
34
|
+
"typescript": "^5.3.0"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"taujs",
|
|
38
|
+
"create-taujs",
|
|
39
|
+
"scaffold",
|
|
40
|
+
"template",
|
|
41
|
+
"react",
|
|
42
|
+
"ssr",
|
|
43
|
+
"fastify",
|
|
44
|
+
"typescript"
|
|
45
|
+
],
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/aoede3/create-taujs.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/aoede3/create-taujs/issues"
|
|
52
|
+
}
|
|
53
|
+
}
|