create-svc 0.1.9 → 0.1.11

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.
Files changed (163) hide show
  1. package/README.md +138 -16
  2. package/bin/create-service.mjs +2 -0
  3. package/package.json +19 -11
  4. package/src/cli.test.ts +46 -7
  5. package/src/cli.ts +282 -84
  6. package/src/git-bootstrap.test.ts +40 -0
  7. package/src/git-bootstrap.ts +110 -0
  8. package/src/naming.test.ts +5 -2
  9. package/src/naming.ts +32 -1
  10. package/src/neon.ts +10 -8
  11. package/src/post-scaffold.test.ts +19 -0
  12. package/src/post-scaffold.ts +18 -26
  13. package/src/profiles.ts +25 -0
  14. package/src/scaffold.test.ts +320 -18
  15. package/src/scaffold.ts +154 -28
  16. package/src/vault.test.ts +94 -10
  17. package/src/vault.ts +81 -18
  18. package/templates/shared/.github/workflows/ci.yml +2 -1
  19. package/templates/shared/.github/workflows/deploy.yml +2 -0
  20. package/templates/shared/README.md +217 -29
  21. package/templates/shared/docker-compose.yml +19 -0
  22. package/templates/shared/grafana/alerts.yaml +54 -0
  23. package/templates/shared/grafana/waitlist-dashboard.json +63 -0
  24. package/templates/shared/scripts/authctl.ts +231 -0
  25. package/templates/shared/scripts/cloudrun/bootstrap.ts +24 -42
  26. package/templates/shared/scripts/cloudrun/cleanup.ts +81 -35
  27. package/templates/shared/scripts/cloudrun/cli.ts +324 -7
  28. package/templates/shared/scripts/cloudrun/config.ts +21 -19
  29. package/templates/shared/scripts/cloudrun/deploy.ts +16 -11
  30. package/templates/shared/scripts/cloudrun/lib.ts +232 -123
  31. package/templates/shared/scripts/cloudrun/neon.ts +127 -13
  32. package/templates/shared/scripts/dev.ts +22 -0
  33. package/templates/shared/scripts/ensure-local-db.ts +3 -0
  34. package/templates/shared/scripts/local-docker.ts +63 -0
  35. package/templates/shared/scripts/local-env.ts +27 -0
  36. package/templates/shared/scripts/seed.ts +73 -0
  37. package/templates/shared/scripts/wait-for-db.ts +32 -0
  38. package/templates/shared/service.config.ts +59 -0
  39. package/templates/shared/service.yaml +24 -1
  40. package/templates/targets/workers/.github/workflows/ci.yml +19 -0
  41. package/templates/targets/workers/.github/workflows/deploy.yml +19 -0
  42. package/templates/targets/workers/Makefile +33 -0
  43. package/templates/targets/workers/README.md +75 -0
  44. package/templates/targets/workers/package.json +35 -0
  45. package/templates/targets/workers/scripts/workers/cli.ts +397 -0
  46. package/templates/targets/workers/src/auth.ts +178 -0
  47. package/templates/targets/workers/src/index.ts +198 -0
  48. package/templates/targets/workers/src/storage.ts +370 -0
  49. package/templates/targets/workers/test/app.test.ts +108 -0
  50. package/templates/targets/workers/tsconfig.json +11 -0
  51. package/templates/targets/workers/wrangler.toml +24 -0
  52. package/templates/variants/bun-connectrpc/Dockerfile +1 -0
  53. package/templates/variants/bun-connectrpc/Makefile +17 -8
  54. package/templates/variants/bun-connectrpc/gen/protos/waitlist/v1/waitlist_pb.ts +424 -0
  55. package/templates/variants/bun-connectrpc/migrations/0000_init.sql +20 -0
  56. package/templates/variants/bun-connectrpc/package.json +25 -1
  57. package/templates/variants/bun-connectrpc/protos/waitlist/v1/waitlist.proto +91 -0
  58. package/templates/variants/bun-connectrpc/scripts/codegen.ts +31 -1
  59. package/templates/variants/bun-connectrpc/scripts/migrate.ts +49 -0
  60. package/templates/variants/bun-connectrpc/src/auth.ts +200 -0
  61. package/templates/variants/bun-connectrpc/src/db/client.ts +15 -0
  62. package/templates/variants/bun-connectrpc/src/db/repository.ts +126 -0
  63. package/templates/variants/bun-connectrpc/src/db/schema.ts +26 -0
  64. package/templates/variants/bun-connectrpc/src/index.ts +194 -22
  65. package/templates/variants/bun-connectrpc/src/temporal/activities.ts +14 -0
  66. package/templates/variants/bun-connectrpc/src/temporal/worker.ts +38 -0
  67. package/templates/variants/bun-connectrpc/src/temporal/workflows.ts +10 -0
  68. package/templates/variants/bun-connectrpc/src/waitlist/service.ts +172 -0
  69. package/templates/variants/bun-connectrpc/src/waitlist/types.ts +45 -0
  70. package/templates/variants/bun-connectrpc/test/app.test.ts +14 -13
  71. package/templates/variants/bun-connectrpc/test/waitlist.integration.test.ts +71 -0
  72. package/templates/variants/bun-connectrpc/tsconfig.json +2 -1
  73. package/templates/variants/bun-hono/Makefile +17 -8
  74. package/templates/variants/bun-hono/migrations/0000_init.sql +20 -0
  75. package/templates/variants/bun-hono/package.json +21 -1
  76. package/templates/variants/bun-hono/scripts/migrate.ts +49 -0
  77. package/templates/variants/bun-hono/src/auth.ts +181 -0
  78. package/templates/variants/bun-hono/src/db/client.ts +15 -0
  79. package/templates/variants/bun-hono/src/db/repository.ts +126 -0
  80. package/templates/variants/bun-hono/src/db/schema.ts +26 -0
  81. package/templates/variants/bun-hono/src/index.ts +141 -10
  82. package/templates/variants/bun-hono/src/temporal/activities.ts +14 -0
  83. package/templates/variants/bun-hono/src/temporal/worker.ts +38 -0
  84. package/templates/variants/bun-hono/src/temporal/workflows.ts +10 -0
  85. package/templates/variants/bun-hono/src/waitlist/service.ts +166 -0
  86. package/templates/variants/bun-hono/src/waitlist/types.ts +50 -0
  87. package/templates/variants/bun-hono/test/app.test.ts +90 -5
  88. package/templates/variants/bun-hono/test/waitlist.integration.test.ts +102 -0
  89. package/templates/variants/bun-hono/tsconfig.json +1 -0
  90. package/templates/variants/go-chi/Makefile +30 -10
  91. package/templates/variants/go-chi/atlas.hcl +8 -0
  92. package/templates/variants/go-chi/cmd/server/main.go +25 -13
  93. package/templates/variants/go-chi/go.mod +3 -2
  94. package/templates/variants/go-chi/internal/app/service.go +279 -70
  95. package/templates/variants/go-chi/internal/auth/middleware.go +289 -0
  96. package/templates/variants/go-chi/internal/auth/middleware_test.go +38 -0
  97. package/templates/variants/go-chi/internal/config/config.go +38 -7
  98. package/templates/variants/go-chi/internal/httpapi/routes.go +170 -47
  99. package/templates/variants/go-chi/internal/httpapi/waitlist_integration_test.go +199 -0
  100. package/templates/variants/go-chi/internal/temporal/activities.go +27 -0
  101. package/templates/variants/go-chi/internal/temporal/worker.go +42 -0
  102. package/templates/variants/go-chi/internal/temporal/workflows.go +18 -0
  103. package/templates/variants/go-chi/migrations/0000_init.sql +20 -0
  104. package/templates/variants/go-chi/migrations/atlas.sum +2 -0
  105. package/templates/variants/go-chi/package.json +7 -1
  106. package/templates/variants/go-chi/test/go.test.ts +4 -1
  107. package/templates/variants/go-connectrpc/Makefile +29 -8
  108. package/templates/variants/go-connectrpc/atlas.hcl +8 -0
  109. package/templates/variants/go-connectrpc/buf.gen.yaml +2 -0
  110. package/templates/variants/go-connectrpc/cmd/server/main.go +44 -9
  111. package/templates/variants/go-connectrpc/gen/waitlist/v1/waitlist.pb.go +960 -0
  112. package/templates/variants/go-connectrpc/gen/waitlist/v1/waitlistv1connect/waitlist.connect.go +283 -0
  113. package/templates/variants/go-connectrpc/go.mod +4 -0
  114. package/templates/variants/go-connectrpc/internal/app/service.go +279 -70
  115. package/templates/variants/go-connectrpc/internal/auth/middleware.go +289 -0
  116. package/templates/variants/go-connectrpc/internal/auth/middleware_test.go +38 -0
  117. package/templates/variants/go-connectrpc/internal/config/config.go +38 -7
  118. package/templates/variants/go-connectrpc/internal/connectapi/handler.go +129 -40
  119. package/templates/variants/go-connectrpc/internal/connectapi/waitlist_integration_test.go +122 -0
  120. package/templates/variants/go-connectrpc/internal/httpapi/routes.go +170 -47
  121. package/templates/variants/go-connectrpc/internal/temporal/activities.go +27 -0
  122. package/templates/variants/go-connectrpc/internal/temporal/worker.go +42 -0
  123. package/templates/variants/go-connectrpc/internal/temporal/workflows.go +18 -0
  124. package/templates/variants/go-connectrpc/migrations/0000_init.sql +20 -0
  125. package/templates/variants/go-connectrpc/migrations/atlas.sum +2 -0
  126. package/templates/variants/go-connectrpc/package.json +7 -1
  127. package/templates/variants/go-connectrpc/protos/waitlist/v1/waitlist.proto +93 -0
  128. package/templates/root/.github/workflows/buf-publish.yml +0 -19
  129. package/templates/root/.github/workflows/ci.yml +0 -26
  130. package/templates/root/.github/workflows/deploy.yml +0 -22
  131. package/templates/root/Dockerfile +0 -23
  132. package/templates/root/README.md +0 -69
  133. package/templates/root/buf.gen.yaml +0 -10
  134. package/templates/root/buf.yaml +0 -9
  135. package/templates/root/cmd/server/main.go +0 -44
  136. package/templates/root/gen/dns/v1/dns.pb.go +0 -623
  137. package/templates/root/gen/dns/v1/dnsv1connect/dns.connect.go +0 -192
  138. package/templates/root/go.mod +0 -10
  139. package/templates/root/internal/app/service.go +0 -152
  140. package/templates/root/internal/app/token_source.go +0 -50
  141. package/templates/root/internal/cloudflare/client.go +0 -160
  142. package/templates/root/internal/config/config.go +0 -55
  143. package/templates/root/internal/connectapi/handler.go +0 -79
  144. package/templates/root/internal/httpapi/routes.go +0 -93
  145. package/templates/root/internal/vault/client.go +0 -148
  146. package/templates/root/package.json +0 -12
  147. package/templates/root/protos/dns/v1/dns.proto +0 -58
  148. package/templates/root/scripts/cloudrun/bootstrap.ts +0 -65
  149. package/templates/root/scripts/cloudrun/config.ts +0 -50
  150. package/templates/root/scripts/cloudrun/deploy.ts +0 -41
  151. package/templates/root/scripts/cloudrun/lib.ts +0 -244
  152. package/templates/root/service.yaml +0 -50
  153. package/templates/root/test/go.test.ts +0 -19
  154. package/templates/shared/.env.example +0 -10
  155. package/templates/variants/go-chi/buf.gen.yaml +0 -10
  156. package/templates/variants/go-chi/buf.yaml +0 -9
  157. package/templates/variants/go-chi/gen/dns/v1/dns.pb.go +0 -623
  158. package/templates/variants/go-chi/gen/dns/v1/dnsv1connect/dns.connect.go +0 -192
  159. package/templates/variants/go-chi/internal/connectapi/handler.go +0 -79
  160. package/templates/variants/go-chi/protos/dns/v1/dns.proto +0 -58
  161. package/templates/variants/go-connectrpc/gen/dns/v1/dns.pb.go +0 -623
  162. package/templates/variants/go-connectrpc/gen/dns/v1/dnsv1connect/dns.connect.go +0 -192
  163. package/templates/variants/go-connectrpc/protos/dns/v1/dns.proto +0 -58
@@ -0,0 +1,110 @@
1
+ import { existsSync } from "node:fs";
2
+ import { dirname } from "node:path";
3
+
4
+ export type GitBootstrapConfig = {
5
+ enabled: boolean;
6
+ owner: string;
7
+ repository: string;
8
+ };
9
+
10
+ export type GitBootstrapResult =
11
+ | { status: "disabled" }
12
+ | { status: "skipped-existing-worktree"; root: string }
13
+ | { status: "created"; url: string };
14
+
15
+ export function buildGitBootstrapConfig(serviceName: string, noGit: boolean | undefined): GitBootstrapConfig {
16
+ return {
17
+ enabled: !noGit,
18
+ owner: "anmho",
19
+ repository: serviceName,
20
+ };
21
+ }
22
+
23
+ export async function bootstrapGitHubRepository(targetDir: string, config: GitBootstrapConfig): Promise<GitBootstrapResult> {
24
+ if (!config.enabled) {
25
+ return { status: "disabled" };
26
+ }
27
+
28
+ const existingRoot = findExistingGitWorktree(targetDir);
29
+ if (existingRoot) {
30
+ return { status: "skipped-existing-worktree", root: existingRoot };
31
+ }
32
+
33
+ run(["git", "--version"], targetDir, "git is required to initialize the generated repository");
34
+ run(["gh", "--version"], targetDir, "GitHub CLI `gh` is required to create the generated repository");
35
+ run(["gh", "auth", "status"], targetDir, "Authenticate GitHub CLI with `gh auth login` before creating the repository");
36
+
37
+ run(["git", "init", "-b", "main"], targetDir);
38
+ run(["git", "add", "."], targetDir);
39
+
40
+ if (hasStagedChanges(targetDir)) {
41
+ run(["git", "commit", "-m", "Initial commit"], targetDir);
42
+ }
43
+
44
+ const repository = `${config.owner}/${config.repository}`;
45
+ run(["gh", "repo", "create", repository, "--private", "--source", ".", "--remote", "origin", "--push"], targetDir);
46
+
47
+ return {
48
+ status: "created",
49
+ url: `https://github.com/${repository}`,
50
+ };
51
+ }
52
+
53
+ export function commitAndPushGeneratedArtifacts(targetDir: string, message: string) {
54
+ run(["git", "add", "."], targetDir);
55
+ if (!hasStagedChanges(targetDir)) {
56
+ return { committed: false };
57
+ }
58
+ run(["git", "commit", "-m", message], targetDir);
59
+ run(["git", "push"], targetDir);
60
+ return { committed: true };
61
+ }
62
+
63
+ export function findExistingGitWorktree(targetDir: string) {
64
+ const cwd = existingPath(targetDir);
65
+ const result = Bun.spawnSync(["git", "-C", cwd, "rev-parse", "--show-toplevel"], {
66
+ stdout: "pipe",
67
+ stderr: "pipe",
68
+ });
69
+ if (result.exitCode !== 0) {
70
+ return undefined;
71
+ }
72
+ return result.stdout.toString().trim() || undefined;
73
+ }
74
+
75
+ function existingPath(path: string): string {
76
+ if (existsSync(path)) {
77
+ return path;
78
+ }
79
+
80
+ const parent = dirname(path);
81
+ if (parent === path) {
82
+ return path;
83
+ }
84
+
85
+ return existingPath(parent);
86
+ }
87
+
88
+ function hasStagedChanges(cwd: string) {
89
+ const result = Bun.spawnSync(["git", "diff", "--cached", "--quiet"], {
90
+ cwd,
91
+ stdout: "pipe",
92
+ stderr: "pipe",
93
+ });
94
+ return result.exitCode === 1;
95
+ }
96
+
97
+ function run(command: string[], cwd: string, message?: string) {
98
+ const result = Bun.spawnSync(command, {
99
+ cwd,
100
+ stdin: "inherit",
101
+ stdout: "inherit",
102
+ stderr: "pipe",
103
+ });
104
+ if (result.exitCode === 0) {
105
+ return;
106
+ }
107
+
108
+ const detail = result.stderr.toString().trim();
109
+ throw new Error([message, `Command failed: ${command.join(" ")}`, detail].filter(Boolean).join("\n"));
110
+ }
@@ -1,14 +1,17 @@
1
1
  import { expect, test } from "bun:test";
2
- import { buildGcpProjectOptions, compactDatabaseName, compactIdentifier, deriveDefaults } from "./naming";
2
+ import { buildGcpProjectOptions, compactDatabaseName, compactIdentifier, deriveDefaults, deriveLocalPostgresPort } from "./naming";
3
3
 
4
4
  test("deriveDefaults uses the service name for project, repo, and database naming", () => {
5
5
  expect(deriveDefaults("edge-api")).toEqual({
6
+ serviceId: "edge-api",
6
7
  serviceName: "edge-api",
7
8
  projectName: "edge-api",
8
9
  projectId: "anmho-edge-api",
9
- githubRepo: "anmho/edge-api",
10
10
  cloudRunService: "edge-api",
11
11
  neonDatabaseName: "edge_api",
12
+ localDatabasePort: deriveLocalPostgresPort("edge-api"),
13
+ apiHostname: "api.edge-api.anmho.com",
14
+ modulePath: "example.com/edge-api",
12
15
  });
13
16
  });
14
17
 
package/src/naming.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  export const BILLING_ACCOUNT_DEFAULT = "billingAccounts/01BD2E-3A6949-8F4C84";
2
2
  export const QUOTA_PROJECT_DEFAULT = "anmho-infra-prod";
3
3
 
4
+ export const DEPLOY_TARGETS = ["cloudrun", "workers"] as const;
5
+
6
+ export type DeployTarget = (typeof DEPLOY_TARGETS)[number];
7
+
4
8
  export const FRAMEWORKS_BY_RUNTIME = {
5
9
  go: ["chi", "connectrpc"],
6
10
  bun: ["hono", "connectrpc"],
@@ -10,6 +14,24 @@ export type Runtime = keyof typeof FRAMEWORKS_BY_RUNTIME;
10
14
  export type Framework = (typeof FRAMEWORKS_BY_RUNTIME)[Runtime][number];
11
15
  export type GcpProjectMode = "create_new" | "use_existing";
12
16
 
17
+ export function parseDeployTarget(value: string): DeployTarget {
18
+ if (DEPLOY_TARGETS.includes(value as DeployTarget)) {
19
+ return value as DeployTarget;
20
+ }
21
+
22
+ throw new Error(`Unknown target: ${value}`);
23
+ }
24
+
25
+ export function frameworksForTargetRuntime(target: DeployTarget, runtime: Runtime): readonly Framework[] {
26
+ if (target === "workers") {
27
+ if (runtime === "bun") {
28
+ return ["hono"];
29
+ }
30
+ return [];
31
+ }
32
+ return FRAMEWORKS_BY_RUNTIME[runtime];
33
+ }
34
+
13
35
  export function slugify(value: string, maxLength = 63) {
14
36
  return value
15
37
  .trim()
@@ -54,16 +76,25 @@ export function compactDatabaseName(serviceName: string) {
54
76
  });
55
77
  }
56
78
 
79
+ export function deriveLocalPostgresPort(serviceName: string) {
80
+ const normalized = slugify(serviceName) || "my-service";
81
+ const hash = Number.parseInt(shortHash(normalized).slice(0, 4), 16);
82
+ return String(55000 + (hash % 1000));
83
+ }
84
+
57
85
  export function deriveDefaults(serviceName: string) {
58
86
  const normalizedServiceName = slugify(serviceName) || "my-service";
59
87
 
60
88
  return {
89
+ serviceId: normalizedServiceName,
61
90
  serviceName: normalizedServiceName,
62
91
  projectName: normalizedServiceName,
63
92
  projectId: compactIdentifier(`anmho-${normalizedServiceName}`, 30),
64
- githubRepo: `anmho/${normalizedServiceName}`,
65
93
  cloudRunService: normalizedServiceName,
66
94
  neonDatabaseName: compactDatabaseName(normalizedServiceName),
95
+ localDatabasePort: deriveLocalPostgresPort(normalizedServiceName),
96
+ apiHostname: `api.${normalizedServiceName}.anmho.com`,
97
+ modulePath: `example.com/${normalizedServiceName}`,
67
98
  };
68
99
  }
69
100
 
package/src/neon.ts CHANGED
@@ -21,25 +21,27 @@ export function createNeonApi(apiKey = process.env.NEON_API_KEY): NeonApi {
21
21
  async listProjects() {
22
22
  const client = createApiClient({ apiKey: (apiKey?.trim() || (await resolveNeonApiKey())) });
23
23
  const payload = await client.listProjects({ limit: 100 });
24
- return (payload.projects ?? [])
25
- .map((project) => ({
24
+ const projects = ((payload.data as { projects?: Array<{ id?: string; name?: string }> } | undefined)?.projects ?? []);
25
+ return projects
26
+ .map((project: { id?: string; name?: string }) => ({
26
27
  id: project.id ?? "",
27
28
  name: project.name ?? project.id ?? "",
28
29
  }))
29
- .filter((project) => project.id)
30
- .sort((left, right) => left.name.localeCompare(right.name));
30
+ .filter((project: NeonProject) => Boolean(project.id))
31
+ .sort((left: NeonProject, right: NeonProject) => left.name.localeCompare(right.name));
31
32
  },
32
33
 
33
34
  async listBranches(projectId: string) {
34
35
  const client = createApiClient({ apiKey: (apiKey?.trim() || (await resolveNeonApiKey())) });
35
36
  const payload = await client.listProjectBranches({ projectId });
36
- return (payload.branches ?? [])
37
- .map((branch) => ({
37
+ const branches = ((payload.data as { branches?: Array<{ id?: string; name?: string }> } | undefined)?.branches ?? []);
38
+ return branches
39
+ .map((branch: { id?: string; name?: string }) => ({
38
40
  id: branch.id ?? "",
39
41
  name: branch.name ?? branch.id ?? "",
40
42
  }))
41
- .filter((branch) => branch.id)
42
- .sort((left, right) => left.name.localeCompare(right.name));
43
+ .filter((branch: NeonBranch) => Boolean(branch.id))
44
+ .sort((left: NeonBranch, right: NeonBranch) => left.name.localeCompare(right.name));
43
45
  },
44
46
  };
45
47
  }
@@ -0,0 +1,19 @@
1
+ import { describe, expect, test } from "bun:test";
2
+ import { buildPostScaffoldCommands } from "./post-scaffold";
3
+
4
+ describe("buildPostScaffoldCommands", () => {
5
+ test("runs create and deploy for HTTP services", () => {
6
+ expect(buildPostScaffoldCommands({ framework: "hono" })).toEqual([
7
+ { command: "bun", args: ["run", "service", "--", "create"] },
8
+ { command: "bun", args: ["run", "service", "--", "deploy"] },
9
+ ]);
10
+ });
11
+
12
+ test("builds SDK artifacts before create and deploy for ConnectRPC services", () => {
13
+ expect(buildPostScaffoldCommands({ framework: "connectrpc" })).toEqual([
14
+ { command: "bun", args: ["run", "service", "--", "sdk", "build"] },
15
+ { command: "bun", args: ["run", "service", "--", "create"] },
16
+ { command: "bun", args: ["run", "service", "--", "deploy"] },
17
+ ]);
18
+ });
19
+ });
@@ -12,40 +12,32 @@ type CommandResult = {
12
12
  stderr: string;
13
13
  };
14
14
 
15
+ type PostScaffoldCommand = {
16
+ command: string;
17
+ args: string[];
18
+ };
19
+
15
20
  const decoder = new TextDecoder();
21
+ const encoder = new TextEncoder();
16
22
 
17
23
  export async function runPostScaffoldFlow(config: ScaffoldConfig, cwd: string) {
18
- if (config.createGithubRepo) {
19
- initializeRepository(cwd);
20
- createGitHubRepo(config, cwd);
21
- }
22
-
23
24
  if (config.autoDeploy) {
24
25
  installProjectDependencies(cwd);
25
- run("bun", ["run", "bootstrap"], { cwd });
26
- run("bun", ["run", "deploy"], { cwd });
27
- return { message: "Repository initialized, pushed, and first deploy started" };
26
+ for (const command of buildPostScaffoldCommands(config)) {
27
+ run(command.command, command.args, { cwd });
28
+ }
29
+ return { message: "Dependencies installed, service created, and service deployed" };
28
30
  }
29
31
 
30
- return { message: "Repository initialized" };
32
+ return { message: "Backend package generated" };
31
33
  }
32
34
 
33
- function initializeRepository(cwd: string) {
34
- requireCommand("git");
35
- run("git", ["init", "-b", "main"], { cwd, allowFailure: true });
36
- run("git", ["add", "."], { cwd });
37
- run("git", ["commit", "--allow-empty", "-m", "Initial commit"], { cwd, allowFailure: true });
38
- }
39
-
40
- function createGitHubRepo(config: ScaffoldConfig, cwd: string) {
41
- requireCommand("gh");
42
-
43
- const existing = run("gh", ["repo", "view", config.githubRepo], { cwd, allowFailure: true });
44
- if (!existing.success) {
45
- run("gh", ["repo", "create", config.githubRepo, `--${config.githubVisibility}`, "--source=.", "--remote=origin"], { cwd });
46
- }
47
-
48
- run("git", ["push", "-u", "origin", "main"], { cwd, allowFailure: true });
35
+ export function buildPostScaffoldCommands(config: Pick<ScaffoldConfig, "framework">): PostScaffoldCommand[] {
36
+ return [
37
+ ...(config.framework === "connectrpc" ? [{ command: "bun", args: ["run", "service", "--", "sdk", "build"] }] : []),
38
+ { command: "bun", args: ["run", "service", "--", "create"] },
39
+ { command: "bun", args: ["run", "service", "--", "deploy"] },
40
+ ];
49
41
  }
50
42
 
51
43
  function installProjectDependencies(cwd: string) {
@@ -63,7 +55,7 @@ function run(command: string, args: string[], options: CommandOptions): CommandR
63
55
  const result = Bun.spawnSync([command, ...args], {
64
56
  cwd: options.cwd,
65
57
  env: process.env,
66
- stdin: options.input,
58
+ stdin: options.input === undefined ? undefined : encoder.encode(options.input),
67
59
  stdout: options.allowFailure ? "pipe" : "inherit",
68
60
  stderr: options.allowFailure ? "pipe" : "inherit",
69
61
  });
@@ -0,0 +1,25 @@
1
+ export const PROFILES = ["microservice"] as const;
2
+
3
+ export type Profile = (typeof PROFILES)[number];
4
+
5
+ export function parseProfile(value: string): Profile {
6
+ if (PROFILES.includes(value as Profile)) {
7
+ return value as Profile;
8
+ }
9
+
10
+ if (value === "app") {
11
+ throw new Error(
12
+ "The app profile has moved out of create-service. Use the private create-app template repositories instead."
13
+ );
14
+ }
15
+
16
+ throw new Error(`Unknown profile: ${value}`);
17
+ }
18
+
19
+ export function exampleForProfile(_profile: Profile) {
20
+ return {
21
+ kind: "microservice",
22
+ domain: "waitlist",
23
+ label: "waitlist/launch service",
24
+ };
25
+ }