@tanstack/cta-engine 0.14.3 → 0.14.4
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/add-ons.js +5 -91
- package/dist/add-to-app.js +171 -0
- package/dist/config-file.js +34 -11
- package/dist/constants.js +0 -2
- package/dist/create-app.js +142 -451
- package/dist/custom-add-ons/add-on.js +175 -0
- package/dist/custom-add-ons/shared.js +116 -0
- package/dist/custom-add-ons/starter.js +84 -0
- package/dist/environment.js +67 -44
- package/dist/file-helpers.js +165 -0
- package/dist/frameworks.js +92 -0
- package/dist/index.js +18 -1
- package/dist/integrations/git.js +4 -0
- package/dist/integrations/shadcn.js +33 -0
- package/dist/options.js +9 -333
- package/dist/package-json.js +48 -0
- package/dist/package-manager.js +51 -6
- package/dist/registry.js +56 -0
- package/dist/special-steps/index.js +24 -0
- package/dist/special-steps/rimraf-node-modules.js +16 -0
- package/dist/template-file.js +112 -0
- package/dist/types/add-ons.d.ts +3 -8
- package/dist/types/add-to-app.d.ts +17 -0
- package/dist/types/config-file.d.ts +7 -4
- package/dist/types/constants.d.ts +0 -3
- package/dist/types/create-app.d.ts +1 -7
- package/dist/types/custom-add-ons/add-on.d.ts +69 -0
- package/dist/types/custom-add-ons/shared.d.ts +15 -0
- package/dist/types/custom-add-ons/starter.d.ts +7 -0
- package/dist/types/environment.d.ts +2 -1
- package/dist/types/file-helpers.d.ts +15 -0
- package/dist/types/frameworks.d.ts +7 -0
- package/dist/types/index.d.ts +21 -1
- package/dist/types/integrations/git.d.ts +2 -0
- package/dist/types/integrations/shadcn.d.ts +2 -0
- package/dist/types/options.d.ts +2 -6
- package/dist/types/package-json.d.ts +7 -0
- package/dist/types/package-manager.d.ts +18 -1
- package/dist/types/registry.d.ts +25 -0
- package/dist/types/special-steps/index.d.ts +2 -0
- package/dist/types/special-steps/rimraf-node-modules.d.ts +2 -0
- package/dist/types/template-file.d.ts +2 -0
- package/dist/types/types.d.ts +788 -85
- package/dist/types/utils.d.ts +5 -0
- package/dist/types.js +65 -1
- package/dist/utils.js +9 -0
- package/package.json +9 -12
- package/src/add-ons.ts +7 -123
- package/src/add-to-app.ts +276 -0
- package/src/config-file.ts +51 -20
- package/src/constants.ts +0 -5
- package/src/create-app.ts +180 -730
- package/src/custom-add-ons/add-on.ts +261 -0
- package/src/custom-add-ons/shared.ts +160 -0
- package/src/custom-add-ons/starter.ts +126 -0
- package/src/environment.ts +80 -45
- package/src/file-helpers.ts +235 -0
- package/src/frameworks.ts +134 -0
- package/src/index.ts +85 -1
- package/src/integrations/git.ts +7 -0
- package/src/integrations/shadcn.ts +54 -0
- package/src/options.ts +8 -409
- package/src/package-json.ts +69 -0
- package/src/package-manager.ts +80 -9
- package/src/registry.ts +92 -0
- package/src/special-steps/index.ts +36 -0
- package/src/special-steps/rimraf-node-modules.ts +25 -0
- package/src/template-file.ts +150 -0
- package/src/types.ts +175 -87
- package/src/utils.ts +17 -0
- package/tests/add-ons.test.ts +67 -0
- package/tests/add-to-app.test.ts +358 -0
- package/tests/config-file.test.ts +105 -0
- package/tests/create-app.test.ts +120 -0
- package/tests/custom-add-ons/add-on.test.ts +12 -0
- package/tests/custom-add-ons/shared.test.ts +253 -0
- package/tests/custom-add-ons/starter.test.ts +58 -0
- package/tests/environment.test.ts +115 -0
- package/tests/file-helper.test.ts +90 -0
- package/tests/frameworks.test.ts +95 -0
- package/tests/index.test.ts +9 -0
- package/tests/integrations/git.test.ts +20 -0
- package/tests/integrations/shadcn.test.ts +91 -0
- package/tests/options.test.ts +42 -0
- package/tests/package-json.test.ts +63 -0
- package/tests/package-manager.test.ts +154 -0
- package/tests/setupVitest.ts +6 -0
- package/tests/template-file.test.ts +178 -0
- package/tests/utils.test.ts +23 -0
- package/vitest.config.ts +21 -0
- package/dist/add.js +0 -125
- package/dist/cli.js +0 -132
- package/dist/custom-add-on.js +0 -254
- package/dist/file-helper.js +0 -18
- package/dist/mcp.js +0 -229
- package/dist/templates.js +0 -6
- package/dist/toolchain.js +0 -6
- package/dist/types/add.d.ts +0 -3
- package/dist/types/cli.d.ts +0 -7
- package/dist/types/custom-add-on.d.ts +0 -3
- package/dist/types/file-helper.d.ts +0 -2
- package/dist/types/mcp.d.ts +0 -7
- package/dist/types/templates.d.ts +0 -1
- package/dist/types/toolchain.d.ts +0 -3
- package/src/add.ts +0 -186
- package/src/cli.ts +0 -210
- package/src/custom-add-on.ts +0 -325
- package/src/file-helper.ts +0 -20
- package/src/mcp.ts +0 -302
- package/src/templates.ts +0 -7
- package/src/toolchain.ts +0 -7
- package/templates/react/add-on/clerk/README.md +0 -3
- package/templates/react/add-on/clerk/assets/_dot_env.local.append +0 -2
- package/templates/react/add-on/clerk/assets/src/integrations/clerk/header-user.tsx +0 -19
- package/templates/react/add-on/clerk/assets/src/integrations/clerk/provider.tsx +0 -18
- package/templates/react/add-on/clerk/assets/src/routes/demo.clerk.tsx +0 -20
- package/templates/react/add-on/clerk/info.json +0 -13
- package/templates/react/add-on/clerk/package.json +0 -5
- package/templates/react/add-on/convex/README.md +0 -4
- package/templates/react/add-on/convex/assets/_dot_cursorrules.append +0 -93
- package/templates/react/add-on/convex/assets/_dot_env.local.append +0 -3
- package/templates/react/add-on/convex/assets/convex/products.ts +0 -8
- package/templates/react/add-on/convex/assets/convex/schema.ts +0 -10
- package/templates/react/add-on/convex/assets/src/integrations/convex/provider.tsx +0 -20
- package/templates/react/add-on/convex/assets/src/routes/demo.convex.tsx +0 -33
- package/templates/react/add-on/convex/info.json +0 -13
- package/templates/react/add-on/convex/package.json +0 -6
- package/templates/react/add-on/form/assets/src/components/demo.FormComponents.tsx.ejs +0 -300
- package/templates/react/add-on/form/assets/src/hooks/demo.form-context.ts +0 -4
- package/templates/react/add-on/form/assets/src/hooks/demo.form.ts +0 -22
- package/templates/react/add-on/form/assets/src/routes/demo.form.address.tsx.ejs +0 -213
- package/templates/react/add-on/form/assets/src/routes/demo.form.simple.tsx.ejs +0 -77
- package/templates/react/add-on/form/info.json +0 -26
- package/templates/react/add-on/form/package.json +0 -6
- package/templates/react/add-on/module-federation/assets/module-federation.config.js.ejs +0 -31
- package/templates/react/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
- package/templates/react/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -11
- package/templates/react/add-on/module-federation/info.json +0 -7
- package/templates/react/add-on/module-federation/package.json +0 -5
- package/templates/react/add-on/netlify/README.md +0 -11
- package/templates/react/add-on/netlify/info.json +0 -7
- package/templates/react/add-on/sentry/assets/_dot_cursorrules.append +0 -22
- package/templates/react/add-on/sentry/assets/_dot_env.local.append +0 -11
- package/templates/react/add-on/sentry/assets/src/app/global-middleware.ts +0 -11
- package/templates/react/add-on/sentry/assets/src/routes/demo.sentry.testing.tsx +0 -489
- package/templates/react/add-on/sentry/info.json +0 -14
- package/templates/react/add-on/sentry/package.json +0 -5
- package/templates/react/add-on/shadcn/README.md +0 -7
- package/templates/react/add-on/shadcn/assets/_dot_cursorrules.append +0 -7
- package/templates/react/add-on/shadcn/assets/components.json +0 -21
- package/templates/react/add-on/shadcn/assets/src/lib/utils.ts +0 -6
- package/templates/react/add-on/shadcn/assets/src/styles.css +0 -138
- package/templates/react/add-on/shadcn/info.json +0 -7
- package/templates/react/add-on/shadcn/package.json +0 -9
- package/templates/react/add-on/start/assets/_dot_gitignore.append +0 -2
- package/templates/react/add-on/start/assets/app.config.ts.ejs +0 -32
- package/templates/react/add-on/start/assets/src/api.ts +0 -6
- package/templates/react/add-on/start/assets/src/client.tsx.ejs +0 -33
- package/templates/react/add-on/start/assets/src/router.tsx.ejs +0 -48
- package/templates/react/add-on/start/assets/src/routes/api.demo-names.ts +0 -11
- package/templates/react/add-on/start/assets/src/routes/demo.start.api-request.tsx.ejs +0 -33
- package/templates/react/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -50
- package/templates/react/add-on/start/assets/src/ssr.tsx.ejs +0 -30
- package/templates/react/add-on/start/info.json +0 -18
- package/templates/react/add-on/start/package.json +0 -13
- package/templates/react/add-on/store/assets/src/lib/demo-store.ts +0 -13
- package/templates/react/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -75
- package/templates/react/add-on/store/info.json +0 -13
- package/templates/react/add-on/store/package.json +0 -6
- package/templates/react/add-on/t3env/README.md +0 -16
- package/templates/react/add-on/t3env/assets/src/env.ts +0 -39
- package/templates/react/add-on/t3env/info.json +0 -10
- package/templates/react/add-on/t3env/package.json +0 -6
- package/templates/react/add-on/tRPC/assets/src/integrations/trpc/init.ts +0 -9
- package/templates/react/add-on/tRPC/assets/src/integrations/trpc/react.ts +0 -4
- package/templates/react/add-on/tRPC/assets/src/integrations/trpc/router.ts +0 -18
- package/templates/react/add-on/tRPC/assets/src/routes/api.trpc.$.tsx +0 -16
- package/templates/react/add-on/tRPC/info.json +0 -9
- package/templates/react/add-on/tRPC/package.json +0 -9
- package/templates/react/add-on/table/assets/src/data/demo-table-data.ts +0 -50
- package/templates/react/add-on/table/assets/src/routes/demo.table.tsx.ejs +0 -373
- package/templates/react/add-on/table/info.json +0 -13
- package/templates/react/add-on/table/package.json +0 -7
- package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/layout.tsx +0 -5
- package/templates/react/add-on/tanstack-query/assets/src/integrations/tanstack-query/root-provider.tsx.ejs +0 -70
- package/templates/react/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx.ejs +0 -53
- package/templates/react/add-on/tanstack-query/info.json +0 -13
- package/templates/react/add-on/tanstack-query/package.json +0 -6
- package/templates/react/base/README.md.ejs +0 -558
- package/templates/react/base/_dot_gitignore +0 -5
- package/templates/react/base/_dot_vscode/settings.biome.json +0 -38
- package/templates/react/base/_dot_vscode/settings.json +0 -11
- package/templates/react/base/index.html.ejs +0 -20
- package/templates/react/base/package.biome.json +0 -10
- package/templates/react/base/package.eslintprettier.json +0 -11
- package/templates/react/base/package.json +0 -30
- package/templates/react/base/package.ts.json +0 -7
- package/templates/react/base/package.tw.json +0 -6
- package/templates/react/base/public/favicon.ico +0 -0
- package/templates/react/base/public/logo192.png +0 -0
- package/templates/react/base/public/logo512.png +0 -0
- package/templates/react/base/public/manifest.json +0 -25
- package/templates/react/base/public/robots.txt +0 -3
- package/templates/react/base/src/App.css +0 -38
- package/templates/react/base/src/App.test.tsx.ejs +0 -10
- package/templates/react/base/src/App.tsx.ejs +0 -74
- package/templates/react/base/src/components/Header.tsx.ejs +0 -27
- package/templates/react/base/src/logo.svg +0 -44
- package/templates/react/base/src/reportWebVitals.ts.ejs +0 -28
- package/templates/react/base/src/styles.css.ejs +0 -15
- package/templates/react/base/toolchain/.prettierignore +0 -3
- package/templates/react/base/toolchain/biome.json +0 -31
- package/templates/react/base/toolchain/eslint.config.js +0 -5
- package/templates/react/base/toolchain/prettier.config.js +0 -10
- package/templates/react/base/tsconfig.json.ejs +0 -29
- package/templates/react/base/vite.config.js.ejs +0 -23
- package/templates/react/code-router/src/main.tsx.ejs +0 -92
- package/templates/react/example/tanchat/README.md +0 -37
- package/templates/react/example/tanchat/assets/_dot_env.local.append +0 -2
- package/templates/react/example/tanchat/assets/public/example-guitar-flowers.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-motherboard.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-racing.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-steamer-trunk.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-superhero.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-traveling.jpg +0 -0
- package/templates/react/example/tanchat/assets/public/example-guitar-video-games.jpg +0 -0
- package/templates/react/example/tanchat/assets/src/components/example-AIAssistant.tsx +0 -173
- package/templates/react/example/tanchat/assets/src/components/example-GuitarRecommendation.tsx +0 -47
- package/templates/react/example/tanchat/assets/src/data/example-guitars.ts +0 -83
- package/templates/react/example/tanchat/assets/src/demo.index.css +0 -220
- package/templates/react/example/tanchat/assets/src/integrations/tanchat/header-user.tsx +0 -5
- package/templates/react/example/tanchat/assets/src/routes/api.messages.ts +0 -24
- package/templates/react/example/tanchat/assets/src/routes/api.sse.ts +0 -23
- package/templates/react/example/tanchat/assets/src/routes/example.chat.tsx +0 -159
- package/templates/react/example/tanchat/assets/src/routes/example.guitars/$guitarId.tsx +0 -50
- package/templates/react/example/tanchat/assets/src/routes/example.guitars/index.tsx +0 -54
- package/templates/react/example/tanchat/assets/src/store/example-assistant.ts +0 -3
- package/templates/react/example/tanchat/assets/src/utils/demo.ai.ts +0 -62
- package/templates/react/example/tanchat/assets/src/utils/demo.sse.ts +0 -31
- package/templates/react/example/tanchat/assets/src/utils/demo.tools.ts +0 -47
- package/templates/react/example/tanchat/info.json +0 -19
- package/templates/react/example/tanchat/package.json +0 -16
- package/templates/react/file-router/package.fr.json +0 -5
- package/templates/react/file-router/src/main.tsx.ejs +0 -55
- package/templates/react/file-router/src/routes/__root.tsx.ejs +0 -82
- package/templates/solid/add-on/form/assets/src/routes/demo.form.tsx.ejs +0 -352
- package/templates/solid/add-on/form/info.json +0 -13
- package/templates/solid/add-on/form/package.json +0 -5
- package/templates/solid/add-on/module-federation/assets/module-federation.config.js.ejs +0 -27
- package/templates/solid/add-on/module-federation/assets/src/demo-mf-component.tsx +0 -3
- package/templates/solid/add-on/module-federation/assets/src/demo-mf-self-contained.tsx +0 -9
- package/templates/solid/add-on/module-federation/info.json +0 -7
- package/templates/solid/add-on/module-federation/package.json +0 -5
- package/templates/solid/add-on/sentry/assets/_dot_cursorrules.append +0 -22
- package/templates/solid/add-on/sentry/assets/_dot_env.local.append +0 -2
- package/templates/solid/add-on/sentry/assets/src/routes/demo.sentry.bad-event-handler.tsx +0 -20
- package/templates/solid/add-on/sentry/info.json +0 -13
- package/templates/solid/add-on/sentry/package.json +0 -5
- package/templates/solid/add-on/solid-ui/README.md +0 -9
- package/templates/solid/add-on/solid-ui/assets/src/lib/utils.ts +0 -6
- package/templates/solid/add-on/solid-ui/assets/src/styles.css +0 -138
- package/templates/solid/add-on/solid-ui/assets/ui.config.json +0 -13
- package/templates/solid/add-on/solid-ui/info.json +0 -11
- package/templates/solid/add-on/solid-ui/package.json +0 -9
- package/templates/solid/add-on/start/assets/app.config.ts +0 -16
- package/templates/solid/add-on/start/assets/src/api.ts +0 -6
- package/templates/solid/add-on/start/assets/src/client.tsx +0 -7
- package/templates/solid/add-on/start/assets/src/router.tsx.ejs +0 -24
- package/templates/solid/add-on/start/assets/src/routes/demo.start.server-funcs.tsx +0 -49
- package/templates/solid/add-on/start/assets/src/ssr.tsx +0 -12
- package/templates/solid/add-on/start/info.json +0 -14
- package/templates/solid/add-on/start/package.json +0 -12
- package/templates/solid/add-on/store/assets/src/lib/demo-store.ts +0 -13
- package/templates/solid/add-on/store/assets/src/routes/demo.store.tsx.ejs +0 -77
- package/templates/solid/add-on/store/info.json +0 -13
- package/templates/solid/add-on/store/package.json +0 -6
- package/templates/solid/add-on/t3env/README.md +0 -16
- package/templates/solid/add-on/t3env/assets/src/env.ts +0 -39
- package/templates/solid/add-on/t3env/info.json +0 -10
- package/templates/solid/add-on/t3env/package.json +0 -6
- package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/header-user.tsx +0 -5
- package/templates/solid/add-on/tanstack-query/assets/src/integrations/tanstack-query/provider.tsx +0 -15
- package/templates/solid/add-on/tanstack-query/assets/src/routes/demo.tanstack-query.tsx +0 -30
- package/templates/solid/add-on/tanstack-query/info.json +0 -13
- package/templates/solid/add-on/tanstack-query/package.json +0 -6
- package/templates/solid/base/README.md.ejs +0 -215
- package/templates/solid/base/_dot_cursorrules.append +0 -35
- package/templates/solid/base/_dot_gitignore +0 -5
- package/templates/solid/base/_dot_vscode/settings.biome.json +0 -38
- package/templates/solid/base/_dot_vscode/settings.json +0 -11
- package/templates/solid/base/index.html.ejs +0 -20
- package/templates/solid/base/package.biome.json +0 -10
- package/templates/solid/base/package.eslintprettier.json +0 -11
- package/templates/solid/base/package.json +0 -23
- package/templates/solid/base/package.ts.json +0 -5
- package/templates/solid/base/package.tw.json +0 -6
- package/templates/solid/base/public/favicon.ico +0 -0
- package/templates/solid/base/public/logo192.png +0 -0
- package/templates/solid/base/public/logo512.png +0 -0
- package/templates/solid/base/public/manifest.json +0 -25
- package/templates/solid/base/public/robots.txt +0 -3
- package/templates/solid/base/src/App.css +0 -0
- package/templates/solid/base/src/App.tsx.ejs +0 -47
- package/templates/solid/base/src/components/Header.tsx.ejs +0 -26
- package/templates/solid/base/src/logo.svg +0 -120
- package/templates/solid/base/src/styles.css.ejs +0 -15
- package/templates/solid/base/toolchain/.prettierignore +0 -3
- package/templates/solid/base/toolchain/biome.json +0 -31
- package/templates/solid/base/toolchain/eslint.config.js +0 -5
- package/templates/solid/base/toolchain/prettier.config.js +0 -10
- package/templates/solid/base/tsconfig.json.ejs +0 -31
- package/templates/solid/base/vite.config.js.ejs +0 -22
- package/templates/solid/code-router/src/main.tsx.ejs +0 -71
- package/templates/solid/example/tanchat/README.md +0 -52
- package/templates/solid/example/tanchat/assets/ai-streaming-server/README.md +0 -110
- package/templates/solid/example/tanchat/assets/ai-streaming-server/_dot_env.example +0 -1
- package/templates/solid/example/tanchat/assets/ai-streaming-server/package.json +0 -26
- package/templates/solid/example/tanchat/assets/ai-streaming-server/src/index.ts +0 -102
- package/templates/solid/example/tanchat/assets/ai-streaming-server/tsconfig.json +0 -15
- package/templates/solid/example/tanchat/assets/src/components/demo.SettingsDialog.tsx +0 -149
- package/templates/solid/example/tanchat/assets/src/demo.index.css +0 -227
- package/templates/solid/example/tanchat/assets/src/lib/demo-store.ts +0 -13
- package/templates/solid/example/tanchat/assets/src/routes/example.chat.tsx +0 -435
- package/templates/solid/example/tanchat/assets/src/store/demo.hooks.ts +0 -17
- package/templates/solid/example/tanchat/assets/src/store/demo.store.ts +0 -133
- package/templates/solid/example/tanchat/info.json +0 -14
- package/templates/solid/example/tanchat/package.json +0 -7
- package/templates/solid/file-router/package.fr.json +0 -5
- package/templates/solid/file-router/src/main.tsx.ejs +0 -47
- package/templates/solid/file-router/src/routes/__root.tsx.ejs +0 -41
- package/templates/solid/file-router/src/routes/index.tsx +0 -43
- package/tests/cra.test.ts +0 -293
- package/tests/snapshots/cra/cr-js-npm.json +0 -33
- package/tests/snapshots/cra/cr-ts-npm.json +0 -34
- package/tests/snapshots/cra/cr-ts-start-npm.json +0 -38
- package/tests/snapshots/cra/fr-ts-npm.json +0 -34
- package/tests/snapshots/cra/fr-ts-tw-npm.json +0 -33
- package/tests/snapshots/cra/solid-cr-js-npm.json +0 -31
- package/tests/snapshots/cra/solid-cr-ts-npm.json +0 -32
- package/tests/snapshots/cra/solid-cr-ts-start-npm.json +0 -36
- package/tests/snapshots/cra/solid-fr-ts-npm.json +0 -33
- package/tests/snapshots/cra/solid-fr-ts-tw-npm.json +0 -32
- package/tests/test-utilities.ts +0 -87
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
3
|
+
import { basename, extname, resolve } from 'node:path';
|
|
4
|
+
import parseGitignore from 'parse-gitignore';
|
|
5
|
+
import ignore from 'ignore';
|
|
6
|
+
const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.svg', '.ico'];
|
|
7
|
+
export function readFileHelper(path) {
|
|
8
|
+
if (isBinaryFile(path)) {
|
|
9
|
+
return `base64::${readFileSync(path).toString('base64')}`;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return readFileSync(path, 'utf-8').toString();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export function isBinaryFile(path) {
|
|
16
|
+
return BINARY_EXTENSIONS.includes(extname(path));
|
|
17
|
+
}
|
|
18
|
+
export function convertBinaryContentsToBase64(contents) {
|
|
19
|
+
return `base64::${Buffer.from(contents).toString('base64')}`;
|
|
20
|
+
}
|
|
21
|
+
export function isBase64(content) {
|
|
22
|
+
return content.startsWith('base64::');
|
|
23
|
+
}
|
|
24
|
+
export function getBinaryFile(content) {
|
|
25
|
+
if (content.startsWith('base64::')) {
|
|
26
|
+
const binaryContent = Buffer.from(content.replace('base64::', ''), 'base64');
|
|
27
|
+
return binaryContent;
|
|
28
|
+
}
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
export function relativePath(from, to) {
|
|
32
|
+
const cleanedFrom = from.startsWith('./') ? from.slice(2) : from;
|
|
33
|
+
const cleanedTo = to.startsWith('./') ? to.slice(2) : to;
|
|
34
|
+
const fromSegments = cleanedFrom.split('/');
|
|
35
|
+
const toSegments = cleanedTo.split('/');
|
|
36
|
+
fromSegments.pop();
|
|
37
|
+
toSegments.pop();
|
|
38
|
+
let commonIndex = 0;
|
|
39
|
+
while (commonIndex < fromSegments.length &&
|
|
40
|
+
commonIndex < toSegments.length &&
|
|
41
|
+
fromSegments[commonIndex] === toSegments[commonIndex]) {
|
|
42
|
+
commonIndex++;
|
|
43
|
+
}
|
|
44
|
+
const upLevels = fromSegments.length - commonIndex;
|
|
45
|
+
const downLevels = toSegments.slice(commonIndex);
|
|
46
|
+
if (upLevels === 0 && downLevels.length === 0) {
|
|
47
|
+
return `./${basename(to)}`;
|
|
48
|
+
}
|
|
49
|
+
else if (upLevels === 0 && downLevels.length > 0) {
|
|
50
|
+
return `./${downLevels.join('/')}/${basename(to)}`;
|
|
51
|
+
}
|
|
52
|
+
else {
|
|
53
|
+
const relativePath = [...Array(upLevels).fill('..'), ...downLevels].join('/');
|
|
54
|
+
return `${relativePath}/${basename(to)}`;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
export function isDirectory(path) {
|
|
58
|
+
return statSync(path).isDirectory();
|
|
59
|
+
}
|
|
60
|
+
export function findFilesRecursively(path, files) {
|
|
61
|
+
const dirFiles = readdirSync(path);
|
|
62
|
+
for (const file of dirFiles) {
|
|
63
|
+
const filePath = resolve(path, file);
|
|
64
|
+
if (isDirectory(filePath)) {
|
|
65
|
+
findFilesRecursively(filePath, files);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
files[filePath] = readFileHelper(filePath);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
async function recursivelyGatherFilesHelper(basePath, path, files, ignore) {
|
|
73
|
+
const dirFiles = await readdir(path, { withFileTypes: true });
|
|
74
|
+
for (const file of dirFiles) {
|
|
75
|
+
if (ignore(file.name)) {
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
if (file.isDirectory()) {
|
|
79
|
+
await recursivelyGatherFilesHelper(basePath, resolve(path, file.name), files, ignore);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const filePath = resolve(path, file.name);
|
|
83
|
+
files[filePath.replace(basePath, '.')] = await readFileHelper(filePath);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
export async function recursivelyGatherFiles(path, includeProjectFiles = true) {
|
|
88
|
+
const ignore = createIgnore(path, includeProjectFiles);
|
|
89
|
+
const files = {};
|
|
90
|
+
await recursivelyGatherFilesHelper(path, path, files, ignore);
|
|
91
|
+
return files;
|
|
92
|
+
}
|
|
93
|
+
async function recursivelyGatherFilesFromEnvironmentHelper(environment, basePath, path, files, ignore) {
|
|
94
|
+
const dirFiles = await environment.readdir(path);
|
|
95
|
+
for (const file of dirFiles) {
|
|
96
|
+
if (ignore(file)) {
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (environment.isDirectory(resolve(path, file))) {
|
|
100
|
+
await recursivelyGatherFilesFromEnvironmentHelper(environment, basePath, resolve(path, file), files, ignore);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const filePath = resolve(path, file);
|
|
104
|
+
files[filePath.replace(basePath, '.')] =
|
|
105
|
+
await environment.readFile(filePath);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
export async function recursivelyGatherFilesFromEnvironment(environment, path, includeProjectFiles = true) {
|
|
110
|
+
const ignore = createIgnore(path, includeProjectFiles);
|
|
111
|
+
const files = {};
|
|
112
|
+
await recursivelyGatherFilesFromEnvironmentHelper(environment, path, path, files, ignore);
|
|
113
|
+
return files;
|
|
114
|
+
}
|
|
115
|
+
export const IGNORE_FILES = [
|
|
116
|
+
'.starter',
|
|
117
|
+
'.add-on',
|
|
118
|
+
'.cta.json',
|
|
119
|
+
'.git',
|
|
120
|
+
'add-on-info.json',
|
|
121
|
+
'add-on.json',
|
|
122
|
+
'build',
|
|
123
|
+
'bun.lock',
|
|
124
|
+
'bun.lockb',
|
|
125
|
+
'deno.lock',
|
|
126
|
+
'dist',
|
|
127
|
+
'node_modules',
|
|
128
|
+
'package-lock.json',
|
|
129
|
+
'pnpm-lock.yaml',
|
|
130
|
+
'starter.json',
|
|
131
|
+
'starter-info.json',
|
|
132
|
+
'yarn.lock',
|
|
133
|
+
];
|
|
134
|
+
const PROJECT_FILES = ['package.json'];
|
|
135
|
+
export function createIgnore(path, includeProjectFiles = true) {
|
|
136
|
+
const ignoreList = existsSync(resolve(path, '.gitignore'))
|
|
137
|
+
? parseGitignore(readFileSync(resolve(path, '.gitignore'))).patterns
|
|
138
|
+
: [];
|
|
139
|
+
const ig = ignore().add(ignoreList);
|
|
140
|
+
return (filePath) => {
|
|
141
|
+
const fileName = basename(filePath);
|
|
142
|
+
if (IGNORE_FILES.includes(fileName) ||
|
|
143
|
+
(includeProjectFiles && PROJECT_FILES.includes(fileName))) {
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
146
|
+
const nameWithoutDotSlash = fileName.replace(/^\.\//, '');
|
|
147
|
+
return ig.ignores(nameWithoutDotSlash);
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
export function cleanUpFiles(files, targetDir) {
|
|
151
|
+
return Object.keys(files).reduce((acc, file) => {
|
|
152
|
+
if (basename(file) !== '.cta.json') {
|
|
153
|
+
acc[targetDir ? file.replace(targetDir, '.') : file] = files[file];
|
|
154
|
+
}
|
|
155
|
+
return acc;
|
|
156
|
+
}, {});
|
|
157
|
+
}
|
|
158
|
+
export function cleanUpFileArray(files, targetDir) {
|
|
159
|
+
return files.reduce((acc, file) => {
|
|
160
|
+
if (basename(file) !== '.cta.json') {
|
|
161
|
+
acc.push(targetDir ? file.replace(targetDir, '.') : file);
|
|
162
|
+
}
|
|
163
|
+
return acc;
|
|
164
|
+
}, []);
|
|
165
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
import { findFilesRecursively, isDirectory, readFileHelper, } from './file-helpers.js';
|
|
4
|
+
const frameworks = [];
|
|
5
|
+
function getAddOns(framework) {
|
|
6
|
+
const addOns = [];
|
|
7
|
+
for (const addOnsBase of framework.addOnsDirectories) {
|
|
8
|
+
for (const dir of readdirSync(addOnsBase).filter((file) => isDirectory(resolve(addOnsBase, file)))) {
|
|
9
|
+
const filePath = resolve(addOnsBase, dir, 'info.json');
|
|
10
|
+
const fileContent = readFileSync(filePath, 'utf-8');
|
|
11
|
+
const info = JSON.parse(fileContent);
|
|
12
|
+
let packageAdditions = {};
|
|
13
|
+
if (existsSync(resolve(addOnsBase, dir, 'package.json'))) {
|
|
14
|
+
packageAdditions = JSON.parse(readFileSync(resolve(addOnsBase, dir, 'package.json'), 'utf-8'));
|
|
15
|
+
}
|
|
16
|
+
let readme;
|
|
17
|
+
if (existsSync(resolve(addOnsBase, dir, 'README.md'))) {
|
|
18
|
+
readme = readFileSync(resolve(addOnsBase, dir, 'README.md'), 'utf-8');
|
|
19
|
+
}
|
|
20
|
+
let smallLogo;
|
|
21
|
+
if (existsSync(resolve(addOnsBase, dir, 'small-logo.svg'))) {
|
|
22
|
+
smallLogo = readFileSync(resolve(addOnsBase, dir, 'small-logo.svg'), 'utf-8');
|
|
23
|
+
}
|
|
24
|
+
const absoluteFiles = {};
|
|
25
|
+
const assetsDir = resolve(addOnsBase, dir, 'assets');
|
|
26
|
+
if (existsSync(assetsDir)) {
|
|
27
|
+
findFilesRecursively(assetsDir, absoluteFiles);
|
|
28
|
+
}
|
|
29
|
+
const files = {};
|
|
30
|
+
for (const file of Object.keys(absoluteFiles)) {
|
|
31
|
+
files[file.replace(assetsDir, '.')] = readFileHelper(file);
|
|
32
|
+
}
|
|
33
|
+
const getFiles = () => {
|
|
34
|
+
return Promise.resolve(Object.keys(files));
|
|
35
|
+
};
|
|
36
|
+
const getFileContents = (path) => {
|
|
37
|
+
return Promise.resolve(files[path]);
|
|
38
|
+
};
|
|
39
|
+
addOns.push({
|
|
40
|
+
...info,
|
|
41
|
+
id: dir,
|
|
42
|
+
packageAdditions,
|
|
43
|
+
readme,
|
|
44
|
+
files,
|
|
45
|
+
smallLogo,
|
|
46
|
+
getFiles,
|
|
47
|
+
getFileContents,
|
|
48
|
+
getDeletedFiles: () => Promise.resolve(info.deletedFiles ?? []),
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return addOns;
|
|
53
|
+
}
|
|
54
|
+
export function __testRegisterFramework(framework) {
|
|
55
|
+
frameworks.push(framework);
|
|
56
|
+
}
|
|
57
|
+
export function __testClearFrameworks() {
|
|
58
|
+
frameworks.length = 0;
|
|
59
|
+
}
|
|
60
|
+
export function registerFramework(framework) {
|
|
61
|
+
const baseAssetsDirectory = resolve(framework.baseDirectory, 'base');
|
|
62
|
+
const basePackageJSON = JSON.parse(readFileSync(resolve(baseAssetsDirectory, 'package.json'), 'utf8'));
|
|
63
|
+
const optionalPackages = JSON.parse(readFileSync(resolve(framework.baseDirectory, 'packages.json'), 'utf8'));
|
|
64
|
+
const addOns = getAddOns(framework);
|
|
65
|
+
const frameworkWithBundler = {
|
|
66
|
+
...framework,
|
|
67
|
+
getFiles: () => {
|
|
68
|
+
const files = {};
|
|
69
|
+
findFilesRecursively(baseAssetsDirectory, files);
|
|
70
|
+
return Promise.resolve(Object.keys(files).map((path) => path.replace(baseAssetsDirectory, '.')));
|
|
71
|
+
},
|
|
72
|
+
getFileContents: (path) => {
|
|
73
|
+
return Promise.resolve(readFileHelper(resolve(baseAssetsDirectory, path)));
|
|
74
|
+
},
|
|
75
|
+
getDeletedFiles: () => {
|
|
76
|
+
return Promise.resolve([]);
|
|
77
|
+
},
|
|
78
|
+
basePackageJSON,
|
|
79
|
+
optionalPackages,
|
|
80
|
+
getAddOns: () => addOns,
|
|
81
|
+
};
|
|
82
|
+
frameworks.push(frameworkWithBundler);
|
|
83
|
+
}
|
|
84
|
+
export function getFrameworkById(id) {
|
|
85
|
+
return frameworks.find((framework) => framework.id === id);
|
|
86
|
+
}
|
|
87
|
+
export function getFrameworkByName(name) {
|
|
88
|
+
return frameworks.find((framework) => framework.name === name);
|
|
89
|
+
}
|
|
90
|
+
export function getFrameworks() {
|
|
91
|
+
return frameworks;
|
|
92
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -1 +1,18 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { createApp } from './create-app.js';
|
|
2
|
+
export { addToApp } from './add-to-app.js';
|
|
3
|
+
export { finalizeAddOns, getAllAddOns } from './add-ons.js';
|
|
4
|
+
export { loadRemoteAddOn } from './custom-add-ons/add-on.js';
|
|
5
|
+
export { loadStarter } from './custom-add-ons/starter.js';
|
|
6
|
+
export { createMemoryEnvironment, createDefaultEnvironment, } from './environment.js';
|
|
7
|
+
export { CODE_ROUTER, CONFIG_FILE, FILE_ROUTER } from './constants.js';
|
|
8
|
+
export { DEFAULT_PACKAGE_MANAGER, SUPPORTED_PACKAGE_MANAGERS, getPackageManager, } from './package-manager.js';
|
|
9
|
+
export { registerFramework, getFrameworkById, getFrameworkByName, getFrameworks, } from './frameworks.js';
|
|
10
|
+
export { writeConfigFileToEnvironment, readConfigFileFromEnvironment, readConfigFile, } from './config-file.js';
|
|
11
|
+
export { cleanUpFiles, cleanUpFileArray, readFileHelper, getBinaryFile, recursivelyGatherFiles, relativePath, } from './file-helpers.js';
|
|
12
|
+
export { formatCommand } from './utils.js';
|
|
13
|
+
export { initStarter, compileStarter } from './custom-add-ons/starter.js';
|
|
14
|
+
export { initAddOn, compileAddOn } from './custom-add-ons/add-on.js';
|
|
15
|
+
export { createAppOptionsFromPersisted, createSerializedOptionsFromPersisted, } from './custom-add-ons/shared.js';
|
|
16
|
+
export { createSerializedOptions } from './options.js';
|
|
17
|
+
export { getRawRegistry, getRegistry, getRegistryAddOns, getRegistryStarters, } from './registry.js';
|
|
18
|
+
export { StarterCompiledSchema, AddOnCompiledSchema, AddOnInfoSchema, IntegrationSchema, } from './types.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { packageManagerExecute } from '../package-manager.js';
|
|
3
|
+
export async function installShadcnComponents(environment, targetDir, options) {
|
|
4
|
+
const s = environment.spinner();
|
|
5
|
+
if (options.chosenAddOns.find((a) => a.id === 'shadcn')) {
|
|
6
|
+
const shadcnComponents = new Set();
|
|
7
|
+
for (const addOn of options.chosenAddOns) {
|
|
8
|
+
if (addOn.shadcnComponents) {
|
|
9
|
+
for (const component of addOn.shadcnComponents) {
|
|
10
|
+
shadcnComponents.add(component);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
if (options.starter) {
|
|
15
|
+
if (options.starter.shadcnComponents) {
|
|
16
|
+
for (const component of options.starter.shadcnComponents) {
|
|
17
|
+
shadcnComponents.add(component);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
if (shadcnComponents.size > 0) {
|
|
22
|
+
s.start(`Installing shadcn components (${Array.from(shadcnComponents).join(', ')})...`);
|
|
23
|
+
environment.startStep({
|
|
24
|
+
id: 'install-shadcn-components',
|
|
25
|
+
type: 'command',
|
|
26
|
+
message: `Installing shadcn components (${Array.from(shadcnComponents).join(', ')})...`,
|
|
27
|
+
});
|
|
28
|
+
await packageManagerExecute(environment, resolve(targetDir), options.packageManager, 'shadcn@latest', ['add', '--silent', '--yes', ...Array.from(shadcnComponents)]);
|
|
29
|
+
environment.finishStep('install-shadcn-components', 'Shadcn components installed');
|
|
30
|
+
s.stop(`Installed additional shadcn components`);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
package/dist/options.js
CHANGED
|
@@ -1,333 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
// with spaces, We need to normalize this edge case.
|
|
11
|
-
if (Array.isArray(cliOptions.addOns) && cliOptions.addOns.length === 1) {
|
|
12
|
-
const parseSeparatedArgs = cliOptions.addOns[0].split(' ');
|
|
13
|
-
if (parseSeparatedArgs.length > 1) {
|
|
14
|
-
cliOptions.addOns = parseSeparatedArgs;
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
if (cliOptions.projectName) {
|
|
18
|
-
let typescript = cliOptions.template === 'typescript' ||
|
|
19
|
-
cliOptions.template === 'file-router' ||
|
|
20
|
-
cliOptions.framework === 'solid';
|
|
21
|
-
let tailwind = !!cliOptions.tailwind;
|
|
22
|
-
if (cliOptions.framework === 'solid') {
|
|
23
|
-
tailwind = true;
|
|
24
|
-
}
|
|
25
|
-
let mode = cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER;
|
|
26
|
-
const overlay = cliOptions.overlay
|
|
27
|
-
? (await loadRemoteAddOn(cliOptions.overlay))
|
|
28
|
-
: undefined;
|
|
29
|
-
if (overlay) {
|
|
30
|
-
tailwind = overlay.tailwind;
|
|
31
|
-
typescript = overlay.typescript;
|
|
32
|
-
cliOptions.framework = overlay.framework;
|
|
33
|
-
mode = overlay.mode;
|
|
34
|
-
}
|
|
35
|
-
let addOns = false;
|
|
36
|
-
let chosenAddOns = [];
|
|
37
|
-
if (Array.isArray(cliOptions.addOns) ||
|
|
38
|
-
overlay?.dependsOn ||
|
|
39
|
-
forcedAddOns) {
|
|
40
|
-
addOns = true;
|
|
41
|
-
let finalAddOns = Array.from(new Set([...(overlay?.dependsOn || []), ...(forcedAddOns || [])]));
|
|
42
|
-
if (cliOptions.addOns && Array.isArray(cliOptions.addOns)) {
|
|
43
|
-
finalAddOns = Array.from(new Set([
|
|
44
|
-
...(forcedAddOns || []),
|
|
45
|
-
...finalAddOns,
|
|
46
|
-
...cliOptions.addOns,
|
|
47
|
-
]));
|
|
48
|
-
}
|
|
49
|
-
chosenAddOns = await finalizeAddOns(cliOptions.framework || DEFAULT_FRAMEWORK, forcedMode || cliOptions.template === 'file-router'
|
|
50
|
-
? FILE_ROUTER
|
|
51
|
-
: CODE_ROUTER, finalAddOns);
|
|
52
|
-
tailwind = true;
|
|
53
|
-
typescript = true;
|
|
54
|
-
}
|
|
55
|
-
return {
|
|
56
|
-
framework: cliOptions.framework || 'react',
|
|
57
|
-
projectName: cliOptions.projectName,
|
|
58
|
-
typescript,
|
|
59
|
-
tailwind,
|
|
60
|
-
packageManager: cliOptions.packageManager ||
|
|
61
|
-
getPackageManager() ||
|
|
62
|
-
DEFAULT_PACKAGE_MANAGER,
|
|
63
|
-
toolchain: cliOptions.toolchain || DEFAULT_TOOLCHAIN,
|
|
64
|
-
mode,
|
|
65
|
-
git: !!cliOptions.git,
|
|
66
|
-
addOns,
|
|
67
|
-
chosenAddOns,
|
|
68
|
-
variableValues: {},
|
|
69
|
-
overlay,
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
async function collectVariables(variables) {
|
|
74
|
-
const responses = {};
|
|
75
|
-
for (const variable of variables) {
|
|
76
|
-
if (variable.type === 'string') {
|
|
77
|
-
const response = await text({
|
|
78
|
-
message: variable.description,
|
|
79
|
-
initialValue: variable.default,
|
|
80
|
-
});
|
|
81
|
-
if (isCancel(response)) {
|
|
82
|
-
cancel('Operation cancelled.');
|
|
83
|
-
process.exit(0);
|
|
84
|
-
}
|
|
85
|
-
responses[variable.name] = response;
|
|
86
|
-
}
|
|
87
|
-
else if (variable.type === 'number') {
|
|
88
|
-
const response = await text({
|
|
89
|
-
message: variable.description,
|
|
90
|
-
initialValue: variable.default.toString(),
|
|
91
|
-
});
|
|
92
|
-
if (isCancel(response)) {
|
|
93
|
-
cancel('Operation cancelled.');
|
|
94
|
-
process.exit(0);
|
|
95
|
-
}
|
|
96
|
-
responses[variable.name] = Number(response);
|
|
97
|
-
}
|
|
98
|
-
else {
|
|
99
|
-
const response = await confirm({
|
|
100
|
-
message: variable.description,
|
|
101
|
-
initialValue: variable.default === true,
|
|
102
|
-
});
|
|
103
|
-
if (isCancel(response)) {
|
|
104
|
-
cancel('Operation cancelled.');
|
|
105
|
-
process.exit(0);
|
|
106
|
-
}
|
|
107
|
-
responses[variable.name] = response;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
return responses;
|
|
111
|
-
}
|
|
112
|
-
export async function promptForOptions(cliOptions, { forcedAddOns = [], forcedMode, }) {
|
|
113
|
-
const options = {};
|
|
114
|
-
options.framework = cliOptions.framework || DEFAULT_FRAMEWORK;
|
|
115
|
-
if (options.framework === 'solid') {
|
|
116
|
-
options.typescript = true;
|
|
117
|
-
options.tailwind = true;
|
|
118
|
-
}
|
|
119
|
-
if (cliOptions.addOns) {
|
|
120
|
-
options.typescript = true;
|
|
121
|
-
}
|
|
122
|
-
if (!cliOptions.projectName) {
|
|
123
|
-
const value = await text({
|
|
124
|
-
message: 'What would you like to name your project?',
|
|
125
|
-
defaultValue: 'my-app',
|
|
126
|
-
validate(value) {
|
|
127
|
-
if (!value) {
|
|
128
|
-
return 'Please enter a name';
|
|
129
|
-
}
|
|
130
|
-
},
|
|
131
|
-
});
|
|
132
|
-
if (isCancel(value)) {
|
|
133
|
-
cancel('Operation cancelled.');
|
|
134
|
-
process.exit(0);
|
|
135
|
-
}
|
|
136
|
-
options.projectName = value;
|
|
137
|
-
}
|
|
138
|
-
else {
|
|
139
|
-
options.projectName = cliOptions.projectName;
|
|
140
|
-
}
|
|
141
|
-
// Router type selection
|
|
142
|
-
if (!cliOptions.template && !forcedMode) {
|
|
143
|
-
const routerType = await select({
|
|
144
|
-
message: 'Select the router type:',
|
|
145
|
-
options: [
|
|
146
|
-
{
|
|
147
|
-
value: FILE_ROUTER,
|
|
148
|
-
label: 'File Router - File-based routing structure',
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
value: CODE_ROUTER,
|
|
152
|
-
label: 'Code Router - Traditional code-based routing',
|
|
153
|
-
},
|
|
154
|
-
],
|
|
155
|
-
initialValue: FILE_ROUTER,
|
|
156
|
-
});
|
|
157
|
-
if (isCancel(routerType)) {
|
|
158
|
-
cancel('Operation cancelled.');
|
|
159
|
-
process.exit(0);
|
|
160
|
-
}
|
|
161
|
-
options.mode = routerType;
|
|
162
|
-
}
|
|
163
|
-
else if (forcedMode) {
|
|
164
|
-
options.mode = forcedMode === 'file-router' ? FILE_ROUTER : CODE_ROUTER;
|
|
165
|
-
options.typescript = options.mode === FILE_ROUTER;
|
|
166
|
-
}
|
|
167
|
-
else {
|
|
168
|
-
options.mode =
|
|
169
|
-
cliOptions.template === 'file-router' ? FILE_ROUTER : CODE_ROUTER;
|
|
170
|
-
if (options.mode === FILE_ROUTER) {
|
|
171
|
-
options.typescript = true;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
// TypeScript selection (if using Code Router)
|
|
175
|
-
if (!options.typescript) {
|
|
176
|
-
if (options.mode === CODE_ROUTER) {
|
|
177
|
-
const typescriptEnable = await confirm({
|
|
178
|
-
message: 'Would you like to use TypeScript?',
|
|
179
|
-
initialValue: true,
|
|
180
|
-
});
|
|
181
|
-
if (isCancel(typescriptEnable)) {
|
|
182
|
-
cancel('Operation cancelled.');
|
|
183
|
-
process.exit(0);
|
|
184
|
-
}
|
|
185
|
-
options.typescript = typescriptEnable;
|
|
186
|
-
}
|
|
187
|
-
else {
|
|
188
|
-
options.typescript = true;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
// Tailwind selection
|
|
192
|
-
if (!cliOptions.tailwind && options.framework === 'react') {
|
|
193
|
-
const tailwind = await confirm({
|
|
194
|
-
message: 'Would you like to use Tailwind CSS?',
|
|
195
|
-
initialValue: true,
|
|
196
|
-
});
|
|
197
|
-
if (isCancel(tailwind)) {
|
|
198
|
-
cancel('Operation cancelled.');
|
|
199
|
-
process.exit(0);
|
|
200
|
-
}
|
|
201
|
-
options.tailwind = tailwind;
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
options.tailwind = options.framework === 'solid' || !!cliOptions.tailwind;
|
|
205
|
-
}
|
|
206
|
-
// Package manager selection
|
|
207
|
-
if (cliOptions.packageManager === undefined) {
|
|
208
|
-
const detectedPackageManager = getPackageManager();
|
|
209
|
-
if (!detectedPackageManager) {
|
|
210
|
-
const pm = await select({
|
|
211
|
-
message: 'Select package manager:',
|
|
212
|
-
options: SUPPORTED_PACKAGE_MANAGERS.map((pm) => ({
|
|
213
|
-
value: pm,
|
|
214
|
-
label: pm,
|
|
215
|
-
})),
|
|
216
|
-
initialValue: DEFAULT_PACKAGE_MANAGER,
|
|
217
|
-
});
|
|
218
|
-
if (isCancel(pm)) {
|
|
219
|
-
cancel('Operation cancelled.');
|
|
220
|
-
process.exit(0);
|
|
221
|
-
}
|
|
222
|
-
options.packageManager = pm;
|
|
223
|
-
}
|
|
224
|
-
else {
|
|
225
|
-
options.packageManager = detectedPackageManager;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
options.packageManager = cliOptions.packageManager;
|
|
230
|
-
}
|
|
231
|
-
// Toolchain selection
|
|
232
|
-
if (cliOptions.toolchain === undefined) {
|
|
233
|
-
const tc = await select({
|
|
234
|
-
message: 'Select toolchain',
|
|
235
|
-
options: SUPPORTED_TOOLCHAINS.map((tc) => ({
|
|
236
|
-
value: tc,
|
|
237
|
-
label: tc,
|
|
238
|
-
})),
|
|
239
|
-
initialValue: DEFAULT_TOOLCHAIN,
|
|
240
|
-
});
|
|
241
|
-
if (isCancel(tc)) {
|
|
242
|
-
cancel('Operation cancelled.');
|
|
243
|
-
process.exit(0);
|
|
244
|
-
}
|
|
245
|
-
options.toolchain = tc;
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
options.toolchain = cliOptions.toolchain;
|
|
249
|
-
}
|
|
250
|
-
options.chosenAddOns = [];
|
|
251
|
-
if (Array.isArray(cliOptions.addOns)) {
|
|
252
|
-
options.chosenAddOns = await finalizeAddOns(options.framework, options.mode, Array.from(new Set([...cliOptions.addOns, ...forcedAddOns])));
|
|
253
|
-
options.tailwind = true;
|
|
254
|
-
}
|
|
255
|
-
else if (cliOptions.addOns) {
|
|
256
|
-
// Select any add-ons
|
|
257
|
-
const allAddOns = await getAllAddOns(options.framework, options.mode);
|
|
258
|
-
const addOns = allAddOns.filter((addOn) => addOn.type === 'add-on');
|
|
259
|
-
let selectedAddOns = [];
|
|
260
|
-
if (options.typescript && addOns.length > 0) {
|
|
261
|
-
const value = await multiselect({
|
|
262
|
-
message: 'What add-ons would you like for your project:',
|
|
263
|
-
options: addOns
|
|
264
|
-
.filter((addOn) => !forcedAddOns.includes(addOn.id))
|
|
265
|
-
.map((addOn) => ({
|
|
266
|
-
value: addOn.id,
|
|
267
|
-
label: addOn.name,
|
|
268
|
-
hint: addOn.description,
|
|
269
|
-
})),
|
|
270
|
-
required: false,
|
|
271
|
-
});
|
|
272
|
-
if (isCancel(value)) {
|
|
273
|
-
cancel('Operation cancelled.');
|
|
274
|
-
process.exit(0);
|
|
275
|
-
}
|
|
276
|
-
selectedAddOns = value;
|
|
277
|
-
}
|
|
278
|
-
// Select any examples
|
|
279
|
-
let selectedExamples = [];
|
|
280
|
-
const examples = allAddOns.filter((addOn) => addOn.type === 'example');
|
|
281
|
-
if (options.typescript && examples.length > 0) {
|
|
282
|
-
const value = await multiselect({
|
|
283
|
-
message: 'Would you like any examples?',
|
|
284
|
-
options: examples
|
|
285
|
-
.filter((addOn) => !forcedAddOns.includes(addOn.id))
|
|
286
|
-
.map((addOn) => ({
|
|
287
|
-
value: addOn.id,
|
|
288
|
-
label: addOn.name,
|
|
289
|
-
hint: addOn.description,
|
|
290
|
-
})),
|
|
291
|
-
required: false,
|
|
292
|
-
});
|
|
293
|
-
if (isCancel(value)) {
|
|
294
|
-
cancel('Operation cancelled.');
|
|
295
|
-
process.exit(0);
|
|
296
|
-
}
|
|
297
|
-
selectedExamples = value;
|
|
298
|
-
}
|
|
299
|
-
if (selectedAddOns.length > 0 ||
|
|
300
|
-
selectedExamples.length > 0 ||
|
|
301
|
-
forcedAddOns.length > 0) {
|
|
302
|
-
options.chosenAddOns = await finalizeAddOns(options.framework, options.mode, Array.from(new Set([...selectedAddOns, ...selectedExamples, ...forcedAddOns])));
|
|
303
|
-
options.tailwind = true;
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
else if (forcedAddOns.length > 0) {
|
|
307
|
-
options.chosenAddOns = await finalizeAddOns(options.framework, options.mode, forcedAddOns);
|
|
308
|
-
}
|
|
309
|
-
// Collect variables
|
|
310
|
-
const variables = [];
|
|
311
|
-
for (const addOn of options.chosenAddOns) {
|
|
312
|
-
for (const variable of addOn.variables ?? []) {
|
|
313
|
-
variables.push(variable);
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
options.variableValues = await collectVariables(variables);
|
|
317
|
-
// Git selection
|
|
318
|
-
if (cliOptions.git === undefined) {
|
|
319
|
-
const git = await confirm({
|
|
320
|
-
message: 'Would you like to initialize a new git repository?',
|
|
321
|
-
initialValue: true,
|
|
322
|
-
});
|
|
323
|
-
if (isCancel(git)) {
|
|
324
|
-
cancel('Operation cancelled.');
|
|
325
|
-
process.exit(0);
|
|
326
|
-
}
|
|
327
|
-
options.git = git;
|
|
328
|
-
}
|
|
329
|
-
else {
|
|
330
|
-
options.git = !!cliOptions.git;
|
|
331
|
-
}
|
|
332
|
-
return options;
|
|
333
|
-
}
|
|
1
|
+
export const createSerializedOptions = (options) => {
|
|
2
|
+
const serializedOptions = {
|
|
3
|
+
...options,
|
|
4
|
+
chosenAddOns: options.chosenAddOns.map((addOn) => addOn.id),
|
|
5
|
+
framework: options.framework.id,
|
|
6
|
+
starter: options.starter?.id,
|
|
7
|
+
};
|
|
8
|
+
return serializedOptions;
|
|
9
|
+
};
|