@tanstack/cta-engine 0.14.3 → 0.15.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/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
package/dist/types/utils.d.ts
CHANGED
package/dist/types.js
CHANGED
|
@@ -1 +1,65 @@
|
|
|
1
|
-
|
|
1
|
+
import z from 'zod';
|
|
2
|
+
export const AddOnBaseSchema = z.object({
|
|
3
|
+
id: z.string(),
|
|
4
|
+
name: z.string(),
|
|
5
|
+
description: z.string(),
|
|
6
|
+
author: z.string().optional(),
|
|
7
|
+
version: z.string().optional(),
|
|
8
|
+
link: z.string().optional(),
|
|
9
|
+
license: z.string().optional(),
|
|
10
|
+
warning: z.string().optional(),
|
|
11
|
+
type: z.enum(['add-on', 'example', 'starter', 'toolchain']),
|
|
12
|
+
command: z
|
|
13
|
+
.object({
|
|
14
|
+
command: z.string(),
|
|
15
|
+
args: z.array(z.string()).optional(),
|
|
16
|
+
})
|
|
17
|
+
.optional(),
|
|
18
|
+
routes: z
|
|
19
|
+
.array(z.object({
|
|
20
|
+
url: z.string().optional(),
|
|
21
|
+
name: z.string().optional(),
|
|
22
|
+
path: z.string(),
|
|
23
|
+
jsName: z.string(),
|
|
24
|
+
}))
|
|
25
|
+
.optional(),
|
|
26
|
+
packageAdditions: z
|
|
27
|
+
.object({
|
|
28
|
+
dependencies: z.record(z.string(), z.string()).optional(),
|
|
29
|
+
devDependencies: z.record(z.string(), z.string()).optional(),
|
|
30
|
+
scripts: z.record(z.string(), z.string()).optional(),
|
|
31
|
+
})
|
|
32
|
+
.optional(),
|
|
33
|
+
shadcnComponents: z.array(z.string()).optional(),
|
|
34
|
+
dependsOn: z.array(z.string()).optional(),
|
|
35
|
+
smallLogo: z.string().optional(),
|
|
36
|
+
logo: z.string().optional(),
|
|
37
|
+
addOnSpecialSteps: z.array(z.string()).optional(),
|
|
38
|
+
createSpecialSteps: z.array(z.string()).optional(),
|
|
39
|
+
});
|
|
40
|
+
export const StarterSchema = AddOnBaseSchema.extend({
|
|
41
|
+
framework: z.string(),
|
|
42
|
+
mode: z.string(),
|
|
43
|
+
typescript: z.boolean(),
|
|
44
|
+
tailwind: z.boolean(),
|
|
45
|
+
banner: z.string().optional(),
|
|
46
|
+
});
|
|
47
|
+
export const StarterCompiledSchema = StarterSchema.extend({
|
|
48
|
+
files: z.record(z.string(), z.string()),
|
|
49
|
+
deletedFiles: z.array(z.string()),
|
|
50
|
+
});
|
|
51
|
+
export const IntegrationSchema = z.object({
|
|
52
|
+
type: z.string(),
|
|
53
|
+
path: z.string(),
|
|
54
|
+
jsName: z.string(),
|
|
55
|
+
});
|
|
56
|
+
export const AddOnInfoSchema = AddOnBaseSchema.extend({
|
|
57
|
+
modes: z.array(z.string()),
|
|
58
|
+
integrations: z.array(IntegrationSchema).optional(),
|
|
59
|
+
phase: z.enum(['setup', 'add-on']),
|
|
60
|
+
readme: z.string().optional(),
|
|
61
|
+
});
|
|
62
|
+
export const AddOnCompiledSchema = AddOnInfoSchema.extend({
|
|
63
|
+
files: z.record(z.string(), z.string()),
|
|
64
|
+
deletedFiles: z.array(z.string()),
|
|
65
|
+
});
|
package/dist/utils.js
CHANGED
|
@@ -6,3 +6,12 @@ export function sortObject(obj) {
|
|
|
6
6
|
return acc;
|
|
7
7
|
}, {});
|
|
8
8
|
}
|
|
9
|
+
export function jsSafeName(name) {
|
|
10
|
+
return name
|
|
11
|
+
.split(/[^a-zA-Z0-9]/)
|
|
12
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
13
|
+
.join('');
|
|
14
|
+
}
|
|
15
|
+
export function formatCommand({ command, args, }) {
|
|
16
|
+
return `${command} ${args.join(' ')}`.trim();
|
|
17
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/cta-engine",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Tanstack Application Builder Engine",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -15,35 +15,32 @@
|
|
|
15
15
|
"url": "https://github.com/sponsors/tannerlinsley"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
|
-
"react",
|
|
19
18
|
"tanstack",
|
|
20
19
|
"router",
|
|
21
|
-
"create-
|
|
20
|
+
"create-tsrouter-app"
|
|
22
21
|
],
|
|
23
22
|
"author": "Jack Herrington <jherr@pobox.com>",
|
|
24
23
|
"license": "MIT",
|
|
25
24
|
"dependencies": {
|
|
26
|
-
"@clack/prompts": "^0.10.0",
|
|
27
|
-
"@modelcontextprotocol/sdk": "^1.6.0",
|
|
28
|
-
"chalk": "^5.4.1",
|
|
29
|
-
"commander": "^13.1.0",
|
|
30
25
|
"ejs": "^3.1.10",
|
|
31
26
|
"execa": "^9.5.2",
|
|
32
|
-
"
|
|
27
|
+
"ignore": "^7.0.3",
|
|
33
28
|
"memfs": "^4.17.0",
|
|
29
|
+
"parse-gitignore": "^2.0.0",
|
|
34
30
|
"prettier": "^3.5.0",
|
|
31
|
+
"rimraf": "^6.0.1",
|
|
35
32
|
"zod": "^3.24.2"
|
|
36
33
|
},
|
|
37
34
|
"devDependencies": {
|
|
38
35
|
"@tanstack/config": "^0.16.2",
|
|
39
36
|
"@types/ejs": "^3.1.5",
|
|
40
|
-
"@types/express": "^5.0.0",
|
|
41
37
|
"@types/node": "^22.13.4",
|
|
38
|
+
"@types/parse-gitignore": "^1.0.2",
|
|
39
|
+
"@vitest/coverage-v8": "3.1.1",
|
|
42
40
|
"eslint": "^9.20.0",
|
|
43
|
-
"eslint-plugin-react-hooks": "^5.1.0",
|
|
44
|
-
"eslint-plugin-unused-imports": "^4.1.4",
|
|
45
41
|
"typescript": "^5.6.3",
|
|
46
|
-
"vitest": "^3.0.8"
|
|
42
|
+
"vitest": "^3.0.8",
|
|
43
|
+
"vitest-fetch-mock": "^0.4.5"
|
|
47
44
|
},
|
|
48
45
|
"scripts": {}
|
|
49
46
|
}
|
package/src/add-ons.ts
CHANGED
|
@@ -1,100 +1,20 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { existsSync, readdirSync, statSync } from 'node:fs'
|
|
3
|
-
import { resolve } from 'node:path'
|
|
4
|
-
import chalk from 'chalk'
|
|
1
|
+
import { loadRemoteAddOn } from './custom-add-ons/add-on.js'
|
|
5
2
|
|
|
6
|
-
import {
|
|
7
|
-
import { DEFAULT_FRAMEWORK } from './constants.js'
|
|
8
|
-
import { readFileHelper } from './file-helper.js'
|
|
3
|
+
import type { AddOn, Framework, Mode } from './types.js'
|
|
9
4
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
function isDirectory(path: string): boolean {
|
|
13
|
-
return statSync(path).isDirectory()
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function findFilesRecursively(path: string, files: Record<string, string>) {
|
|
17
|
-
const dirFiles = readdirSync(path)
|
|
18
|
-
for (const file of dirFiles) {
|
|
19
|
-
const filePath = resolve(path, file)
|
|
20
|
-
if (isDirectory(filePath)) {
|
|
21
|
-
findFilesRecursively(filePath, files)
|
|
22
|
-
} else {
|
|
23
|
-
files[filePath] = readFileHelper(filePath)
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function getAllAddOns(
|
|
29
|
-
framework: Framework,
|
|
30
|
-
template: string,
|
|
31
|
-
): Promise<Array<AddOn>> {
|
|
32
|
-
const addOns: Array<AddOn> = []
|
|
33
|
-
|
|
34
|
-
for (const type of ['add-on', 'example']) {
|
|
35
|
-
const addOnsBase = resolve(getTemplatesRoot(), framework, type)
|
|
36
|
-
|
|
37
|
-
if (!existsSync(addOnsBase)) {
|
|
38
|
-
continue
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
for (const dir of await readdirSync(addOnsBase).filter((file) =>
|
|
42
|
-
isDirectory(resolve(addOnsBase, file)),
|
|
43
|
-
)) {
|
|
44
|
-
const filePath = resolve(addOnsBase, dir, 'info.json')
|
|
45
|
-
const fileContent = await readFile(filePath, 'utf-8')
|
|
46
|
-
const info = JSON.parse(fileContent)
|
|
47
|
-
|
|
48
|
-
if (!info.templates.includes(template)) {
|
|
49
|
-
continue
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
let packageAdditions: Record<string, string> = {}
|
|
53
|
-
if (existsSync(resolve(addOnsBase, dir, 'package.json'))) {
|
|
54
|
-
packageAdditions = JSON.parse(
|
|
55
|
-
await readFile(resolve(addOnsBase, dir, 'package.json'), 'utf-8'),
|
|
56
|
-
)
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
let readme: string | undefined
|
|
60
|
-
if (existsSync(resolve(addOnsBase, dir, 'README.md'))) {
|
|
61
|
-
readme = await readFile(resolve(addOnsBase, dir, 'README.md'), 'utf-8')
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const absoluteFiles: Record<string, string> = {}
|
|
65
|
-
const assetsDir = resolve(addOnsBase, dir, 'assets')
|
|
66
|
-
if (existsSync(assetsDir)) {
|
|
67
|
-
await findFilesRecursively(assetsDir, absoluteFiles)
|
|
68
|
-
}
|
|
69
|
-
const files: Record<string, string> = {}
|
|
70
|
-
for (const file of Object.keys(absoluteFiles)) {
|
|
71
|
-
files[file.replace(assetsDir, '.')] = absoluteFiles[file]
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
addOns.push({
|
|
75
|
-
...info,
|
|
76
|
-
id: dir,
|
|
77
|
-
type,
|
|
78
|
-
packageAdditions,
|
|
79
|
-
readme,
|
|
80
|
-
files,
|
|
81
|
-
deletedFiles: [],
|
|
82
|
-
})
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
return addOns
|
|
5
|
+
export function getAllAddOns(framework: Framework, mode: Mode): Array<AddOn> {
|
|
6
|
+
return framework.getAddOns().filter((a) => a.modes.includes(mode))
|
|
87
7
|
}
|
|
88
8
|
|
|
89
9
|
// Turn the list of chosen add-on IDs into a final list of add-ons by resolving dependencies
|
|
90
10
|
export async function finalizeAddOns(
|
|
91
11
|
framework: Framework,
|
|
92
|
-
|
|
12
|
+
mode: Mode,
|
|
93
13
|
chosenAddOnIDs: Array<string>,
|
|
94
14
|
): Promise<Array<AddOn>> {
|
|
95
15
|
const finalAddOnIDs = new Set(chosenAddOnIDs)
|
|
96
16
|
|
|
97
|
-
const addOns =
|
|
17
|
+
const addOns = getAllAddOns(framework, mode)
|
|
98
18
|
|
|
99
19
|
for (const addOnID of finalAddOnIDs) {
|
|
100
20
|
let addOn: AddOn | undefined
|
|
@@ -120,46 +40,10 @@ export async function finalizeAddOns(
|
|
|
120
40
|
const finalAddOns = [...finalAddOnIDs].map(
|
|
121
41
|
(id) => addOns.find((a) => a.id === id)!,
|
|
122
42
|
)
|
|
123
|
-
return finalAddOns
|
|
124
|
-
}
|
|
125
43
|
|
|
126
|
-
|
|
127
|
-
options: CliOptions,
|
|
128
|
-
{
|
|
129
|
-
forcedMode,
|
|
130
|
-
forcedAddOns = [],
|
|
131
|
-
}: {
|
|
132
|
-
forcedMode?: TemplateOptions
|
|
133
|
-
forcedAddOns?: Array<string>
|
|
134
|
-
},
|
|
135
|
-
) {
|
|
136
|
-
let mode = forcedMode
|
|
137
|
-
if (!mode) {
|
|
138
|
-
if (options.template) {
|
|
139
|
-
mode =
|
|
140
|
-
options.template === 'file-router'
|
|
141
|
-
? 'file-router'
|
|
142
|
-
: ('code-router' as TemplateOptions)
|
|
143
|
-
} else {
|
|
144
|
-
mode = 'code-router' as TemplateOptions
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
const addOns = await getAllAddOns(
|
|
148
|
-
options.framework || DEFAULT_FRAMEWORK,
|
|
149
|
-
mode,
|
|
150
|
-
)
|
|
151
|
-
for (const addOn of addOns.filter((a) => !forcedAddOns.includes(a.id))) {
|
|
152
|
-
console.log(`${chalk.bold(addOn.id)}: ${addOn.description}`)
|
|
153
|
-
}
|
|
44
|
+
return finalAddOns
|
|
154
45
|
}
|
|
155
46
|
|
|
156
47
|
function loadAddOn(addOn: AddOn): AddOn {
|
|
157
48
|
return addOn
|
|
158
49
|
}
|
|
159
|
-
|
|
160
|
-
export async function loadRemoteAddOn(url: string): Promise<AddOn> {
|
|
161
|
-
const response = await fetch(url)
|
|
162
|
-
const fileContent = await response.json()
|
|
163
|
-
fileContent.id = url
|
|
164
|
-
return fileContent
|
|
165
|
-
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { basename, resolve } from 'node:path'
|
|
2
|
+
|
|
3
|
+
import { CONFIG_FILE } from './constants.js'
|
|
4
|
+
import { finalizeAddOns } from './add-ons.js'
|
|
5
|
+
import { getFrameworkById } from './frameworks.js'
|
|
6
|
+
import { createMemoryEnvironment } from './environment.js'
|
|
7
|
+
import { createApp } from './create-app.js'
|
|
8
|
+
import {
|
|
9
|
+
readConfigFileFromEnvironment,
|
|
10
|
+
writeConfigFileToEnvironment,
|
|
11
|
+
} from './config-file.js'
|
|
12
|
+
import { formatCommand } from './utils.js'
|
|
13
|
+
import { packageManagerInstall } from './package-manager.js'
|
|
14
|
+
import {
|
|
15
|
+
isBase64,
|
|
16
|
+
recursivelyGatherFilesFromEnvironment,
|
|
17
|
+
} from './file-helpers.js'
|
|
18
|
+
import { mergePackageJSON } from './package-json.js'
|
|
19
|
+
import { runSpecialSteps } from './special-steps/index.js'
|
|
20
|
+
import { loadStarter } from './custom-add-ons/starter.js'
|
|
21
|
+
|
|
22
|
+
import type { Environment, Mode, Options } from './types.js'
|
|
23
|
+
import type { PersistedOptions } from './config-file.js'
|
|
24
|
+
|
|
25
|
+
export async function hasPendingGitChanges(
|
|
26
|
+
environment: Environment,
|
|
27
|
+
cwd: string,
|
|
28
|
+
) {
|
|
29
|
+
const { stdout } = await environment.execute(
|
|
30
|
+
'git',
|
|
31
|
+
['status', '--porcelain'],
|
|
32
|
+
cwd,
|
|
33
|
+
)
|
|
34
|
+
return stdout.length > 0
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async function createOptions(
|
|
38
|
+
json: PersistedOptions,
|
|
39
|
+
addOns: Array<string>,
|
|
40
|
+
targetDir: string,
|
|
41
|
+
): Promise<Options> {
|
|
42
|
+
const framework = getFrameworkById(json.framework)
|
|
43
|
+
|
|
44
|
+
const starter = json.starter ? await loadStarter(json.starter) : undefined
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
...json,
|
|
48
|
+
framework,
|
|
49
|
+
tailwind: true,
|
|
50
|
+
addOns: true,
|
|
51
|
+
chosenAddOns: await finalizeAddOns(framework!, json.mode as Mode, [
|
|
52
|
+
...json.chosenAddOns,
|
|
53
|
+
...addOns,
|
|
54
|
+
]),
|
|
55
|
+
targetDir,
|
|
56
|
+
starter,
|
|
57
|
+
} as Options
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async function runCreateApp(options: Required<Options>) {
|
|
61
|
+
const { environment, output } = createMemoryEnvironment(options.targetDir)
|
|
62
|
+
await createApp(environment, options)
|
|
63
|
+
return output
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export async function getCurrentConfiguration(
|
|
67
|
+
environment: Environment,
|
|
68
|
+
cwd: string,
|
|
69
|
+
) {
|
|
70
|
+
const persistedOptions = await readConfigFileFromEnvironment(environment, cwd)
|
|
71
|
+
if (!persistedOptions) {
|
|
72
|
+
environment.error(
|
|
73
|
+
'There is no .cta.json file in your project.',
|
|
74
|
+
'This is probably because this was created with an older version of create-tsrouter-app.',
|
|
75
|
+
)
|
|
76
|
+
return undefined
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return persistedOptions
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function writeFiles(
|
|
83
|
+
environment: Environment,
|
|
84
|
+
cwd: string,
|
|
85
|
+
output: {
|
|
86
|
+
files: Record<string, string>
|
|
87
|
+
deletedFiles: Array<string>
|
|
88
|
+
},
|
|
89
|
+
forced: boolean,
|
|
90
|
+
) {
|
|
91
|
+
const currentFiles = await recursivelyGatherFilesFromEnvironment(
|
|
92
|
+
environment,
|
|
93
|
+
cwd,
|
|
94
|
+
false,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
const overwrittenFiles: Array<string> = []
|
|
98
|
+
const changedFiles: Array<string> = []
|
|
99
|
+
for (const file of Object.keys(output.files)) {
|
|
100
|
+
const relativeFile = file.replace(cwd, '')
|
|
101
|
+
if (currentFiles[relativeFile]) {
|
|
102
|
+
if (currentFiles[relativeFile] !== output.files[file]) {
|
|
103
|
+
overwrittenFiles.push(relativeFile)
|
|
104
|
+
}
|
|
105
|
+
} else {
|
|
106
|
+
changedFiles.push(relativeFile)
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!forced && overwrittenFiles.length) {
|
|
111
|
+
environment.warn(
|
|
112
|
+
'The following will be overwritten',
|
|
113
|
+
[...overwrittenFiles, ...output.deletedFiles].join('\n'),
|
|
114
|
+
)
|
|
115
|
+
const shouldContinue = await environment.confirm('Do you want to continue?')
|
|
116
|
+
if (!shouldContinue) {
|
|
117
|
+
throw new Error('User cancelled')
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
for (const file of output.deletedFiles) {
|
|
122
|
+
if (environment.exists(resolve(cwd, file))) {
|
|
123
|
+
await environment.deleteFile(resolve(cwd, file))
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
environment.startStep({
|
|
128
|
+
id: 'write-files',
|
|
129
|
+
type: 'file',
|
|
130
|
+
message: 'Writing add-on files...',
|
|
131
|
+
})
|
|
132
|
+
|
|
133
|
+
for (const file of [...changedFiles, ...overwrittenFiles]) {
|
|
134
|
+
const fName = basename(file)
|
|
135
|
+
const contents = output.files[file]
|
|
136
|
+
if (fName === 'package.json') {
|
|
137
|
+
const currentJson = JSON.parse(
|
|
138
|
+
await environment.readFile(resolve(cwd, file)),
|
|
139
|
+
)
|
|
140
|
+
const newJSON = mergePackageJSON(currentJson, JSON.parse(contents))
|
|
141
|
+
environment.writeFile(
|
|
142
|
+
resolve(cwd, file),
|
|
143
|
+
JSON.stringify(newJSON, null, 2),
|
|
144
|
+
)
|
|
145
|
+
} else if (fName !== CONFIG_FILE) {
|
|
146
|
+
if (isBase64(contents)) {
|
|
147
|
+
await environment.writeFileBase64(resolve(cwd, file), contents)
|
|
148
|
+
} else {
|
|
149
|
+
await environment.writeFile(resolve(cwd, file), contents)
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
environment.finishStep('write-files', 'Add-on files written')
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
export async function runNewCommands(
|
|
158
|
+
environment: Environment,
|
|
159
|
+
originalOptions: PersistedOptions,
|
|
160
|
+
cwd: string,
|
|
161
|
+
output: {
|
|
162
|
+
commands: Array<{
|
|
163
|
+
command: string
|
|
164
|
+
args: Array<string>
|
|
165
|
+
}>
|
|
166
|
+
},
|
|
167
|
+
) {
|
|
168
|
+
const originalOutput = await runCreateApp({
|
|
169
|
+
...(await createOptions(originalOptions, [], cwd)),
|
|
170
|
+
} as Required<Options>)
|
|
171
|
+
|
|
172
|
+
const originalCommands = new Set(
|
|
173
|
+
originalOutput.commands.map((c) => [c.command, ...c.args].join(' ')),
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
for (const command of output.commands) {
|
|
177
|
+
const commandString = [command.command, ...command.args].join(' ')
|
|
178
|
+
if (!originalCommands.has(commandString)) {
|
|
179
|
+
environment.startStep({
|
|
180
|
+
id: 'run-commands',
|
|
181
|
+
type: 'command',
|
|
182
|
+
message: `Running ${formatCommand({ command: command.command, args: command.args })}...`,
|
|
183
|
+
})
|
|
184
|
+
await environment.execute(command.command, command.args, cwd)
|
|
185
|
+
environment.finishStep('run-commands', 'Setup commands complete')
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export async function addToApp(
|
|
191
|
+
environment: Environment,
|
|
192
|
+
addOns: Array<string>,
|
|
193
|
+
cwd: string,
|
|
194
|
+
options?: {
|
|
195
|
+
forced?: boolean
|
|
196
|
+
},
|
|
197
|
+
) {
|
|
198
|
+
const persistedOptions = await getCurrentConfiguration(environment, cwd)
|
|
199
|
+
if (!persistedOptions) {
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
if (!options?.forced && (await hasPendingGitChanges(environment, cwd))) {
|
|
204
|
+
environment.error(
|
|
205
|
+
'You have pending git changes.',
|
|
206
|
+
'Please commit or stash them before adding add-ons.',
|
|
207
|
+
)
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
environment.intro(`Adding ${addOns.join(', ')} to the project...`)
|
|
212
|
+
environment.startStep({
|
|
213
|
+
id: 'processing-new-app-setup',
|
|
214
|
+
type: 'file',
|
|
215
|
+
message: 'Processing new app setup...',
|
|
216
|
+
})
|
|
217
|
+
|
|
218
|
+
const newOptions = await createOptions(persistedOptions, addOns, cwd)
|
|
219
|
+
|
|
220
|
+
const output = await runCreateApp({
|
|
221
|
+
...newOptions,
|
|
222
|
+
targetDir: cwd,
|
|
223
|
+
} as Required<Options>)
|
|
224
|
+
|
|
225
|
+
await writeFiles(environment, cwd, output, !!options?.forced)
|
|
226
|
+
|
|
227
|
+
environment.finishStep(
|
|
228
|
+
'processing-new-app-setup',
|
|
229
|
+
'Application files written',
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
// Run any special steps for the new add-ons
|
|
233
|
+
|
|
234
|
+
const specialSteps = new Set<string>([])
|
|
235
|
+
for (const addOn of newOptions.chosenAddOns) {
|
|
236
|
+
for (const step of addOn.addOnSpecialSteps || []) {
|
|
237
|
+
if (addOns.includes(addOn.id)) {
|
|
238
|
+
specialSteps.add(step)
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (specialSteps.size) {
|
|
243
|
+
await runSpecialSteps(environment, newOptions, Array.from(specialSteps))
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Install dependencies
|
|
247
|
+
|
|
248
|
+
environment.startStep({
|
|
249
|
+
id: 'install-dependencies',
|
|
250
|
+
type: 'package-manager',
|
|
251
|
+
message: `Installing dependencies via ${newOptions.packageManager}...`,
|
|
252
|
+
})
|
|
253
|
+
const s = environment.spinner()
|
|
254
|
+
s.start(`Installing dependencies via ${newOptions.packageManager}...`)
|
|
255
|
+
await packageManagerInstall(
|
|
256
|
+
environment,
|
|
257
|
+
newOptions.targetDir,
|
|
258
|
+
newOptions.packageManager,
|
|
259
|
+
)
|
|
260
|
+
s.stop(`Installed dependencies`)
|
|
261
|
+
environment.finishStep('install-dependencies', 'Dependencies installed')
|
|
262
|
+
|
|
263
|
+
// Handle new commands
|
|
264
|
+
|
|
265
|
+
await runNewCommands(environment, persistedOptions, cwd, output)
|
|
266
|
+
|
|
267
|
+
environment.startStep({
|
|
268
|
+
id: 'write-config-file',
|
|
269
|
+
type: 'file',
|
|
270
|
+
message: 'Writing config file...',
|
|
271
|
+
})
|
|
272
|
+
writeConfigFileToEnvironment(environment, newOptions)
|
|
273
|
+
environment.finishStep('write-config-file', 'Config file written')
|
|
274
|
+
|
|
275
|
+
environment.outro(`Add-ons ${addOns.join(', ')} added!`)
|
|
276
|
+
}
|
package/src/config-file.ts
CHANGED
|
@@ -1,45 +1,76 @@
|
|
|
1
|
-
import { readFile } from 'node:fs/promises'
|
|
2
1
|
import { resolve } from 'node:path'
|
|
3
2
|
|
|
4
3
|
import { CONFIG_FILE } from './constants.js'
|
|
4
|
+
import { createDefaultEnvironment } from './environment.js'
|
|
5
5
|
|
|
6
|
-
import type { Environment, Options } from './types'
|
|
6
|
+
import type { Environment, Options } from './types.js'
|
|
7
7
|
|
|
8
|
-
export type PersistedOptions =
|
|
8
|
+
export type PersistedOptions = Omit<
|
|
9
9
|
Partial<Options>,
|
|
10
|
-
'addOns' | 'chosenAddOns'
|
|
10
|
+
'addOns' | 'chosenAddOns' | 'framework' | 'starter' | 'targetDir'
|
|
11
11
|
> & {
|
|
12
|
+
framework: string
|
|
12
13
|
version: number
|
|
13
|
-
|
|
14
|
+
chosenAddOns: Array<string>
|
|
15
|
+
starter?: string
|
|
14
16
|
}
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
targetDir
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
...options,
|
|
18
|
+
function createPersistedOptions(options: Options): PersistedOptions {
|
|
19
|
+
/* eslint-disable unused-imports/no-unused-vars */
|
|
20
|
+
const { chosenAddOns, framework, targetDir, ...rest } = options
|
|
21
|
+
/* eslint-enable unused-imports/no-unused-vars */
|
|
22
|
+
return {
|
|
23
|
+
...rest,
|
|
23
24
|
version: 1,
|
|
24
|
-
|
|
25
|
+
framework: options.framework.id,
|
|
26
|
+
chosenAddOns: options.chosenAddOns.map((addOn) => addOn.id),
|
|
27
|
+
starter: options.starter?.id ?? undefined,
|
|
25
28
|
}
|
|
26
|
-
|
|
27
|
-
delete persistedOptions.chosenAddOns
|
|
29
|
+
}
|
|
28
30
|
|
|
31
|
+
export async function writeConfigFileToEnvironment(
|
|
32
|
+
environment: Environment,
|
|
33
|
+
options: Options,
|
|
34
|
+
) {
|
|
29
35
|
await environment.writeFile(
|
|
30
|
-
resolve(targetDir, CONFIG_FILE),
|
|
31
|
-
JSON.stringify(
|
|
36
|
+
resolve(options.targetDir, CONFIG_FILE),
|
|
37
|
+
JSON.stringify(createPersistedOptions(options), null, 2),
|
|
32
38
|
)
|
|
33
39
|
}
|
|
34
40
|
|
|
35
|
-
export async function
|
|
41
|
+
export async function readConfigFileFromEnvironment(
|
|
42
|
+
environment: Environment,
|
|
36
43
|
targetDir: string,
|
|
37
44
|
): Promise<PersistedOptions | null> {
|
|
38
45
|
try {
|
|
39
46
|
const configFile = resolve(targetDir, CONFIG_FILE)
|
|
40
|
-
const config = await readFile(configFile
|
|
41
|
-
|
|
47
|
+
const config = await environment.readFile(configFile)
|
|
48
|
+
|
|
49
|
+
const originalJSON = JSON.parse(config)
|
|
50
|
+
|
|
51
|
+
// Look for markers out outdated config files and upgrade the format on the fly (it will be written in the updated version after we add add-ons)
|
|
52
|
+
if (originalJSON.existingAddOns) {
|
|
53
|
+
if (originalJSON.framework === 'react') {
|
|
54
|
+
originalJSON.framework = 'react-cra'
|
|
55
|
+
}
|
|
56
|
+
originalJSON.chosenAddOns = originalJSON.existingAddOns
|
|
57
|
+
delete originalJSON.existingAddOns
|
|
58
|
+
delete originalJSON.addOns
|
|
59
|
+
if (originalJSON.toolchain && originalJSON.toolchain !== 'none') {
|
|
60
|
+
originalJSON.chosenAddOns.push(originalJSON.toolchain)
|
|
61
|
+
}
|
|
62
|
+
delete originalJSON.toolchain
|
|
63
|
+
delete originalJSON.variableValues
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return originalJSON
|
|
42
67
|
} catch {
|
|
43
68
|
return null
|
|
44
69
|
}
|
|
45
70
|
}
|
|
71
|
+
|
|
72
|
+
export async function readConfigFile(
|
|
73
|
+
targetDir: string,
|
|
74
|
+
): Promise<PersistedOptions | null> {
|
|
75
|
+
return readConfigFileFromEnvironment(createDefaultEnvironment(), targetDir)
|
|
76
|
+
}
|
package/src/constants.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import type { Framework } from './types.js'
|
|
2
|
-
|
|
3
1
|
export const CODE_ROUTER = 'code-router'
|
|
4
2
|
export const FILE_ROUTER = 'file-router'
|
|
5
3
|
|
|
6
|
-
export const SUPPORTED_FRAMEWORKS: Array<Framework> = ['solid', 'react']
|
|
7
|
-
export const DEFAULT_FRAMEWORK: Framework = 'react'
|
|
8
|
-
|
|
9
4
|
export const CONFIG_FILE = '.cta.json'
|