@ubean/cli 0.1.8 → 0.1.9

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 CHANGED
@@ -1,4 +1,4 @@
1
- import { S as createFsOps, a as scaffold, i as recoverScaffold, n as listScaffoldableFiles, r as pageCommand, t as deleteScaffold, v as renderTemplate } from "./page-Cmp7s9l2.js";
1
+ import { E as createFsOps, S as renderTemplate, a as scaffold, c as scaffoldStarterTemplate, i as recoverScaffold, l as scaffoldUnifyTemplate, n as listScaffoldableFiles, o as scaffoldBlogTemplate, r as pageCommand, s as scaffoldMinimalTemplate, t as deleteScaffold } from "./page-VyP_7yLT.js";
2
2
  import { existsSync, mkdirSync, readFileSync } from "node:fs";
3
3
  import { extname, normalize } from "node:path";
4
4
  import { consola } from "consola";
@@ -847,13 +847,17 @@ SESSION_SECRET=your-session-secret
847
847
  //#region src/init.ts
848
848
  const logger$3 = consola.withTag("ubean-cli");
849
849
  const TEMPLATES = [
850
+ {
851
+ value: "unify",
852
+ label: "Unify (recommended, full-stack with islands/i18n/layouts/middleware)"
853
+ },
850
854
  {
851
855
  value: "minimal",
852
856
  label: "Minimal (just a hello world page)"
853
857
  },
854
858
  {
855
859
  value: "starter",
856
- label: "Starter (recommended, includes pages/api/layouts)"
860
+ label: "Starter (includes pages/api/layouts)"
857
861
  },
858
862
  {
859
863
  value: "blog",
@@ -934,559 +938,6 @@ async function confirm(question, defaultValue = true) {
934
938
  function isNonInteractive() {
935
939
  return !process.stdin.isTTY || process.env.CI !== void 0 || process.env.NONINTERACTIVE !== void 0;
936
940
  }
937
- const PACKAGE_JSON_TEMPLATE = `{
938
- "name": "{{name}}",
939
- "private": true,
940
- "type": "module",
941
- "scripts": {
942
- "dev": "ubean dev",
943
- "build": "ubean build",
944
- "preview": "ubean preview",
945
- "prepare": "ubean prepare",
946
- "typecheck": "vue-tsc --noEmit"
947
- },
948
- "dependencies": {
949
- "ubean": "latest",
950
- "vue": "^3.5.0"
951
- },
952
- "devDependencies": {
953
- "typescript": "^5.6.0",
954
- "vue-tsc": "^2.1.0"
955
- }
956
- }
957
- `;
958
- const TSCONFIG_TEMPLATE = `{
959
- "compilerOptions": {
960
- "target": "ESNext",
961
- "module": "ESNext",
962
- "moduleResolution": "Bundler",
963
- "strict": true,
964
- "jsx": "preserve",
965
- "resolveJsonModule": true,
966
- "esModuleInterop": true,
967
- "skipLibCheck": true,
968
- "isolatedModules": true,
969
- "allowImportingTsExtensions": true,
970
- "noEmit": true,
971
- "lib": ["ESNext", "DOM", "DOM.Iterable"],
972
- "types": ["ubean/client"]
973
- },
974
- "include": ["src/**/*.ts", "src/**/*.vue", ".ubean/**/*.d.ts"],
975
- "exclude": ["node_modules", "dist"]
976
- }
977
- `;
978
- const UBEAN_CONFIG_TEMPLATE = `import { defineConfig } from 'ubean';
979
-
980
- export default defineConfig({
981
- srcDir: 'src',
982
- preset: '{{preset}}'
983
- });
984
- `;
985
- const APP_VUE_TEMPLATE = `<template>
986
- <div id="app">
987
- <RouterView />
988
- </div>
989
- </template>
990
-
991
- <script setup lang="ts">
992
- import { RouterView } from 'vue-router';
993
- <\/script>
994
-
995
- <style>
996
- * {
997
- margin: 0;
998
- padding: 0;
999
- box-sizing: border-box;
1000
- }
1001
-
1002
- body {
1003
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
1004
- }
1005
-
1006
- #app {
1007
- min-height: 100vh;
1008
- }
1009
- </style>
1010
- `;
1011
- const INDEX_PAGE_TEMPLATE = `<template>
1012
- <div class="home-page">
1013
- <h1>Welcome to ubean</h1>
1014
- <p>Your Vue meta framework is ready! 🚀</p>
1015
- <div class="links">
1016
- <RouterLink to="/about">About</RouterLink>
1017
- </div>
1018
- </div>
1019
- </template>
1020
-
1021
- <script setup lang="ts">
1022
- import { RouterLink } from 'vue-router';
1023
-
1024
- definePage({
1025
- meta: {
1026
- title: 'Home'
1027
- }
1028
- });
1029
- <\/script>
1030
-
1031
- <style scoped>
1032
- .home-page {
1033
- display: flex;
1034
- flex-direction: column;
1035
- align-items: center;
1036
- justify-content: center;
1037
- min-height: 100vh;
1038
- padding: 2rem;
1039
- text-align: center;
1040
- }
1041
-
1042
- h1 {
1043
- font-size: 3rem;
1044
- margin-bottom: 1rem;
1045
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1046
- -webkit-background-clip: text;
1047
- -webkit-text-fill-color: transparent;
1048
- background-clip: text;
1049
- }
1050
-
1051
- p {
1052
- color: #666;
1053
- font-size: 1.2rem;
1054
- margin-bottom: 2rem;
1055
- }
1056
-
1057
- .links {
1058
- display: flex;
1059
- gap: 1rem;
1060
- }
1061
-
1062
- a {
1063
- padding: 0.75rem 1.5rem;
1064
- border-radius: 8px;
1065
- background: #667eea;
1066
- color: white;
1067
- text-decoration: none;
1068
- font-weight: 500;
1069
- transition: all 0.2s;
1070
- }
1071
-
1072
- a:hover {
1073
- background: #5a67d8;
1074
- transform: translateY(-1px);
1075
- }
1076
- </style>
1077
- `;
1078
- const ABOUT_PAGE_TEMPLATE = `<template>
1079
- <div class="about-page">
1080
- <h1>About</h1>
1081
- <p>This page is built with ubean.</p>
1082
- <RouterLink to="/">Back to Home</RouterLink>
1083
- </div>
1084
- </template>
1085
-
1086
- <script setup lang="ts">
1087
- import { RouterLink } from 'vue-router';
1088
-
1089
- definePage({
1090
- meta: {
1091
- title: 'About'
1092
- }
1093
- });
1094
- <\/script>
1095
-
1096
- <style scoped>
1097
- .about-page {
1098
- max-width: 800px;
1099
- margin: 0 auto;
1100
- padding: 3rem 2rem;
1101
- }
1102
-
1103
- h1 {
1104
- margin-bottom: 1rem;
1105
- color: #333;
1106
- }
1107
-
1108
- p {
1109
- color: #666;
1110
- line-height: 1.6;
1111
- margin-bottom: 2rem;
1112
- }
1113
-
1114
- a {
1115
- color: #667eea;
1116
- text-decoration: none;
1117
- }
1118
-
1119
- a:hover {
1120
- text-decoration: underline;
1121
- }
1122
- </style>
1123
- `;
1124
- const HELLO_API_TEMPLATE = `import { defineHandler } from 'ubean';
1125
-
1126
- export const GET = defineHandler(c => {
1127
- return c.json({
1128
- message: 'Hello from ubean API!',
1129
- timestamp: Date.now()
1130
- });
1131
- });
1132
- `;
1133
- /**
1134
- * 类型化请求客户端模板 - 浏览器端
1135
- *
1136
- * 启动 dev server 后,ubean 会自动生成 .ubean/openapi.d.ts(包含项目所有 API 的 paths 类型)。
1137
- * 本文件将 paths 类型绑定到 createTypedClient,使浏览器端请求的路径、参数、请求体和返回值都获得类型安全。
1138
- *
1139
- * 使用方式:
1140
- * import { api } from '../request/client';
1141
- * const user = await api.get('/api/users/{id}', { params: { path: { id: 1 } } });
1142
- */
1143
- const REQUEST_CLIENT_TEMPLATE = `import { createRequest } from '@soybeanjs/fetch';
1144
- import { createTypedClient, toFlatTypedClient } from '@soybeanjs/fetch/openapi';
1145
- import type { paths } from '../../.ubean/openapi';
1146
-
1147
- /**
1148
- * 底层 HTTP 请求实例(@soybeanjs/fetch 封装)。
1149
- *
1150
- * api 和 flatApi 共用同一份 RequestInstance,共享 baseURL/timeout/headers/state 等。
1151
- * 调整配置时只需修改此处一处。
1152
- */
1153
- const request = createRequest({
1154
- // baseURL: '/api', // 按需设置 API 基础路径
1155
- // timeout: 10000,
1156
- });
1157
-
1158
- /**
1159
- * 浏览器端类型化 HTTP 客户端(抛异常模式)
1160
- *
1161
- * 路径、参数、请求体和返回值类型均从 OpenAPI schema 自动推断。
1162
- * 启动 dev server 后类型会自动更新(.ubean/openapi.d.ts)。
1163
- *
1164
- * 支持通过 responseType 配置不同的返回类型:
1165
- * - 'json' (默认): 返回解析后的 JSON 数据
1166
- * - 'blob': 返回 { file: Blob; filename: string; contentType: string }
1167
- * - 'text': 返回 string
1168
- * - 'arraybuffer': 返回 { file: ArrayBuffer; filename: string; contentType: string }
1169
- *
1170
- * @example
1171
- * import { api } from '../request/client';
1172
- *
1173
- * // JSON 请求(默认)
1174
- * const user = await api.get('/api/users/{id}', { pathParams: { id: 1 } });
1175
- *
1176
- * // 文件下载
1177
- * const file = await api.get('/api/export', { responseType: 'blob' });
1178
- * // file: { file: Blob; filename: string; contentType: string }
1179
- *
1180
- * // 文本
1181
- * const text = await api.get('/api/readme', { responseType: 'text' });
1182
- * // text: string
1183
- */
1184
- export const api = createTypedClient<paths>(request);
1185
-
1186
- /**
1187
- * 扁平模式类型化 HTTP 客户端(不抛异常,通过返回值判断)
1188
- *
1189
- * toFlatTypedClient 接收同一个 RequestInstance,内部通过 withResponse + try/catch
1190
- * 实现扁平化返回,与 api 共享 state/cache/auth。
1191
- *
1192
- * 返回 { data, error, response } — 成功时 error 为 null,失败时 data 为 null。
1193
- * 接口与 api 一致,同样支持 responseType。
1194
- *
1195
- * @example
1196
- * import { flatApi } from '../request/client';
1197
- *
1198
- * const { data, error } = await flatApi.get('/api/users/{id}', {
1199
- * pathParams: { id: 1 }
1200
- * });
1201
- * if (error) {
1202
- * console.error('Failed:', error.message);
1203
- * } else {
1204
- * console.log('User:', data);
1205
- * }
1206
- */
1207
- export const flatApi = toFlatTypedClient<paths>(request);
1208
- `;
1209
- /**
1210
- * 类型化请求客户端模板 - server 端内部调度
1211
- *
1212
- * 在 API 路由或 useData 的 fetcher 中使用,自动转发 cookie/authorization 等请求头。
1213
- * 与 client.ts 接口一致,但内部通过 createInternalAdapter + @soybeanjs/fetch 发起请求(进程内调度)。
1214
- *
1215
- * 使用方式:
1216
- * import { createServerApi } from '../request/internal';
1217
- * export const GET = defineHandler(async (c) => {
1218
- * const api = createServerApi(c);
1219
- * const user = await api.get('/api/users/{id}', { pathParams: { id: 1 } });
1220
- * return c.json(user);
1221
- * });
1222
- */
1223
- const REQUEST_INTERNAL_TEMPLATE = `import { createInternalAdapter } from 'ubean';
1224
- import { createRequest } from '@soybeanjs/fetch';
1225
- import { createTypedClient } from '@soybeanjs/fetch/openapi';
1226
- import type { paths } from '../../.ubean/openapi';
1227
-
1228
- /**
1229
- * server 端类型化内部 fetch
1230
- *
1231
- * 在 API 路由或 useData 的 fetcher 中使用,自动转发 cookie/authorization 等请求头。
1232
- * 与 client.ts 的 api 接口一致,但通过进程内调度发起请求(不发起新的网络请求)。
1233
- *
1234
- * @example
1235
- * // src/routes/api/posts.ts
1236
- * import { defineHandler } from 'ubean';
1237
- * import { createServerApi } from '../request/internal';
1238
- *
1239
- * export const GET = defineHandler(async (c) => {
1240
- * const api = createServerApi(c);
1241
- * const user = await api.get('/api/users/{id}', { pathParams: { id: 1 } });
1242
- * return c.json(user);
1243
- * });
1244
- *
1245
- * @example
1246
- * // 在 useData 中使用
1247
- * import { useData, defineHandler } from 'ubean';
1248
- * import { createServerApi } from '../request/internal';
1249
- *
1250
- * export const GET = defineHandler(async (c) => {
1251
- * const api = createServerApi(c);
1252
- * const result = await useData({
1253
- * fetcher: async () => api.get('/api/users/{id}', { pathParams: { id: 1 } })
1254
- * });
1255
- * return c.json(result.data);
1256
- * });
1257
- */
1258
- export function createServerApi(context: Parameters<typeof createInternalAdapter>[0]) {
1259
- const adapter = createInternalAdapter(context);
1260
- const request = createRequest(
1261
- { retry: { retries: 0 }, adapter },
1262
- { isBackendSuccess: () => true, transform: response => response.data }
1263
- );
1264
- return createTypedClient<paths>(request);
1265
- }
1266
- `;
1267
- const DEFAULT_LAYOUT_TEMPLATE = `<template>
1268
- <slot />
1269
- </template>
1270
-
1271
- <script setup lang="ts">
1272
- <\/script>
1273
-
1274
- <style>
1275
- body {
1276
- line-height: 1.5;
1277
- }
1278
- </style>
1279
- `;
1280
- const GITIGNORE_TEMPLATE = `node_modules
1281
- dist
1282
- .ubean
1283
- .DS_Store
1284
- *.log
1285
- .env
1286
- .env.local
1287
- .env.*.local
1288
- `;
1289
- const FAVICON_SVG_TEMPLATE = `<svg width="100%" height="100%" version="1.1" viewBox="0 0 1000 1000" xmlns="http://www.w3.org/2000/svg"
1290
- xmlns:xlink="http://www.w3.org/1999/xlink">
1291
- <g>
1292
- <path
1293
- d="M 200,866 C 100,866 50,779.4 100,692.8 L 200,519.6 C 220,485 240,490 265,499.6 S 360,542.68 360,542.68 C 480.5,601 498,642.5 500,720 C 498,811 462,856 420,866"
1294
- fill="url(#LinearGradient)" fill-rule="nonzero" opacity="1" stroke="none" />
1295
- <path
1296
- d="M 420,866 C 455,861 478,846 500,827 C 614,696 615,597 500,517 C 394,444 333,374 380,207.82 L 260,415.67 C 240.22,450 254.37,465.1 275.28,481.79 S 360,542.68 360,542.68 C 480.5,601 498,642.5 500,720 C 498,811 462,856 420,866"
1297
- fill="url(#LinearGradient_2)" fill-rule="nonzero" opacity="1" stroke="none" />
1298
- <path d="M 500,517 C 394,444 333,374 380,207.82 L 400,173.2 C 367,295 421,350 603,428 C 572,440 524,474 500,517"
1299
- fill="url(#LinearGradient_3)" fill-rule="nonzero" opacity="1" stroke="none" />
1300
- <path d="M 500,827 L 660,660 C 738,589 710,482 603,428 C 572,440 524,474 500,517 C 615,597 614,696 500,827"
1301
- fill="url(#LinearGradient_4)" fill-rule="nonzero" opacity="1" stroke="none" />
1302
- <path d="M 400,173.2 C 367,295 421,350 603,428 C 690,389, 750,445 788,500 L 600,173.2 C 550,86.6 450,86.6 400,173.2"
1303
- fill="url(#LinearGradient_5)" fill-rule="nonzero" opacity="1" stroke="none" />
1304
- <path
1305
- d="M 500,827 L 660,660 C 738,589 710,482 603,428 C 690,389, 750,445 788,500 C 816,554 797,606 750,640 L 500,827"
1306
- fill="url(#LinearGradient_6)" fill-rule="nonzero" opacity="1" stroke="none" />
1307
- <path
1308
- d="M 788,500 C 816,554 797,606 750,640 L 500,827 C 497,851 513,862 540,866 L 800,866 C 900,866 950,779.4 900,692.8 L 788,500"
1309
- fill="url(#LinearGradient_7)" fill-rule="nonzero" opacity="1" stroke="none" />
1310
- <g transform="translate(140, 650) scale(0.18)">
1311
- <path d="M539.04,146.5c-77.37,32.74-126.47,114.53-123.22,198,.61,150.92,169.47,210.6,214.99,341.13,39.71,96.62-16.62,230.68-122.31,253.16-374.89-83.15-390.44-785.49,30.54-792.29ZM564.61,948.5c68.1-32.18,118.51-95.45,132.49-169.97,41.81-214.6-158.22-254.7-215.15-413.02-31.14-86.21,21.33-198.66,114.56-214.57,129.21,21.58,214.93,148.7,230.96,272.19,7.94,38.53,21.57,75.37,34.41,112.43,75.75,198.26-76.06,438.99-297.26,412.94Z" fill="#ffffff" fill-rule="evenodd"/>
1312
- </g>
1313
- </g>
1314
- <defs>
1315
- <linearGradient gradientTransform="matrix(104.391 -73.3432 73.3432 104.391 277.441 710.122)"
1316
- gradientUnits="userSpaceOnUse" id="LinearGradient" x1="0" x2="1" y1="0" y2="0">
1317
- <stop offset="0" stop-color="#373ebf" />
1318
- <stop offset="1" stop-color="#5058e6" />
1319
- </linearGradient>
1320
- <linearGradient gradientTransform="matrix(-173.747 557.324 -557.324 -173.747 508.829 258.172)"
1321
- gradientUnits="userSpaceOnUse" id="LinearGradient_2" x1="0" x2="1" y1="0" y2="0">
1322
- <stop offset="0" stop-color="#c2d6ff" />
1323
- <stop offset="1" stop-color="#646cff" />
1324
- </linearGradient>
1325
- <linearGradient gradientTransform="matrix(157.951 295.666 -295.666 157.951 382.944 193.642)"
1326
- gradientUnits="userSpaceOnUse" id="LinearGradient_3" x1="0" x2="1" y1="0" y2="0">
1327
- <stop offset="0" stop-color="#5058e6" />
1328
- <stop offset="1" stop-color="#373ebf" />
1329
- </linearGradient>
1330
- <linearGradient gradientTransform="matrix(-44.3023 219.578 -219.578 -44.3023 619.69 469.652)"
1331
- gradientUnits="userSpaceOnUse" id="LinearGradient_4" x1="0" x2="1" y1="0" y2="0">
1332
- <stop offset="0" stop-color="#91a7ff" />
1333
- <stop offset="1" stop-color="#5058e6" />
1334
- </linearGradient>
1335
- <linearGradient gradientTransform="matrix(125.52 334.256 -334.256 125.52 539.723 235.139)"
1336
- gradientUnits="userSpaceOnUse" id="LinearGradient_5" x1="0" x2="1" y1="0" y2="0">
1337
- <stop offset="0" stop-color="#646cff" />
1338
- <stop offset="1" stop-color="#c2d6ff" />
1339
- </linearGradient>
1340
- <linearGradient gradientTransform="matrix(-241.23 357.206 -357.206 -241.23 754.054 449.312)"
1341
- gradientUnits="userSpaceOnUse" id="LinearGradient_6" x1="0" x2="1" y1="0" y2="0">
1342
- <stop offset="0" stop-color="#c2d6ff" />
1343
- <stop offset="1" stop-color="#646cff" />
1344
- </linearGradient>
1345
- <linearGradient gradientTransform="matrix(125.978 210.065 -210.065 125.978 596.433 613.665)"
1346
- gradientUnits="userSpaceOnUse" id="LinearGradient_7" x1="0" x2="1" y1="0" y2="0">
1347
- <stop offset="0" stop-color="#373ebf" />
1348
- <stop offset="1" stop-color="#5058e6" />
1349
- </linearGradient>
1350
- </defs>
1351
- </svg>
1352
- `;
1353
- const README_TEMPLATE = `# {{name}}
1354
-
1355
- A Vue meta-framework project powered by ubean.
1356
-
1357
- ## Getting Started
1358
-
1359
- \`\`\`bash
1360
- # Install dependencies
1361
- {{pm}} install
1362
-
1363
- # Start dev server
1364
- {{pm}} dev
1365
-
1366
- # Build for production
1367
- {{pm}} build
1368
-
1369
- # Preview production build
1370
- {{pm}} preview
1371
- \`\`\`
1372
-
1373
- ## Project Structure
1374
-
1375
- \`\`\`
1376
- ├── src/
1377
- │ ├── pages/ # File-based routing
1378
- │ ├── layouts/ # Layout components
1379
- │ ├── routes/ # API routes
1380
- │ ├── components/ # Vue components
1381
- │ ├── composables/ # Auto-imported composables
1382
- │ ├── plugins/ # App plugins
1383
- │ ├── middleware/ # Request middleware
1384
- │ ├── crons/ # Scheduled tasks
1385
- │ ├── queues/ # Background jobs
1386
- │ ├── request/ # Typed HTTP client & internal fetch
1387
- │ └── app.vue # Root app component
1388
- ├── public/ # Static assets
1389
- └── ubean.config.ts # ubean configuration
1390
- \`\`\`
1391
- `;
1392
- const BLOG_INDEX_TEMPLATE = `<template>
1393
- <div class="blog-page">
1394
- <h1>Blog</h1>
1395
- <div class="posts">
1396
- <article v-for="post in posts" :key="post.slug" class="post-card">
1397
- <h2><RouterLink :to="'/blog/' + post.slug">{{ post.title }}</RouterLink></h2>
1398
- <p class="date">{{ post.date }}</p>
1399
- <p class="excerpt">{{ post.excerpt }}</p>
1400
- </article>
1401
- </div>
1402
- </div>
1403
- </template>
1404
-
1405
- <script setup lang="ts">
1406
- import { RouterLink } from 'vue-router';
1407
- import { useData } from 'ubean';
1408
-
1409
- definePage({
1410
- meta: {
1411
- title: 'Blog'
1412
- }
1413
- });
1414
-
1415
- const { data: posts } = await useData('posts', () => {
1416
- return [
1417
- { slug: 'hello-world', title: 'Hello World', date: '2024-01-15', excerpt: 'Welcome to my blog!' }
1418
- ];
1419
- });
1420
- <\/script>
1421
-
1422
- <style scoped>
1423
- .blog-page {
1424
- max-width: 800px;
1425
- margin: 0 auto;
1426
- padding: 3rem 2rem;
1427
- }
1428
-
1429
- h1 {
1430
- margin-bottom: 2rem;
1431
- }
1432
-
1433
- .posts {
1434
- display: flex;
1435
- flex-direction: column;
1436
- gap: 2rem;
1437
- }
1438
-
1439
- .post-card {
1440
- padding: 1.5rem;
1441
- border-radius: 8px;
1442
- border: 1px solid #eee;
1443
- }
1444
-
1445
- h2 {
1446
- font-size: 1.5rem;
1447
- margin-bottom: 0.5rem;
1448
- }
1449
-
1450
- h2 a {
1451
- color: #333;
1452
- text-decoration: none;
1453
- }
1454
-
1455
- h2 a:hover {
1456
- color: #667eea;
1457
- }
1458
-
1459
- .date {
1460
- color: #999;
1461
- font-size: 0.9rem;
1462
- margin-bottom: 0.5rem;
1463
- }
1464
-
1465
- .excerpt {
1466
- color: #666;
1467
- }
1468
- </style>
1469
- `;
1470
- const BLOG_POST_MD_TEMPLATE = `---
1471
- title: Hello World
1472
- date: 2024-01-15
1473
- description: Welcome to my ubean blog!
1474
- ---
1475
-
1476
- # Hello World
1477
-
1478
- Welcome to my new blog built with **ubean**!
1479
-
1480
- This is a markdown blog post.
1481
-
1482
- ## Features
1483
-
1484
- - File-based routing
1485
- - Markdown support
1486
- - Auto-imports
1487
- - API routes
1488
- - And much more!
1489
- `;
1490
941
  async function scaffoldProject(options) {
1491
942
  const targetDir = resolve$1(options.cwd, options.dir);
1492
943
  const fs = createFsOps(targetDir);
@@ -1502,40 +953,24 @@ async function scaffoldProject(options) {
1502
953
  }
1503
954
  }
1504
955
  }
1505
- await fs.ensureDir("src");
1506
- await fs.ensureDir("src/pages");
1507
- await fs.ensureDir("src/layouts");
1508
- await fs.ensureDir("src/routes");
1509
- await fs.ensureDir("src/components");
1510
- await fs.ensureDir("src/composables");
1511
- await fs.ensureDir("src/plugins");
1512
- await fs.ensureDir("src/request");
1513
- await fs.ensureDir("public");
1514
- await fs.writeFile("package.json", renderTemplate(PACKAGE_JSON_TEMPLATE, { variables: { name: projectName } }));
1515
- await fs.writeFile("public/favicon.svg", FAVICON_SVG_TEMPLATE);
1516
- await fs.writeFile("tsconfig.json", TSCONFIG_TEMPLATE);
1517
- await fs.writeFile("ubean.config.ts", renderTemplate(UBEAN_CONFIG_TEMPLATE, { variables: { preset: options.preset || "standard" } }));
1518
- await fs.writeFile(".gitignore", GITIGNORE_TEMPLATE);
1519
- await fs.writeFile("README.md", renderTemplate(README_TEMPLATE, { variables: {
956
+ const templateOptions = {
1520
957
  name: projectName,
1521
- pm
1522
- } }));
1523
- await fs.writeFile("src/app.vue", APP_VUE_TEMPLATE);
1524
- await fs.writeFile("src/layouts/default.vue", DEFAULT_LAYOUT_TEMPLATE);
1525
- await fs.writeFile("src/request/client.ts", REQUEST_CLIENT_TEMPLATE);
1526
- await fs.writeFile("src/request/internal.ts", REQUEST_INTERNAL_TEMPLATE);
1527
- if (options.template === "minimal") await fs.writeFile("src/pages/index.vue", INDEX_PAGE_TEMPLATE);
1528
- else if (options.template === "blog") {
1529
- await fs.writeFile("src/pages/index.vue", INDEX_PAGE_TEMPLATE);
1530
- await fs.writeFile("src/pages/about.vue", ABOUT_PAGE_TEMPLATE);
1531
- await fs.ensureDir("src/pages/blog");
1532
- await fs.writeFile("src/pages/blog/index.vue", BLOG_INDEX_TEMPLATE);
1533
- await fs.writeFile("src/pages/blog/hello-world.md", BLOG_POST_MD_TEMPLATE);
1534
- await fs.writeFile("src/routes/hello.get.ts", HELLO_API_TEMPLATE);
1535
- } else {
1536
- await fs.writeFile("src/pages/index.vue", INDEX_PAGE_TEMPLATE);
1537
- await fs.writeFile("src/pages/about.vue", ABOUT_PAGE_TEMPLATE);
1538
- await fs.writeFile("src/routes/hello.get.ts", HELLO_API_TEMPLATE);
958
+ preset: options.preset || "standard",
959
+ packageManager: pm
960
+ };
961
+ switch (options.template) {
962
+ case "unify":
963
+ await scaffoldUnifyTemplate(fs, templateOptions);
964
+ break;
965
+ case "minimal":
966
+ await scaffoldMinimalTemplate(fs, templateOptions);
967
+ break;
968
+ case "blog":
969
+ await scaffoldBlogTemplate(fs, templateOptions);
970
+ break;
971
+ default:
972
+ await scaffoldStarterTemplate(fs, templateOptions);
973
+ break;
1539
974
  }
1540
975
  if (options.git) try {
1541
976
  const { execSync } = await import("node:child_process");
@@ -1548,7 +983,7 @@ async function scaffoldProject(options) {
1548
983
  console.log(`Project: ${projectName}`);
1549
984
  console.log(`Location: ${targetDir}`);
1550
985
  console.log(`Preset: ${options.preset || "standard"}`);
1551
- console.log(`Template: ${options.template || "starter"}`);
986
+ console.log(`Template: ${options.template || "unify"}`);
1552
987
  console.log("\nNext steps:");
1553
988
  if (options.dir !== ".") console.log(` cd ${options.dir}`);
1554
989
  console.log(` ${pm} install`);
@@ -1578,7 +1013,7 @@ const initCommand = {
1578
1013
  },
1579
1014
  template: {
1580
1015
  type: "string",
1581
- description: "Project template (minimal/starter/blog)"
1016
+ description: "Project template (unify/minimal/starter/blog)"
1582
1017
  },
1583
1018
  preset: {
1584
1019
  type: "string",
@@ -1611,7 +1046,7 @@ const initCommand = {
1611
1046
  logger$3.info("🚀 ubean project initializer");
1612
1047
  if (!nonInteractive) {
1613
1048
  name = name || await prompt("Project name", args.dir === "." ? basename(cwd) : args.dir);
1614
- template = template || await select("Select a template:", TEMPLATES, "starter");
1049
+ template = template || await select("Select a template:", TEMPLATES, "unify");
1615
1050
  preset = preset || await select("Select a preset:", PRESETS, "standard");
1616
1051
  packageManager = packageManager || await prompt("Package manager (npm/pnpm/yarn/bun)", "npm");
1617
1052
  if (git === void 0) git = await confirm("Initialize git repository?", true);
@@ -1620,7 +1055,7 @@ const initCommand = {
1620
1055
  cwd,
1621
1056
  dir: args.dir,
1622
1057
  force: args.force,
1623
- template: template || "starter",
1058
+ template: template || "unify",
1624
1059
  preset: preset || "standard",
1625
1060
  packageManager: packageManager || "npm",
1626
1061
  git: git !== false,
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { S as createFsOps, _ as renderPluginTemplate, a as scaffold, b as toKebabCase, c as LAYOUT_TEMPLATE, d as PLUGIN_TEMPLATE, f as renderApiTemplate, g as renderPageTemplate, h as renderMiddlewareTemplate, i as recoverScaffold, l as MIDDLEWARE_TEMPLATE, m as renderLayoutTemplate, n as listScaffoldableFiles, o as API_TEMPLATE, p as renderCronTemplate, s as CRON_TEMPLATE, t as deleteScaffold, u as PAGE_TEMPLATE, v as renderTemplate, x as toPascalCase, y as toCamelCase } from "./page-Cmp7s9l2.js";
1
+ import { C as toCamelCase, E as createFsOps, S as renderTemplate, T as toPascalCase, _ as renderCronTemplate, a as scaffold, b as renderPageTemplate, d as CRON_TEMPLATE, f as LAYOUT_TEMPLATE, g as renderApiTemplate, h as PLUGIN_TEMPLATE, i as recoverScaffold, m as PAGE_TEMPLATE, n as listScaffoldableFiles, p as MIDDLEWARE_TEMPLATE, t as deleteScaffold, u as API_TEMPLATE, v as renderLayoutTemplate, w as toKebabCase, x as renderPluginTemplate, y as renderMiddlewareTemplate } from "./page-VyP_7yLT.js";
2
2
  export { API_TEMPLATE, CRON_TEMPLATE, LAYOUT_TEMPLATE, MIDDLEWARE_TEMPLATE, PAGE_TEMPLATE, PLUGIN_TEMPLATE, createFsOps, deleteScaffold, listScaffoldableFiles, recoverScaffold, renderApiTemplate, renderCronTemplate, renderLayoutTemplate, renderMiddlewareTemplate, renderPageTemplate, renderPluginTemplate, renderTemplate, scaffold, toCamelCase, toKebabCase, toPascalCase };