alchemy 0.45.5 → 0.46.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/README.md +2 -2
- package/bin/alchemy.mjs +19285 -15137
- package/bin/alchemy.ts +14 -56
- package/bin/commands/create.ts +307 -137
- package/bin/commands/deploy.ts +23 -0
- package/bin/commands/destroy.ts +19 -0
- package/bin/commands/dev.ts +21 -0
- package/bin/commands/login.ts +66 -0
- package/bin/commands/run.ts +29 -0
- package/bin/services/dependencies.ts +0 -5
- package/bin/services/execute-alchemy.ts +160 -0
- package/bin/services/git.ts +27 -0
- package/bin/services/github-workflow.ts +229 -0
- package/bin/services/package-manager.ts +51 -68
- package/bin/services/template-manager.ts +10 -21
- package/bin/trpc.ts +3 -0
- package/bin/types.ts +4 -2
- package/lib/apply.d.ts +2 -0
- package/lib/apply.d.ts.map +1 -1
- package/lib/apply.js +26 -8
- package/lib/apply.js.map +1 -1
- package/lib/build-date.d.ts +1 -1
- package/lib/build-date.js +1 -1
- package/lib/cloudflare/ai.d.ts +8 -4
- package/lib/cloudflare/ai.d.ts.map +1 -1
- package/lib/cloudflare/ai.js +6 -8
- package/lib/cloudflare/ai.js.map +1 -1
- package/lib/cloudflare/analytics-engine.d.ts +11 -7
- package/lib/cloudflare/analytics-engine.d.ts.map +1 -1
- package/lib/cloudflare/analytics-engine.js +11 -9
- package/lib/cloudflare/analytics-engine.js.map +1 -1
- package/lib/cloudflare/{types.d.ts → api-response.d.ts} +6 -1
- package/lib/cloudflare/api-response.d.ts.map +1 -0
- package/lib/cloudflare/api-response.js +38 -0
- package/lib/cloudflare/api-response.js.map +1 -0
- package/lib/cloudflare/auth-wrangler.d.ts +25 -0
- package/lib/cloudflare/auth-wrangler.d.ts.map +1 -0
- package/lib/cloudflare/auth-wrangler.js +224 -0
- package/lib/cloudflare/auth-wrangler.js.map +1 -0
- package/lib/cloudflare/auth.d.ts.map +1 -1
- package/lib/cloudflare/auth.js +7 -116
- package/lib/cloudflare/auth.js.map +1 -1
- package/lib/cloudflare/browser-rendering.d.ts +12 -3
- package/lib/cloudflare/browser-rendering.d.ts.map +1 -1
- package/lib/cloudflare/browser-rendering.js +12 -2
- package/lib/cloudflare/browser-rendering.js.map +1 -1
- package/lib/cloudflare/bundle/fs.d.ts.map +1 -1
- package/lib/cloudflare/bundle/fs.js +3 -0
- package/lib/cloudflare/bundle/fs.js.map +1 -1
- package/lib/cloudflare/bundle/internal-worker-bundle.d.ts +6 -0
- package/lib/cloudflare/bundle/internal-worker-bundle.d.ts.map +1 -0
- package/lib/cloudflare/bundle/internal-worker-bundle.js +14 -0
- package/lib/cloudflare/bundle/internal-worker-bundle.js.map +1 -0
- package/lib/cloudflare/compatibility-presets.d.ts +22 -0
- package/lib/cloudflare/compatibility-presets.d.ts.map +1 -0
- package/lib/cloudflare/compatibility-presets.js +27 -0
- package/lib/cloudflare/compatibility-presets.js.map +1 -0
- package/lib/cloudflare/container.d.ts +6 -2
- package/lib/cloudflare/container.d.ts.map +1 -1
- package/lib/cloudflare/container.js +48 -4
- package/lib/cloudflare/container.js.map +1 -1
- package/lib/cloudflare/dispatch-namespace.d.ts +5 -0
- package/lib/cloudflare/dispatch-namespace.d.ts.map +1 -1
- package/lib/cloudflare/dispatch-namespace.js +8 -0
- package/lib/cloudflare/dispatch-namespace.js.map +1 -1
- package/lib/cloudflare/durable-object-namespace.d.ts +23 -15
- package/lib/cloudflare/durable-object-namespace.d.ts.map +1 -1
- package/lib/cloudflare/durable-object-namespace.js +22 -21
- package/lib/cloudflare/durable-object-namespace.js.map +1 -1
- package/lib/cloudflare/hyperdrive.d.ts +19 -5
- package/lib/cloudflare/hyperdrive.d.ts.map +1 -1
- package/lib/cloudflare/hyperdrive.js +14 -0
- package/lib/cloudflare/hyperdrive.js.map +1 -1
- package/lib/cloudflare/images.d.ts +27 -17
- package/lib/cloudflare/images.d.ts.map +1 -1
- package/lib/cloudflare/images.js +13 -8
- package/lib/cloudflare/images.js.map +1 -1
- package/lib/cloudflare/index.d.ts +1 -3
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +1 -3
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/miniflare/miniflare.d.ts +3 -3
- package/lib/cloudflare/miniflare/miniflare.d.ts.map +1 -1
- package/lib/cloudflare/miniflare/miniflare.js +7 -7
- package/lib/cloudflare/miniflare/miniflare.js.map +1 -1
- package/lib/cloudflare/miniflare/{mixed-mode.d.ts → remote-binding-proxy.d.ts} +5 -5
- package/lib/cloudflare/miniflare/remote-binding-proxy.d.ts.map +1 -0
- package/lib/cloudflare/miniflare/{mixed-mode.js → remote-binding-proxy.js} +16 -52
- package/lib/cloudflare/miniflare/remote-binding-proxy.js.map +1 -0
- package/lib/cloudflare/state.d.ts +26 -0
- package/lib/cloudflare/state.d.ts.map +1 -0
- package/lib/cloudflare/state.js +14 -0
- package/lib/cloudflare/state.js.map +1 -0
- package/lib/cloudflare/user.d.ts +2 -2
- package/lib/cloudflare/user.d.ts.map +1 -1
- package/lib/cloudflare/user.js +7 -21
- package/lib/cloudflare/user.js.map +1 -1
- package/lib/cloudflare/vectorize-index.d.ts.map +1 -1
- package/lib/cloudflare/vectorize-index.js +5 -2
- package/lib/cloudflare/vectorize-index.js.map +1 -1
- package/lib/cloudflare/version-metadata.d.ts +15 -3
- package/lib/cloudflare/version-metadata.d.ts.map +1 -1
- package/lib/cloudflare/version-metadata.js +11 -2
- package/lib/cloudflare/version-metadata.js.map +1 -1
- package/lib/cloudflare/vite.d.ts.map +1 -1
- package/lib/cloudflare/vite.js +2 -1
- package/lib/cloudflare/vite.js.map +1 -1
- package/lib/cloudflare/worker-metadata.d.ts +13 -2
- package/lib/cloudflare/worker-metadata.d.ts.map +1 -1
- package/lib/cloudflare/worker-metadata.js +10 -15
- package/lib/cloudflare/worker-metadata.js.map +1 -1
- package/lib/cloudflare/worker-subdomain.d.ts +7 -0
- package/lib/cloudflare/worker-subdomain.d.ts.map +1 -1
- package/lib/cloudflare/worker-subdomain.js +17 -22
- package/lib/cloudflare/worker-subdomain.js.map +1 -1
- package/lib/cloudflare/{worker/tail.d.ts → worker-tail.d.ts} +2 -2
- package/lib/cloudflare/worker-tail.d.ts.map +1 -0
- package/lib/cloudflare/{worker/tail.js → worker-tail.js} +11 -9
- package/lib/cloudflare/worker-tail.js.map +1 -0
- package/lib/cloudflare/worker.d.ts +18 -8
- package/lib/cloudflare/worker.d.ts.map +1 -1
- package/lib/cloudflare/worker.js +32 -8
- package/lib/cloudflare/worker.js.map +1 -1
- package/lib/cloudflare/workflow.d.ts +22 -11
- package/lib/cloudflare/workflow.d.ts.map +1 -1
- package/lib/cloudflare/workflow.js +23 -18
- package/lib/cloudflare/workflow.js.map +1 -1
- package/lib/context.d.ts +2 -2
- package/lib/context.d.ts.map +1 -1
- package/lib/docker/api.d.ts.map +1 -1
- package/lib/docker/api.js +30 -8
- package/lib/docker/api.js.map +1 -1
- package/lib/fs/file-system-state-store.d.ts +5 -20
- package/lib/fs/file-system-state-store.d.ts.map +1 -1
- package/lib/fs/file-system-state-store.js +5 -121
- package/lib/fs/file-system-state-store.js.map +1 -1
- package/lib/fs/index.d.ts +0 -1
- package/lib/fs/index.d.ts.map +1 -1
- package/lib/fs/index.js +0 -1
- package/lib/fs/index.js.map +1 -1
- package/lib/llms.cloudflare.txt +6 -5
- package/lib/planetscale/password.js +1 -1
- package/lib/planetscale/password.js.map +1 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +3 -6
- package/lib/scope.js.map +1 -1
- package/lib/state/cloudflare-state-store.d.ts +34 -0
- package/lib/state/cloudflare-state-store.d.ts.map +1 -0
- package/lib/state/cloudflare-state-store.js +116 -0
- package/lib/state/cloudflare-state-store.js.map +1 -0
- package/lib/state/d1-state-store.d.ts +15 -0
- package/lib/state/d1-state-store.d.ts.map +1 -0
- package/lib/{cloudflare → state}/d1-state-store.js +31 -27
- package/lib/state/d1-state-store.js.map +1 -0
- package/lib/{cloudflare/do-state-store/types.d.ts → state/dofs-state-store/api.d.ts} +1 -1
- package/lib/state/dofs-state-store/api.d.ts.map +1 -0
- package/lib/state/dofs-state-store/api.js +1 -0
- package/lib/state/dofs-state-store/api.js.map +1 -0
- package/lib/{cloudflare/do-state-store/store.d.ts → state/dofs-state-store/index.d.ts} +10 -5
- package/lib/state/dofs-state-store/index.d.ts.map +1 -0
- package/lib/{cloudflare/do-state-store/store.js → state/dofs-state-store/index.js} +15 -11
- package/lib/state/dofs-state-store/index.js.map +1 -0
- package/lib/{cloudflare/do-state-store/internal.d.ts → state/dofs-state-store/store.d.ts} +4 -5
- package/lib/state/dofs-state-store/store.d.ts.map +1 -0
- package/lib/{cloudflare/do-state-store/internal.js → state/dofs-state-store/store.js} +7 -22
- package/lib/state/dofs-state-store/store.js.map +1 -0
- package/lib/state/file-system-state-store.d.ts +21 -0
- package/lib/state/file-system-state-store.d.ts.map +1 -0
- package/lib/state/file-system-state-store.js +122 -0
- package/lib/state/file-system-state-store.js.map +1 -0
- package/lib/state/index.d.ts +7 -0
- package/lib/state/index.d.ts.map +1 -0
- package/lib/state/index.js +7 -0
- package/lib/state/index.js.map +1 -0
- package/lib/state/migrations.d.ts +2 -0
- package/lib/state/migrations.d.ts.map +1 -0
- package/lib/state/migrations.js +3 -0
- package/lib/state/migrations.js.map +1 -0
- package/lib/state/operations.d.ts +36 -0
- package/lib/state/operations.d.ts.map +1 -0
- package/lib/state/operations.js +126 -0
- package/lib/state/operations.js.map +1 -0
- package/lib/state/proxy.d.ts +53 -0
- package/lib/state/proxy.d.ts.map +1 -0
- package/lib/state/proxy.js +65 -0
- package/lib/state/proxy.js.map +1 -0
- package/lib/{cloudflare → state}/r2-rest-state-store.d.ts +3 -1
- package/lib/state/r2-rest-state-store.d.ts.map +1 -0
- package/lib/{cloudflare → state}/r2-rest-state-store.js +6 -4
- package/lib/state/r2-rest-state-store.js.map +1 -0
- package/lib/state/schema.d.ts.map +1 -0
- package/lib/state/schema.js.map +1 -0
- package/lib/{sqlite → state}/sqlite-state-store.d.ts +5 -3
- package/lib/state/sqlite-state-store.d.ts.map +1 -0
- package/lib/{sqlite → state}/sqlite-state-store.js +15 -6
- package/lib/state/sqlite-state-store.js.map +1 -0
- package/lib/test/vitest.d.ts.map +1 -1
- package/lib/test/vitest.js +3 -6
- package/lib/test/vitest.js.map +1 -1
- package/lib/util/detect-node-runtime.d.ts +3 -0
- package/lib/util/detect-node-runtime.d.ts.map +1 -0
- package/lib/util/detect-node-runtime.js +10 -0
- package/lib/util/detect-node-runtime.js.map +1 -0
- package/lib/util/detect-package-manager.d.ts +2 -2
- package/lib/util/detect-package-manager.d.ts.map +1 -1
- package/lib/util/detect-package-manager.js +15 -5
- package/lib/util/detect-package-manager.js.map +1 -1
- package/lib/util/http-server.d.ts.map +1 -0
- package/lib/{cloudflare/miniflare → util}/http-server.js +1 -1
- package/lib/util/http-server.js.map +1 -0
- package/lib/util/memoize.d.ts +2 -0
- package/lib/util/memoize.d.ts.map +1 -1
- package/lib/util/memoize.js +14 -7
- package/lib/util/memoize.js.map +1 -1
- package/lib/util/neverthrow.d.ts +9 -0
- package/lib/util/neverthrow.d.ts.map +1 -0
- package/lib/util/neverthrow.js +29 -0
- package/lib/util/neverthrow.js.map +1 -0
- package/package.json +20 -20
- package/src/apply.ts +31 -10
- package/src/build-date.ts +1 -1
- package/src/cloudflare/ai.ts +10 -5
- package/src/cloudflare/analytics-engine.ts +20 -11
- package/src/cloudflare/{types.ts → api-response.ts} +31 -0
- package/src/cloudflare/auth-wrangler.ts +314 -0
- package/src/cloudflare/auth.ts +8 -156
- package/src/cloudflare/browser-rendering.ts +16 -2
- package/src/cloudflare/bundle/fs.ts +5 -0
- package/src/cloudflare/bundle/internal-worker-bundle.ts +21 -0
- package/src/cloudflare/compatibility-presets.ts +34 -0
- package/src/cloudflare/container.ts +77 -6
- package/src/cloudflare/dispatch-namespace.ts +28 -0
- package/src/cloudflare/durable-object-namespace.ts +38 -27
- package/src/cloudflare/hyperdrive.ts +19 -5
- package/src/cloudflare/images.ts +32 -17
- package/src/cloudflare/index.ts +1 -3
- package/src/cloudflare/miniflare/miniflare.ts +10 -7
- package/src/cloudflare/miniflare/{mixed-mode.ts → remote-binding-proxy.ts} +25 -75
- package/src/cloudflare/state.ts +35 -0
- package/src/cloudflare/user.ts +55 -70
- package/src/cloudflare/vectorize-index.ts +7 -2
- package/src/cloudflare/version-metadata.ts +19 -2
- package/src/cloudflare/vite.ts +2 -1
- package/src/cloudflare/worker-metadata.ts +18 -43
- package/src/cloudflare/worker-subdomain.ts +43 -37
- package/src/cloudflare/{worker/tail.ts → worker-tail.ts} +13 -10
- package/src/cloudflare/worker.ts +66 -20
- package/src/cloudflare/workflow.ts +38 -19
- package/src/context.ts +2 -2
- package/src/docker/api.ts +33 -8
- package/src/fs/file-system-state-store.ts +5 -148
- package/src/fs/index.ts +0 -1
- package/src/llms.cloudflare.txt +6 -5
- package/src/planetscale/password.ts +1 -1
- package/src/scope.ts +3 -6
- package/src/state/cloudflare-state-store.ts +170 -0
- package/src/state/d1-state-store.ts +102 -0
- package/src/{cloudflare/do-state-store/store.ts → state/dofs-state-store/index.ts} +20 -13
- package/src/{cloudflare/do-state-store/internal.ts → state/dofs-state-store/store.ts} +9 -27
- package/src/state/file-system-state-store.ts +149 -0
- package/src/state/index.ts +6 -0
- package/src/state/migrations.ts +9 -0
- package/src/state/operations.ts +152 -0
- package/src/state/proxy.ts +132 -0
- package/src/{cloudflare → state}/r2-rest-state-store.ts +11 -8
- package/src/{sqlite → state}/sqlite-state-store.ts +18 -10
- package/src/test/vitest.ts +8 -6
- package/src/util/detect-node-runtime.ts +12 -0
- package/src/util/detect-package-manager.ts +19 -6
- package/src/{cloudflare/miniflare → util}/http-server.ts +1 -1
- package/src/util/memoize.ts +18 -7
- package/src/util/neverthrow.ts +36 -0
- package/templates/astro/package.json +3 -3
- package/templates/nuxt/package.json +3 -3
- package/templates/react-router/package.json +3 -3
- package/templates/rwsdk/alchemy.run.ts +1 -1
- package/templates/rwsdk/package.json +3 -3
- package/templates/sveltekit/package.json +3 -3
- package/templates/tanstack-start/package.json +3 -3
- package/templates/typescript/package.json +3 -2
- package/templates/typescript/tsconfig.json +1 -0
- package/templates/vite/package.json +3 -3
- package/workers/cloudflare-state-store.js +5638 -0
- package/workers/cloudflare-state-store.ts +108 -0
- package/workers/{do-state-store.js → dofs-state-store.js} +4 -4
- package/workers/{do-state-store.ts → dofs-state-store.ts} +12 -8
- package/workers/{mixed-mode-proxy-worker.js → remote-binding-proxy.js} +3 -3
- package/workers/remote-binding-proxy.ts +45 -0
- package/lib/cloudflare/d1-state-store.d.ts +0 -10
- package/lib/cloudflare/d1-state-store.d.ts.map +0 -1
- package/lib/cloudflare/d1-state-store.js.map +0 -1
- package/lib/cloudflare/do-state-store/index.d.ts +0 -2
- package/lib/cloudflare/do-state-store/index.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/index.js +0 -2
- package/lib/cloudflare/do-state-store/index.js.map +0 -1
- package/lib/cloudflare/do-state-store/internal.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/internal.js.map +0 -1
- package/lib/cloudflare/do-state-store/store.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/store.js.map +0 -1
- package/lib/cloudflare/do-state-store/types.d.ts.map +0 -1
- package/lib/cloudflare/do-state-store/types.js +0 -1
- package/lib/cloudflare/do-state-store/types.js.map +0 -1
- package/lib/cloudflare/miniflare/http-server.d.ts.map +0 -1
- package/lib/cloudflare/miniflare/http-server.js.map +0 -1
- package/lib/cloudflare/miniflare/mixed-mode.d.ts.map +0 -1
- package/lib/cloudflare/miniflare/mixed-mode.js.map +0 -1
- package/lib/cloudflare/r2-rest-state-store.d.ts.map +0 -1
- package/lib/cloudflare/r2-rest-state-store.js.map +0 -1
- package/lib/cloudflare/types.d.ts.map +0 -1
- package/lib/cloudflare/types.js +0 -19
- package/lib/cloudflare/types.js.map +0 -1
- package/lib/cloudflare/worker/shared.d.ts +0 -4
- package/lib/cloudflare/worker/shared.d.ts.map +0 -1
- package/lib/cloudflare/worker/shared.js +0 -21
- package/lib/cloudflare/worker/shared.js.map +0 -1
- package/lib/cloudflare/worker/tail.d.ts.map +0 -1
- package/lib/cloudflare/worker/tail.js.map +0 -1
- package/lib/sqlite/base-sqlite-state-store.d.ts +0 -31
- package/lib/sqlite/base-sqlite-state-store.d.ts.map +0 -1
- package/lib/sqlite/base-sqlite-state-store.js +0 -124
- package/lib/sqlite/base-sqlite-state-store.js.map +0 -1
- package/lib/sqlite/index.d.ts +0 -2
- package/lib/sqlite/index.d.ts.map +0 -1
- package/lib/sqlite/index.js +0 -2
- package/lib/sqlite/index.js.map +0 -1
- package/lib/sqlite/schema.d.ts.map +0 -1
- package/lib/sqlite/schema.js.map +0 -1
- package/lib/sqlite/sqlite-state-store.d.ts.map +0 -1
- package/lib/sqlite/sqlite-state-store.js.map +0 -1
- package/src/cloudflare/d1-state-store.ts +0 -105
- package/src/cloudflare/do-state-store/index.ts +0 -1
- package/src/cloudflare/worker/shared.ts +0 -30
- package/src/sqlite/base-sqlite-state-store.ts +0 -199
- package/src/sqlite/index.ts +0 -1
- package/templates/typescript/src/worker.js +0 -5
- package/workers/mixed-mode-proxy-worker.ts +0 -46
- /package/drizzle/{0000_busy_mauler.sql → default/0000_busy_mauler.sql} +0 -0
- /package/drizzle/{0001_concerned_iceman.sql → default/0001_concerned_iceman.sql} +0 -0
- /package/drizzle/{meta → default/meta}/0000_snapshot.json +0 -0
- /package/drizzle/{meta → default/meta}/0001_snapshot.json +0 -0
- /package/drizzle/{meta → default/meta}/_journal.json +0 -0
- /package/lib/{sqlite → state}/schema.d.ts +0 -0
- /package/lib/{sqlite → state}/schema.js +0 -0
- /package/lib/{cloudflare/miniflare → util}/http-server.d.ts +0 -0
- /package/src/{cloudflare/do-state-store/types.ts → state/dofs-state-store/api.ts} +0 -0
- /package/src/{sqlite → state}/schema.ts +0 -0
package/bin/alchemy.ts
CHANGED
|
@@ -1,64 +1,22 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import { createCli
|
|
4
|
-
import {
|
|
3
|
+
import { createCli } from "trpc-cli";
|
|
4
|
+
import { create } from "./commands/create.ts";
|
|
5
|
+
import { deploy } from "./commands/deploy.ts";
|
|
6
|
+
import { destroy } from "./commands/destroy.ts";
|
|
7
|
+
import { dev } from "./commands/dev.ts";
|
|
8
|
+
import { login } from "./commands/login.ts";
|
|
9
|
+
import { run } from "./commands/run.ts";
|
|
5
10
|
import { getPackageVersion } from "./services/get-package-version.ts";
|
|
6
|
-
import {
|
|
7
|
-
EditorSchema,
|
|
8
|
-
PackageManagerSchema,
|
|
9
|
-
ProjectNameSchema,
|
|
10
|
-
TemplateSchema,
|
|
11
|
-
type CreateInput,
|
|
12
|
-
} from "./types.ts";
|
|
13
|
-
|
|
14
|
-
const t = trpcServer.initTRPC.create();
|
|
11
|
+
import { t } from "./trpc.ts";
|
|
15
12
|
|
|
16
13
|
const router = t.router({
|
|
17
|
-
create
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
ProjectNameSchema.optional(),
|
|
24
|
-
z
|
|
25
|
-
.object({
|
|
26
|
-
template: TemplateSchema.optional(),
|
|
27
|
-
yes: z
|
|
28
|
-
.boolean()
|
|
29
|
-
.optional()
|
|
30
|
-
.default(false)
|
|
31
|
-
.describe("Skip prompts and use defaults"),
|
|
32
|
-
overwrite: z
|
|
33
|
-
.boolean()
|
|
34
|
-
.optional()
|
|
35
|
-
.default(false)
|
|
36
|
-
.describe("Overwrite existing directory"),
|
|
37
|
-
install: z
|
|
38
|
-
.boolean()
|
|
39
|
-
.optional()
|
|
40
|
-
.describe("Install dependencies after scaffolding"),
|
|
41
|
-
pm: PackageManagerSchema.optional().describe(
|
|
42
|
-
"Package manager to use (bun, npm, pnpm, yarn)",
|
|
43
|
-
),
|
|
44
|
-
vibeRules: EditorSchema.optional().describe(
|
|
45
|
-
"Setup vibe-rules for the specified editor (cursor, windsurf, vscode, zed, claude-code, gemini, codex, amp, clinerules, roo, unified)",
|
|
46
|
-
),
|
|
47
|
-
})
|
|
48
|
-
.optional()
|
|
49
|
-
.default({}),
|
|
50
|
-
]),
|
|
51
|
-
)
|
|
52
|
-
.mutation(async ({ input }) => {
|
|
53
|
-
const [name, options] = input;
|
|
54
|
-
const isTest = process.env.NODE_ENV === "test";
|
|
55
|
-
const combinedInput: CreateInput = {
|
|
56
|
-
name,
|
|
57
|
-
...options,
|
|
58
|
-
yes: isTest || options.yes,
|
|
59
|
-
};
|
|
60
|
-
await createAlchemy(combinedInput);
|
|
61
|
-
}),
|
|
14
|
+
create,
|
|
15
|
+
login,
|
|
16
|
+
deploy,
|
|
17
|
+
destroy,
|
|
18
|
+
dev,
|
|
19
|
+
run,
|
|
62
20
|
});
|
|
63
21
|
|
|
64
22
|
export type AppRouter = typeof router;
|
package/bin/commands/create.ts
CHANGED
|
@@ -13,122 +13,214 @@ import {
|
|
|
13
13
|
import * as fs from "fs-extra";
|
|
14
14
|
import { resolve } from "node:path";
|
|
15
15
|
import pc from "picocolors";
|
|
16
|
-
|
|
16
|
+
import z from "zod";
|
|
17
|
+
import { detectPackageManager } from "../../src/util/detect-package-manager.ts";
|
|
17
18
|
import { throwWithContext } from "../errors.ts";
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} from "../services/package-manager.ts";
|
|
19
|
+
import { initializeGitRepo, isGitInstalled } from "../services/git.ts";
|
|
20
|
+
import { addGitHubWorkflowToAlchemy } from "../services/github-workflow.ts";
|
|
21
|
+
import { installDependencies } from "../services/package-manager.ts";
|
|
22
22
|
import { copyTemplate } from "../services/template-manager.ts";
|
|
23
23
|
import { ensureVibeRulesPostinstall } from "../services/vibe-rules.ts";
|
|
24
|
+
import { t } from "../trpc.ts";
|
|
24
25
|
import type {
|
|
25
26
|
CreateInput,
|
|
26
27
|
EditorType,
|
|
27
28
|
ProjectContext,
|
|
28
29
|
TemplateType,
|
|
29
30
|
} from "../types.ts";
|
|
30
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
EditorSchema,
|
|
33
|
+
PackageManagerSchema,
|
|
34
|
+
ProjectNameSchema,
|
|
35
|
+
TEMPLATE_DEFINITIONS,
|
|
36
|
+
TemplateSchema,
|
|
37
|
+
} from "../types.ts";
|
|
31
38
|
|
|
32
39
|
const isTest = process.env.NODE_ENV === "test";
|
|
33
40
|
|
|
41
|
+
export const create = t.procedure
|
|
42
|
+
.meta({
|
|
43
|
+
description: "Create a new Alchemy project",
|
|
44
|
+
negateBooleans: true,
|
|
45
|
+
})
|
|
46
|
+
.input(
|
|
47
|
+
z.tuple([
|
|
48
|
+
ProjectNameSchema.optional(),
|
|
49
|
+
z.object({
|
|
50
|
+
template: TemplateSchema.optional(),
|
|
51
|
+
yes: z.boolean().optional().describe("Skip prompts and use defaults"),
|
|
52
|
+
overwrite: z
|
|
53
|
+
.boolean()
|
|
54
|
+
.optional()
|
|
55
|
+
.describe("Overwrite existing directory"),
|
|
56
|
+
install: z
|
|
57
|
+
.boolean()
|
|
58
|
+
.optional()
|
|
59
|
+
.describe("Install dependencies after scaffolding"),
|
|
60
|
+
pm: PackageManagerSchema.optional().describe(
|
|
61
|
+
"Package manager to use (bun, npm, pnpm, yarn)",
|
|
62
|
+
),
|
|
63
|
+
vibeRules: EditorSchema.optional().describe(
|
|
64
|
+
"Setup vibe-rules for the specified editor (cursor, windsurf, vscode, zed, claude-code, gemini, codex, amp, clinerules, roo, unified)",
|
|
65
|
+
),
|
|
66
|
+
githubActions: z
|
|
67
|
+
.boolean()
|
|
68
|
+
.optional()
|
|
69
|
+
.describe("Setup GitHub Actions for PR previews"),
|
|
70
|
+
git: z.boolean().optional().describe("Initialise a git repository"),
|
|
71
|
+
}),
|
|
72
|
+
]),
|
|
73
|
+
)
|
|
74
|
+
.mutation(async ({ input }) => {
|
|
75
|
+
const [name, options] = input;
|
|
76
|
+
const isTest = process.env.NODE_ENV === "test";
|
|
77
|
+
const combinedInput: CreateInput = {
|
|
78
|
+
name,
|
|
79
|
+
...options,
|
|
80
|
+
yes: isTest || options.yes,
|
|
81
|
+
};
|
|
82
|
+
await createAlchemy(combinedInput);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
async function createAlchemy(cliOptions: CreateInput): Promise<void> {
|
|
86
|
+
try {
|
|
87
|
+
intro(pc.cyan("🧪 Welcome to Alchemy!"));
|
|
88
|
+
|
|
89
|
+
const context = await createProjectContext(cliOptions);
|
|
90
|
+
|
|
91
|
+
await handleDirectoryOverwrite(context);
|
|
92
|
+
await initializeTemplate(context);
|
|
93
|
+
await setupVibeRules(context);
|
|
94
|
+
await setupGitHubActions(context);
|
|
95
|
+
await setupGit(context);
|
|
96
|
+
|
|
97
|
+
displayNextSteps(context);
|
|
98
|
+
displaySuccessMessage(context);
|
|
99
|
+
} catch (error) {
|
|
100
|
+
handleError(error);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
34
104
|
async function createProjectContext(
|
|
35
105
|
cliOptions: CreateInput,
|
|
36
106
|
): Promise<ProjectContext> {
|
|
37
|
-
const detectedPm = detectPackageManager();
|
|
107
|
+
const detectedPm = await detectPackageManager();
|
|
38
108
|
const options = { yes: isTest, ...cliOptions };
|
|
39
109
|
|
|
40
|
-
|
|
110
|
+
const name = await getProjectName(options);
|
|
111
|
+
const selectedTemplate = await getSelectedTemplate(options);
|
|
112
|
+
const templateDefinition = getTemplateDefinition(selectedTemplate);
|
|
113
|
+
const packageManager = options.pm || detectedPm;
|
|
114
|
+
const shouldInstall = await getInstallPreference(options, packageManager);
|
|
115
|
+
|
|
116
|
+
const path = resolve(process.cwd(), name);
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
name,
|
|
120
|
+
path,
|
|
121
|
+
template: selectedTemplate,
|
|
122
|
+
packageManager,
|
|
123
|
+
isTest,
|
|
124
|
+
options: {
|
|
125
|
+
...options,
|
|
126
|
+
install: shouldInstall,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async function getProjectName(options: CreateInput): Promise<string> {
|
|
41
132
|
if (options.name) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
throw new Error(
|
|
45
|
-
`Invalid project name: ${result.error.errors[0]?.message}`,
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
name = options.name;
|
|
49
|
-
log.info(`Using project name: ${pc.yellow(name)}`);
|
|
50
|
-
} else {
|
|
51
|
-
const nameResult = await text({
|
|
52
|
-
message: "What is your project name?",
|
|
53
|
-
placeholder: "my-alchemy-app",
|
|
54
|
-
validate: (value) => {
|
|
55
|
-
const result = ProjectNameSchema.safeParse(value);
|
|
56
|
-
return result.success ? undefined : result.error.errors[0]?.message;
|
|
57
|
-
},
|
|
58
|
-
});
|
|
133
|
+
return options.name;
|
|
134
|
+
}
|
|
59
135
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
136
|
+
if (options.yes) {
|
|
137
|
+
return "my-alchemy-app";
|
|
138
|
+
}
|
|
64
139
|
|
|
65
|
-
|
|
140
|
+
const nameResult = await text({
|
|
141
|
+
message: "What is your project name?",
|
|
142
|
+
placeholder: "my-alchemy-app",
|
|
143
|
+
validate: (value) => {
|
|
144
|
+
const result = ProjectNameSchema.safeParse(value);
|
|
145
|
+
if (!result.success) {
|
|
146
|
+
return result.error.issues[0]?.message || "Invalid project name";
|
|
147
|
+
}
|
|
148
|
+
return undefined;
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
if (isCancel(nameResult)) {
|
|
153
|
+
cancel(pc.red("Operation cancelled."));
|
|
154
|
+
process.exit(0);
|
|
66
155
|
}
|
|
67
156
|
|
|
68
|
-
|
|
157
|
+
return nameResult;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
async function getSelectedTemplate(
|
|
161
|
+
options: CreateInput,
|
|
162
|
+
): Promise<TemplateType> {
|
|
69
163
|
if (options.template) {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
} else {
|
|
73
|
-
const templateResult = await select({
|
|
74
|
-
message: "Which template would you like to use?",
|
|
75
|
-
options: TEMPLATE_DEFINITIONS.map((t) => ({
|
|
76
|
-
label: t.description,
|
|
77
|
-
value: t.name as TemplateType,
|
|
78
|
-
})),
|
|
79
|
-
});
|
|
164
|
+
return options.template;
|
|
165
|
+
}
|
|
80
166
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
167
|
+
if (options.yes) {
|
|
168
|
+
return "typescript";
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
const templateResult = await select({
|
|
172
|
+
message: "Which template would you like to use?",
|
|
173
|
+
options: TEMPLATE_DEFINITIONS.map((t) => ({
|
|
174
|
+
label: t.description,
|
|
175
|
+
value: t.name as TemplateType,
|
|
176
|
+
})),
|
|
177
|
+
});
|
|
85
178
|
|
|
86
|
-
|
|
179
|
+
if (isCancel(templateResult)) {
|
|
180
|
+
cancel(pc.red("Operation cancelled."));
|
|
181
|
+
process.exit(0);
|
|
87
182
|
}
|
|
88
183
|
|
|
184
|
+
return templateResult;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
function getTemplateDefinition(selectedTemplate: TemplateType) {
|
|
89
188
|
const templateDefinition = TEMPLATE_DEFINITIONS.find(
|
|
90
189
|
(t) => t.name === selectedTemplate,
|
|
91
190
|
);
|
|
191
|
+
|
|
92
192
|
if (!templateDefinition) {
|
|
93
193
|
throw new Error(
|
|
94
194
|
`Template '${pc.yellow(selectedTemplate)}' not found. Available templates: ${TEMPLATE_DEFINITIONS.map((t) => pc.cyan(t.name)).join(", ")}`,
|
|
95
195
|
);
|
|
96
196
|
}
|
|
97
197
|
|
|
98
|
-
|
|
99
|
-
|
|
198
|
+
return templateDefinition;
|
|
199
|
+
}
|
|
100
200
|
|
|
101
|
-
|
|
201
|
+
async function getInstallPreference(
|
|
202
|
+
options: CreateInput,
|
|
203
|
+
packageManager: string,
|
|
204
|
+
): Promise<boolean> {
|
|
102
205
|
if (options.install !== undefined) {
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
`Dependencies installation: ${pc.yellow(shouldInstall ? "enabled" : "disabled")}`,
|
|
106
|
-
);
|
|
107
|
-
} else if (!options.yes) {
|
|
108
|
-
const installResult = await confirm({
|
|
109
|
-
message: "Install dependencies?",
|
|
110
|
-
initialValue: true,
|
|
111
|
-
});
|
|
206
|
+
return options.install;
|
|
207
|
+
}
|
|
112
208
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}
|
|
209
|
+
if (options.yes) {
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
117
212
|
|
|
118
|
-
|
|
213
|
+
const installResult = await confirm({
|
|
214
|
+
message: `Install dependencies? ${pc.cyan(packageManager)}`,
|
|
215
|
+
initialValue: true,
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
if (isCancel(installResult)) {
|
|
219
|
+
cancel(pc.red("Operation cancelled."));
|
|
220
|
+
process.exit(0);
|
|
119
221
|
}
|
|
120
222
|
|
|
121
|
-
return
|
|
122
|
-
name,
|
|
123
|
-
path,
|
|
124
|
-
template: selectedTemplate,
|
|
125
|
-
packageManager,
|
|
126
|
-
isTest,
|
|
127
|
-
options: {
|
|
128
|
-
...options,
|
|
129
|
-
install: shouldInstall,
|
|
130
|
-
},
|
|
131
|
-
};
|
|
223
|
+
return installResult;
|
|
132
224
|
}
|
|
133
225
|
|
|
134
226
|
async function handleDirectoryOverwrite(
|
|
@@ -138,34 +230,41 @@ async function handleDirectoryOverwrite(
|
|
|
138
230
|
return;
|
|
139
231
|
}
|
|
140
232
|
|
|
141
|
-
|
|
233
|
+
const shouldOverwrite = await getShouldOverwrite(context);
|
|
142
234
|
|
|
235
|
+
if (!shouldOverwrite) {
|
|
236
|
+
cancel(pc.red("Operation cancelled."));
|
|
237
|
+
process.exit(0);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
await removeExistingDirectory(context);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
async function getShouldOverwrite(context: ProjectContext): Promise<boolean> {
|
|
143
244
|
if (context.options.overwrite) {
|
|
144
|
-
shouldOverwrite = true;
|
|
145
245
|
log.warn(
|
|
146
246
|
`Directory ${pc.yellow(context.name)} already exists. Overwriting due to ${pc.cyan("--overwrite")} flag.`,
|
|
147
247
|
);
|
|
148
|
-
|
|
149
|
-
const overwriteResult = await confirm({
|
|
150
|
-
message: `Directory ${pc.yellow(context.name)} already exists. Overwrite?`,
|
|
151
|
-
initialValue: false,
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
if (isCancel(overwriteResult)) {
|
|
155
|
-
cancel(pc.red("Operation cancelled."));
|
|
156
|
-
process.exit(0);
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
shouldOverwrite = overwriteResult;
|
|
248
|
+
return true;
|
|
160
249
|
}
|
|
161
250
|
|
|
162
|
-
|
|
251
|
+
const overwriteResult = await confirm({
|
|
252
|
+
message: `Directory ${pc.yellow(context.name)} already exists. Overwrite?`,
|
|
253
|
+
initialValue: false,
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
if (isCancel(overwriteResult)) {
|
|
163
257
|
cancel(pc.red("Operation cancelled."));
|
|
164
258
|
process.exit(0);
|
|
165
259
|
}
|
|
166
260
|
|
|
261
|
+
return overwriteResult;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async function removeExistingDirectory(context: ProjectContext): Promise<void> {
|
|
167
265
|
const s = spinner();
|
|
168
266
|
s.start(`Removing existing directory: ${pc.yellow(context.path)}`);
|
|
267
|
+
|
|
169
268
|
try {
|
|
170
269
|
await fs.rm(context.path, { recursive: true, force: true });
|
|
171
270
|
s.stop(`Directory ${pc.yellow(context.path)} removed.`);
|
|
@@ -179,6 +278,7 @@ async function initializeTemplate(context: ProjectContext): Promise<void> {
|
|
|
179
278
|
const templateDefinition = TEMPLATE_DEFINITIONS.find(
|
|
180
279
|
(t) => t.name === context.template,
|
|
181
280
|
);
|
|
281
|
+
|
|
182
282
|
if (!templateDefinition) {
|
|
183
283
|
throw new Error(`Template definition not found for: ${context.template}`);
|
|
184
284
|
}
|
|
@@ -194,6 +294,32 @@ async function initializeTemplate(context: ProjectContext): Promise<void> {
|
|
|
194
294
|
}
|
|
195
295
|
|
|
196
296
|
async function setupVibeRules(context: ProjectContext): Promise<void> {
|
|
297
|
+
const selectedEditor = await getSelectedEditor(context);
|
|
298
|
+
|
|
299
|
+
if (!selectedEditor) {
|
|
300
|
+
return;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const s = spinner();
|
|
304
|
+
s.start("Configuring vibe-rules...");
|
|
305
|
+
|
|
306
|
+
try {
|
|
307
|
+
await ensureVibeRulesPostinstall(context.path, selectedEditor);
|
|
308
|
+
await installDependencies(context, {
|
|
309
|
+
devDependencies: ["vibe-rules"],
|
|
310
|
+
});
|
|
311
|
+
// we need to install dependencies to trigger the postinstall script
|
|
312
|
+
await installDependencies(context);
|
|
313
|
+
s.stop("vibe-rules configured");
|
|
314
|
+
} catch (error) {
|
|
315
|
+
s.stop("Failed to configure vibe-rules");
|
|
316
|
+
throwWithContext(error, "Failed to configure vibe-rules");
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
async function getSelectedEditor(
|
|
321
|
+
context: ProjectContext,
|
|
322
|
+
): Promise<EditorType | undefined> {
|
|
197
323
|
let selectedEditor: EditorType | undefined = context.options.vibeRules;
|
|
198
324
|
|
|
199
325
|
if (!selectedEditor && !context.isTest && !context.options.yes) {
|
|
@@ -203,7 +329,7 @@ async function setupVibeRules(context: ProjectContext): Promise<void> {
|
|
|
203
329
|
});
|
|
204
330
|
|
|
205
331
|
if (isCancel(setupResult) || !setupResult) {
|
|
206
|
-
return;
|
|
332
|
+
return undefined;
|
|
207
333
|
}
|
|
208
334
|
|
|
209
335
|
const editorResult = await select({
|
|
@@ -224,63 +350,109 @@ async function setupVibeRules(context: ProjectContext): Promise<void> {
|
|
|
224
350
|
});
|
|
225
351
|
|
|
226
352
|
if (isCancel(editorResult)) {
|
|
227
|
-
return;
|
|
353
|
+
return undefined;
|
|
228
354
|
}
|
|
229
355
|
|
|
230
356
|
selectedEditor = editorResult;
|
|
231
357
|
}
|
|
232
358
|
|
|
233
|
-
|
|
359
|
+
return selectedEditor;
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async function setupGitHubActions(context: ProjectContext): Promise<void> {
|
|
363
|
+
const shouldSetup = await getShouldSetupGitHubActions(context);
|
|
364
|
+
|
|
365
|
+
if (!shouldSetup) {
|
|
234
366
|
return;
|
|
235
367
|
}
|
|
236
368
|
|
|
237
|
-
const s = spinner();
|
|
238
|
-
s.start("Configuring vibe-rules...");
|
|
239
|
-
|
|
240
369
|
try {
|
|
241
|
-
await
|
|
370
|
+
await addGitHubWorkflowToAlchemy(context);
|
|
371
|
+
} catch (error) {
|
|
372
|
+
throwWithContext(error, "GitHub workflow setup failed");
|
|
373
|
+
}
|
|
374
|
+
}
|
|
242
375
|
|
|
243
|
-
|
|
244
|
-
|
|
376
|
+
async function getShouldSetupGitHubActions(
|
|
377
|
+
context: ProjectContext,
|
|
378
|
+
): Promise<boolean> {
|
|
379
|
+
let shouldSetupGitHub = context.options.githubActions;
|
|
380
|
+
|
|
381
|
+
if (
|
|
382
|
+
shouldSetupGitHub === undefined &&
|
|
383
|
+
!context.isTest &&
|
|
384
|
+
!context.options.yes
|
|
385
|
+
) {
|
|
386
|
+
const setupResult = await confirm({
|
|
387
|
+
message: "Add GitHub Actions for PR previews?",
|
|
388
|
+
initialValue: true,
|
|
245
389
|
});
|
|
246
390
|
|
|
247
|
-
|
|
248
|
-
|
|
391
|
+
if (isCancel(setupResult) || !setupResult) {
|
|
392
|
+
return false;
|
|
393
|
+
}
|
|
249
394
|
|
|
250
|
-
|
|
251
|
-
} catch (error) {
|
|
252
|
-
s.stop("Failed to configure vibe-rules");
|
|
253
|
-
throwWithContext(error, "Failed to configure vibe-rules");
|
|
395
|
+
shouldSetupGitHub = true;
|
|
254
396
|
}
|
|
397
|
+
|
|
398
|
+
return shouldSetupGitHub ?? false;
|
|
255
399
|
}
|
|
256
400
|
|
|
257
|
-
|
|
401
|
+
async function setupGit(context: ProjectContext): Promise<void> {
|
|
402
|
+
const gitAvailable = await isGitInstalled();
|
|
403
|
+
|
|
404
|
+
if (!gitAvailable) {
|
|
405
|
+
log.warn("Git is not installed. Skipping git initialisation.");
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const shouldInit = await getShouldInitGit(context);
|
|
410
|
+
|
|
411
|
+
if (!shouldInit) {
|
|
412
|
+
return;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
const s = spinner();
|
|
416
|
+
s.start("Initialising git repository...");
|
|
417
|
+
|
|
258
418
|
try {
|
|
259
|
-
|
|
260
|
-
|
|
419
|
+
await initializeGitRepo(context);
|
|
420
|
+
s.stop("Git repository initialised.");
|
|
421
|
+
} catch (error) {
|
|
422
|
+
s.stop(pc.red("Failed to initialise git repository"));
|
|
423
|
+
throwWithContext(error, "Git initialisation failed");
|
|
424
|
+
}
|
|
425
|
+
}
|
|
261
426
|
|
|
262
|
-
|
|
427
|
+
async function getShouldInitGit(context: ProjectContext): Promise<boolean> {
|
|
428
|
+
let shouldInit = context.options.git;
|
|
263
429
|
|
|
264
|
-
|
|
430
|
+
if (shouldInit === undefined && !context.isTest && !context.options.yes) {
|
|
431
|
+
const initResult = await confirm({
|
|
432
|
+
message: "Initialise a git repository?",
|
|
433
|
+
initialValue: true,
|
|
434
|
+
});
|
|
265
435
|
|
|
266
|
-
|
|
436
|
+
if (isCancel(initResult) || !initResult) {
|
|
437
|
+
return false;
|
|
438
|
+
}
|
|
439
|
+
shouldInit = initResult;
|
|
440
|
+
}
|
|
267
441
|
|
|
268
|
-
|
|
442
|
+
return shouldInit ?? false;
|
|
443
|
+
}
|
|
269
444
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
445
|
+
function displayNextSteps(context: ProjectContext): void {
|
|
446
|
+
const installInstructions =
|
|
447
|
+
context.options.install === false
|
|
448
|
+
? `
|
|
273
449
|
${pc.cyan("📦 Install dependencies:")}
|
|
274
|
-
cd ${context.name}
|
|
275
450
|
${context.packageManager} install
|
|
276
|
-
|
|
277
451
|
`
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
await setupVibeRules(context);
|
|
452
|
+
: "";
|
|
281
453
|
|
|
282
|
-
|
|
283
|
-
|
|
454
|
+
note(
|
|
455
|
+
`
|
|
284
456
|
${pc.cyan("📁 Navigate to your project:")}
|
|
285
457
|
cd ${context.name}
|
|
286
458
|
|
|
@@ -293,22 +465,20 @@ ${pc.cyan("🧹 Destroy your project:")}
|
|
|
293
465
|
${pc.cyan("📚 Learn more:")}
|
|
294
466
|
https://alchemy.run
|
|
295
467
|
`,
|
|
296
|
-
|
|
297
|
-
|
|
468
|
+
"Next Steps:",
|
|
469
|
+
);
|
|
470
|
+
}
|
|
298
471
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
)
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
log.error(pc.red(String(error)));
|
|
311
|
-
}
|
|
312
|
-
process.exit(1);
|
|
472
|
+
function displaySuccessMessage(context: ProjectContext): void {
|
|
473
|
+
outro(
|
|
474
|
+
pc.green(`✅ Project ${pc.yellow(context.name)} created successfully!`),
|
|
475
|
+
);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
function handleError(error: unknown): void {
|
|
479
|
+
if (error instanceof Error) {
|
|
480
|
+
throwWithContext(error, "Project creation failed");
|
|
481
|
+
} else {
|
|
482
|
+
throwWithContext(new Error(String(error)), "Project creation failed");
|
|
313
483
|
}
|
|
314
484
|
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import {
|
|
3
|
+
entrypoint,
|
|
4
|
+
execAlchemy,
|
|
5
|
+
execArgs,
|
|
6
|
+
watch,
|
|
7
|
+
} from "../services/execute-alchemy.ts";
|
|
8
|
+
import { t } from "../trpc.ts";
|
|
9
|
+
|
|
10
|
+
export const deploy = t.procedure
|
|
11
|
+
.meta({
|
|
12
|
+
description: "Deploy an Alchemy project",
|
|
13
|
+
})
|
|
14
|
+
.input(
|
|
15
|
+
z.tuple([
|
|
16
|
+
entrypoint,
|
|
17
|
+
z.object({
|
|
18
|
+
...execArgs,
|
|
19
|
+
watch,
|
|
20
|
+
}),
|
|
21
|
+
]),
|
|
22
|
+
)
|
|
23
|
+
.mutation(async ({ input }) => execAlchemy(...input));
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import z from "zod";
|
|
2
|
+
import {
|
|
3
|
+
entrypoint,
|
|
4
|
+
execAlchemy,
|
|
5
|
+
execArgs,
|
|
6
|
+
} from "../services/execute-alchemy.ts";
|
|
7
|
+
import { t } from "../trpc.ts";
|
|
8
|
+
|
|
9
|
+
export const destroy = t.procedure
|
|
10
|
+
.meta({
|
|
11
|
+
description: "Deploy an Alchemy project",
|
|
12
|
+
})
|
|
13
|
+
.input(z.tuple([entrypoint, z.object(execArgs)]))
|
|
14
|
+
.mutation(async ({ input: [main, options] }) =>
|
|
15
|
+
execAlchemy(main, {
|
|
16
|
+
...options,
|
|
17
|
+
destroy: true,
|
|
18
|
+
}),
|
|
19
|
+
);
|