@taujs/create-taujs 0.3.1 → 0.4.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/dist/index.js +209 -24
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -45,11 +45,15 @@ var PACKAGE_MANAGERS = {
|
|
|
45
45
|
pnpm: "pnpm install",
|
|
46
46
|
yarn: "yarn install"
|
|
47
47
|
};
|
|
48
|
-
var FRAMEWORKS = ["react", "vue"];
|
|
48
|
+
var FRAMEWORKS = ["react", "vue", "solid"];
|
|
49
|
+
var PACKAGE_MANAGER_NAMES = Object.keys(PACKAGE_MANAGERS);
|
|
49
50
|
function parseArgs() {
|
|
50
51
|
const rawArgs = process.argv.slice(2);
|
|
51
52
|
let projectName;
|
|
52
53
|
let framework;
|
|
54
|
+
let packageManager;
|
|
55
|
+
let sawInstall = false;
|
|
56
|
+
let sawNoInstall = false;
|
|
53
57
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
54
58
|
const arg = rawArgs[i];
|
|
55
59
|
if (arg === "--framework") {
|
|
@@ -60,12 +64,37 @@ function parseArgs() {
|
|
|
60
64
|
framework = arg.slice("--framework=".length);
|
|
61
65
|
continue;
|
|
62
66
|
}
|
|
67
|
+
if (arg === "--package-manager") {
|
|
68
|
+
packageManager = rawArgs[++i];
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
if (arg.startsWith("--package-manager=")) {
|
|
72
|
+
packageManager = arg.slice("--package-manager=".length);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
if (arg === "--install") {
|
|
76
|
+
sawInstall = true;
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if (arg === "--no-install") {
|
|
80
|
+
sawNoInstall = true;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
63
83
|
if (!arg.startsWith("-") && !projectName) {
|
|
64
84
|
projectName = arg;
|
|
65
85
|
continue;
|
|
66
86
|
}
|
|
67
87
|
}
|
|
68
|
-
return {
|
|
88
|
+
return {
|
|
89
|
+
projectName,
|
|
90
|
+
framework,
|
|
91
|
+
packageManager,
|
|
92
|
+
install: sawInstall && !sawNoInstall ? true : sawNoInstall && !sawInstall ? false : void 0,
|
|
93
|
+
installConflict: sawInstall && sawNoInstall
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function validatePackageManager(value) {
|
|
97
|
+
return PACKAGE_MANAGER_NAMES.includes(value) ? true : `Package manager must be one of: ${PACKAGE_MANAGER_NAMES.join(", ")}`;
|
|
69
98
|
}
|
|
70
99
|
function validateProjectName(value) {
|
|
71
100
|
if (!value) return "Project name is required";
|
|
@@ -79,7 +108,19 @@ function validateFramework(value) {
|
|
|
79
108
|
}
|
|
80
109
|
async function main() {
|
|
81
110
|
console.log(pc.cyan("\nWelcome to \u03C4js (taujs)\n"));
|
|
82
|
-
const { projectName: argName, framework: argFramework } = parseArgs();
|
|
111
|
+
const { projectName: argName, framework: argFramework, packageManager: argPackageManager, install: argInstall, installConflict } = parseArgs();
|
|
112
|
+
if (installConflict) {
|
|
113
|
+
console.log(pc.red("\n\u2716 --install and --no-install are mutually exclusive"));
|
|
114
|
+
process.exit(1);
|
|
115
|
+
}
|
|
116
|
+
if (argPackageManager) {
|
|
117
|
+
const res = validatePackageManager(argPackageManager);
|
|
118
|
+
if (res !== true) {
|
|
119
|
+
console.log(pc.red(`
|
|
120
|
+
\u2716 Invalid package manager "${argPackageManager}": ${res}`));
|
|
121
|
+
process.exit(1);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
83
124
|
if (argName) {
|
|
84
125
|
const res = validateProjectName(argName);
|
|
85
126
|
if (res !== true) {
|
|
@@ -110,12 +151,13 @@ async function main() {
|
|
|
110
151
|
message: "Framework:",
|
|
111
152
|
choices: [
|
|
112
153
|
{ title: "React", value: "react" },
|
|
113
|
-
{ title: "Vue", value: "vue" }
|
|
154
|
+
{ title: "Vue", value: "vue" },
|
|
155
|
+
{ title: "Solid", value: "solid" }
|
|
114
156
|
],
|
|
115
157
|
initial: 0
|
|
116
158
|
},
|
|
117
159
|
{
|
|
118
|
-
type: "select",
|
|
160
|
+
type: argPackageManager ? null : "select",
|
|
119
161
|
name: "packageManager",
|
|
120
162
|
message: "Package manager:",
|
|
121
163
|
choices: [
|
|
@@ -126,7 +168,7 @@ async function main() {
|
|
|
126
168
|
initial: 0
|
|
127
169
|
},
|
|
128
170
|
{
|
|
129
|
-
type: "confirm",
|
|
171
|
+
type: argInstall === void 0 ? "confirm" : null,
|
|
130
172
|
name: "installDeps",
|
|
131
173
|
message: "Install dependencies now?",
|
|
132
174
|
initial: true
|
|
@@ -158,8 +200,8 @@ async function main() {
|
|
|
158
200
|
}
|
|
159
201
|
const config = {
|
|
160
202
|
projectName,
|
|
161
|
-
packageManager: answers.packageManager,
|
|
162
|
-
installDeps: answers.installDeps,
|
|
203
|
+
packageManager: argPackageManager ?? answers.packageManager,
|
|
204
|
+
installDeps: argInstall ?? answers.installDeps,
|
|
163
205
|
framework
|
|
164
206
|
};
|
|
165
207
|
await createProject(config);
|
|
@@ -236,9 +278,19 @@ function planFiles(config) {
|
|
|
236
278
|
{ path: "src/server/services/registry.ts", content: generateServiceRegistry() },
|
|
237
279
|
{ path: "src/server/services/example.service.ts", content: generateExampleService() },
|
|
238
280
|
{ path: "src/server/types.d.ts", content: generateServiceTypesAugmentation() },
|
|
239
|
-
{ path: "src/client/public/favicon.svg", content: generateFavicon() }
|
|
281
|
+
{ path: "src/client/public/favicon.svg", content: generateFavicon() },
|
|
282
|
+
// Solid's managed compiler owns a DISJOINT tsconfig project: it must claim the client TSX and
|
|
283
|
+
// nothing else. Pointing it at the root tsconfig would make it claim `src/server/**` too, which
|
|
284
|
+
// is not Solid TSX and is compiled by the server toolchain.
|
|
285
|
+
...framework === "solid" ? [{ path: "tsconfig.solid.json", json: generateSolidCompilerTsConfig() }] : []
|
|
240
286
|
];
|
|
241
|
-
const client = framework === "
|
|
287
|
+
const client = framework === "solid" ? [
|
|
288
|
+
{ path: "src/client/App.tsx", content: generateAppComponentSolid() },
|
|
289
|
+
{ path: "src/client/renderId.ts", content: generateSolidRenderId() },
|
|
290
|
+
{ path: "src/client/entry-client.tsx", content: generateEntryClientSolid() },
|
|
291
|
+
{ path: "src/client/entry-server.tsx", content: generateEntryServerSolid() },
|
|
292
|
+
{ path: "src/client/vite-env.d.ts", content: generateViteEnv() }
|
|
293
|
+
] : framework === "vue" ? [
|
|
242
294
|
{ path: "src/client/App.vue", content: generateAppVue() },
|
|
243
295
|
{ path: "src/client/HomePage.vue", content: generateHomePageVue() },
|
|
244
296
|
{ path: "src/client/StreamingPage.vue", content: generateStreamingPageVue() },
|
|
@@ -273,10 +325,10 @@ function generatePackageJson(projectName, framework) {
|
|
|
273
325
|
type: "module",
|
|
274
326
|
scripts: {
|
|
275
327
|
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",
|
|
328
|
+
"build:client": "cross-env NODE_ENV=production tsx build.ts",
|
|
329
|
+
"build:entry-server": "cross-env NODE_ENV=production BUILD_MODE=ssr tsx build.ts",
|
|
278
330
|
"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",
|
|
331
|
+
build: "cross-env NODE_ENV=production tsx build.ts && cross-env NODE_ENV=production 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
332
|
start: "cross-env NODE_ENV=production node dist/server/index.js",
|
|
281
333
|
lint: "vue-tsc --noEmit"
|
|
282
334
|
},
|
|
@@ -292,6 +344,9 @@ function generatePackageJson(projectName, framework) {
|
|
|
292
344
|
"@types/node": "^22.10.5",
|
|
293
345
|
"@vitejs/plugin-vue": "^6.0.0",
|
|
294
346
|
"cross-env": "^7.0.3",
|
|
347
|
+
// `build:server` invokes the esbuild BINARY directly, so it must be a declared dependency
|
|
348
|
+
// of the generated project - it is not inherited from vite's own copy.
|
|
349
|
+
esbuild: "^0.25.0",
|
|
295
350
|
tsx: "^4.19.3",
|
|
296
351
|
typescript: "^5.7.3",
|
|
297
352
|
vite: "^7.1.11",
|
|
@@ -299,6 +354,43 @@ function generatePackageJson(projectName, framework) {
|
|
|
299
354
|
}
|
|
300
355
|
};
|
|
301
356
|
}
|
|
357
|
+
if (framework === "solid") {
|
|
358
|
+
return {
|
|
359
|
+
name: projectName,
|
|
360
|
+
version: "0.1.0",
|
|
361
|
+
private: true,
|
|
362
|
+
type: "module",
|
|
363
|
+
scripts: {
|
|
364
|
+
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",
|
|
365
|
+
"build:client": "cross-env NODE_ENV=production tsx build.ts",
|
|
366
|
+
"build:entry-server": "cross-env NODE_ENV=production BUILD_MODE=ssr tsx build.ts",
|
|
367
|
+
"build:server": "esbuild src/server/index.ts --bundle --platform=node --format=esm --outfile=dist/server/index.js --external:fastify --external:@taujs/server --external:@taujs/solid",
|
|
368
|
+
build: "cross-env NODE_ENV=production tsx build.ts && cross-env NODE_ENV=production 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/solid",
|
|
369
|
+
start: "cross-env NODE_ENV=production node dist/server/index.js",
|
|
370
|
+
lint: "tsc --noEmit"
|
|
371
|
+
},
|
|
372
|
+
dependencies: {
|
|
373
|
+
"@taujs/server": "latest",
|
|
374
|
+
"@taujs/solid": "latest",
|
|
375
|
+
fastify: "^5.2.0",
|
|
376
|
+
"solid-js": "^1.9.0"
|
|
377
|
+
},
|
|
378
|
+
devDependencies: {
|
|
379
|
+
"@taujs/mcp": "latest",
|
|
380
|
+
"@types/node": "^22.10.5",
|
|
381
|
+
"cross-env": "^7.0.3",
|
|
382
|
+
// `build:server` invokes the esbuild BINARY directly, so it must be a declared dependency
|
|
383
|
+
// of the generated project - it is not inherited from vite's own copy.
|
|
384
|
+
esbuild: "^0.25.0",
|
|
385
|
+
tsx: "^4.19.3",
|
|
386
|
+
typescript: "^5.7.3",
|
|
387
|
+
vite: "^7.1.11",
|
|
388
|
+
// The managed compiler instantiates this internally with `ssr: true` forced; the app never
|
|
389
|
+
// adds it to `plugins` itself.
|
|
390
|
+
"vite-plugin-solid": "^2.11.0"
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
}
|
|
302
394
|
return {
|
|
303
395
|
name: projectName,
|
|
304
396
|
version: "0.1.0",
|
|
@@ -306,10 +398,10 @@ function generatePackageJson(projectName, framework) {
|
|
|
306
398
|
type: "module",
|
|
307
399
|
scripts: {
|
|
308
400
|
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",
|
|
309
|
-
"build:client": "tsx build.ts",
|
|
310
|
-
"build:entry-server": "cross-env BUILD_MODE=ssr tsx build.ts",
|
|
401
|
+
"build:client": "cross-env NODE_ENV=production tsx build.ts",
|
|
402
|
+
"build:entry-server": "cross-env NODE_ENV=production BUILD_MODE=ssr tsx build.ts",
|
|
311
403
|
"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",
|
|
312
|
-
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/react",
|
|
404
|
+
build: "cross-env NODE_ENV=production tsx build.ts && cross-env NODE_ENV=production 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/react",
|
|
313
405
|
start: "cross-env NODE_ENV=production node dist/server/index.js",
|
|
314
406
|
lint: "tsc --noEmit"
|
|
315
407
|
},
|
|
@@ -327,6 +419,9 @@ function generatePackageJson(projectName, framework) {
|
|
|
327
419
|
"@types/react-dom": "^19.0.2",
|
|
328
420
|
"@vitejs/plugin-react": "^4.6.0",
|
|
329
421
|
"cross-env": "^7.0.3",
|
|
422
|
+
// `build:server` invokes the esbuild BINARY directly, so it must be a declared dependency
|
|
423
|
+
// of the generated project - it is not inherited from vite's own copy.
|
|
424
|
+
esbuild: "^0.25.0",
|
|
330
425
|
tsx: "^4.19.3",
|
|
331
426
|
typescript: "^5.7.3",
|
|
332
427
|
vite: "^7.1.11"
|
|
@@ -351,8 +446,10 @@ function generateTsConfig(framework) {
|
|
|
351
446
|
target: "ES2022",
|
|
352
447
|
module: "ESNext",
|
|
353
448
|
lib: ["ES2022", "DOM", "DOM.Iterable"],
|
|
354
|
-
// Vue SFCs are typed by vue-tsc; React needs the automatic JSX runtime
|
|
449
|
+
// Vue SFCs are typed by vue-tsc; React needs the automatic JSX runtime; Solid PRESERVES JSX
|
|
450
|
+
// for its own Babel transform and types it through `solid-js`.
|
|
355
451
|
...framework === "react" ? { jsx: "react-jsx" } : {},
|
|
452
|
+
...framework === "solid" ? { jsx: "preserve", jsxImportSource: "solid-js" } : {},
|
|
356
453
|
moduleResolution: "bundler",
|
|
357
454
|
resolveJsonModule: true,
|
|
358
455
|
allowImportingTsExtensions: true,
|
|
@@ -378,11 +475,15 @@ function generateServerTsConfig() {
|
|
|
378
475
|
};
|
|
379
476
|
}
|
|
380
477
|
function generateTaujsConfig(framework) {
|
|
381
|
-
const
|
|
382
|
-
import {
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
478
|
+
const rendererImport = framework === "vue" ? `
|
|
479
|
+
import { vueRenderer } from '@taujs/vue/renderer';` : framework === "solid" ? `
|
|
480
|
+
import { solidRenderer } from '@taujs/solid/renderer';` : `
|
|
481
|
+
import { reactRenderer } from '@taujs/react/renderer';`;
|
|
482
|
+
const rendererLine = framework === "vue" ? `
|
|
483
|
+
renderer: vueRenderer(),` : framework === "solid" ? `
|
|
484
|
+
renderer: solidRenderer({ project: './tsconfig.solid.json' }),` : `
|
|
485
|
+
renderer: reactRenderer({ project: './tsconfig.json' }),`;
|
|
486
|
+
return `import { defineConfig } from '@taujs/server/config';${rendererImport}
|
|
386
487
|
|
|
387
488
|
export default defineConfig({
|
|
388
489
|
server: {
|
|
@@ -390,10 +491,16 @@ export default defineConfig({
|
|
|
390
491
|
host: 'localhost',
|
|
391
492
|
hmrPort: 5174,
|
|
392
493
|
},
|
|
494
|
+
// Declared Vite surface - applied to dev and build. See https://taujs.dev/reference/taujs-config/#vite-configuration
|
|
495
|
+
// vite: {
|
|
496
|
+
// define: { __APP_VERSION__: JSON.stringify('0.0.0') },
|
|
497
|
+
// plugins: [],
|
|
498
|
+
// },
|
|
499
|
+
// alias: { '@components': './src/client/shared/components' },
|
|
393
500
|
apps: [
|
|
394
501
|
{
|
|
395
502
|
appId: 'main',
|
|
396
|
-
entryPoint: '',${
|
|
503
|
+
entryPoint: '',${rendererLine}
|
|
397
504
|
routes: [
|
|
398
505
|
{
|
|
399
506
|
path: '/',
|
|
@@ -1065,6 +1172,82 @@ export const { renderSSR, renderStream } = createRenderer({
|
|
|
1065
1172
|
});
|
|
1066
1173
|
`;
|
|
1067
1174
|
}
|
|
1175
|
+
function generateSolidCompilerTsConfig() {
|
|
1176
|
+
return {
|
|
1177
|
+
compilerOptions: {
|
|
1178
|
+
jsx: "preserve",
|
|
1179
|
+
jsxImportSource: "solid-js"
|
|
1180
|
+
},
|
|
1181
|
+
include: ["src/client/**/*.tsx"]
|
|
1182
|
+
};
|
|
1183
|
+
}
|
|
1184
|
+
function generateSolidRenderId() {
|
|
1185
|
+
return `/**
|
|
1186
|
+
* The renderId is a SHARED constant: the server renders Solid's markers and serialised data under
|
|
1187
|
+
* this namespace, and the client must hydrate under the SAME one. It is imported by BOTH entries
|
|
1188
|
+
* on purpose - a literal duplicated in two files is a hydration bug waiting to happen.
|
|
1189
|
+
*/
|
|
1190
|
+
export const RENDER_ID = 'app';
|
|
1191
|
+
`;
|
|
1192
|
+
}
|
|
1193
|
+
function generateAppComponentSolid() {
|
|
1194
|
+
return `import { Show } from 'solid-js';
|
|
1195
|
+
import { useSSRStore } from '@taujs/solid';
|
|
1196
|
+
|
|
1197
|
+
type RouteData = { message?: string };
|
|
1198
|
+
|
|
1199
|
+
export function App() {
|
|
1200
|
+
// Route data arrives through the store, which the renderer provides. On the server it is already
|
|
1201
|
+
// committed before the render begins; on the client it is seeded from window.__INITIAL_DATA__.
|
|
1202
|
+
const store = useSSRStore<RouteData>();
|
|
1203
|
+
|
|
1204
|
+
return (
|
|
1205
|
+
<main>
|
|
1206
|
+
<h1>\u03C4js + Solid</h1>
|
|
1207
|
+
<Show when={store.data().message} fallback={<p>No route data.</p>}>
|
|
1208
|
+
<p>{store.data().message}</p>
|
|
1209
|
+
</Show>
|
|
1210
|
+
</main>
|
|
1211
|
+
);
|
|
1212
|
+
}
|
|
1213
|
+
`;
|
|
1214
|
+
}
|
|
1215
|
+
function generateEntryClientSolid() {
|
|
1216
|
+
return `import { hydrateApp } from '@taujs/solid';
|
|
1217
|
+
|
|
1218
|
+
import { App } from './App';
|
|
1219
|
+
import { RENDER_ID } from './renderId';
|
|
1220
|
+
|
|
1221
|
+
hydrateApp({
|
|
1222
|
+
app: () => <App />,
|
|
1223
|
+
renderId: RENDER_ID,
|
|
1224
|
+
rootElementId: 'root',
|
|
1225
|
+
onHydrationError: (error) => {
|
|
1226
|
+
console.error('Hydration failed:', error);
|
|
1227
|
+
},
|
|
1228
|
+
});
|
|
1229
|
+
`;
|
|
1230
|
+
}
|
|
1231
|
+
function generateEntryServerSolid() {
|
|
1232
|
+
return `import { createRenderer } from '@taujs/solid';
|
|
1233
|
+
|
|
1234
|
+
import { App } from './App';
|
|
1235
|
+
import { RENDER_ID } from './renderId';
|
|
1236
|
+
|
|
1237
|
+
export const { renderSSR, renderStream } = createRenderer({
|
|
1238
|
+
appComponent: () => <App />,
|
|
1239
|
+
renderId: RENDER_ID,
|
|
1240
|
+
headContent: ({ data, meta }) => \`
|
|
1241
|
+
<title>\${meta?.title || "\u03C4js - Composing systems, not just apps"}</title>
|
|
1242
|
+
<meta name="description" content="\${
|
|
1243
|
+
meta?.description ||
|
|
1244
|
+
data?.message ||
|
|
1245
|
+
"\u03C4js - Composing systems, not just apps"
|
|
1246
|
+
}">
|
|
1247
|
+
\`,
|
|
1248
|
+
});
|
|
1249
|
+
`;
|
|
1250
|
+
}
|
|
1068
1251
|
function generateServerIndex() {
|
|
1069
1252
|
return `import { createServer } from '@taujs/server';
|
|
1070
1253
|
import config from '../../taujs.config.ts';
|
|
@@ -1098,7 +1281,9 @@ export type ServiceRegistry = typeof serviceRegistry;
|
|
|
1098
1281
|
`;
|
|
1099
1282
|
}
|
|
1100
1283
|
function generateServiceTypesAugmentation() {
|
|
1101
|
-
return `
|
|
1284
|
+
return `import '@taujs/server/config';
|
|
1285
|
+
|
|
1286
|
+
declare module '@taujs/server/config' {
|
|
1102
1287
|
interface ServiceContext {
|
|
1103
1288
|
tenantId?: string;
|
|
1104
1289
|
}
|