create-svc 0.1.29 → 0.1.30
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/package.json +1 -1
- package/src/cli.ts +11 -4
- package/src/post-scaffold.test.ts +27 -1
- package/src/post-scaffold.ts +68 -1
package/package.json
CHANGED
package/src/cli.ts
CHANGED
|
@@ -3,7 +3,7 @@ import pc from "picocolors";
|
|
|
3
3
|
import { readdirSync } from "node:fs";
|
|
4
4
|
import { basename, dirname, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
|
-
import { buildDeploymentVerificationCommands, runPostScaffoldFlow } from "./post-scaffold";
|
|
6
|
+
import { buildDeploymentVerificationCommands, buildLocalVerificationCommands, runPostScaffoldFlow } from "./post-scaffold";
|
|
7
7
|
import {
|
|
8
8
|
bootstrapGitHubRepository,
|
|
9
9
|
buildGitBootstrapConfig,
|
|
@@ -184,13 +184,20 @@ function formatCompletionSummary(config: ScaffoldConfig, targetDir: string, gitR
|
|
|
184
184
|
` Temporal API key secret: ${config.serviceName}-temporal-api-key`,
|
|
185
185
|
config.runtime === "go" ? ` Go module: ${config.modulePath}` : undefined,
|
|
186
186
|
"",
|
|
187
|
-
config.autoDeploy ? "Verified after deploy:" : "After deploy, verify with:",
|
|
187
|
+
config.autoDeploy ? "Verified production after deploy:" : "After deploy, verify production with:",
|
|
188
188
|
...buildDeploymentVerificationCommands(config).map(formatShellCommand),
|
|
189
|
+
config.autoDeploy ? "" : undefined,
|
|
190
|
+
config.autoDeploy ? "Local dev started:" : undefined,
|
|
191
|
+
config.autoDeploy ? " .service/local-dev.pid" : undefined,
|
|
192
|
+
config.autoDeploy ? " .service/local-dev.log" : undefined,
|
|
193
|
+
config.autoDeploy ? "" : undefined,
|
|
194
|
+
config.autoDeploy ? "Verified local dev:" : undefined,
|
|
195
|
+
...(config.autoDeploy ? buildLocalVerificationCommands(config).map(formatShellCommand) : []),
|
|
189
196
|
"",
|
|
190
|
-
"We suggest that you begin by typing:",
|
|
197
|
+
config.autoDeploy ? "Next:" : "We suggest that you begin by typing:",
|
|
191
198
|
"",
|
|
192
199
|
` cd ${config.directory}`,
|
|
193
|
-
` ${devCommand}`,
|
|
200
|
+
config.autoDeploy ? " tail -f .service/local-dev.log" : ` ${devCommand}`,
|
|
194
201
|
"",
|
|
195
202
|
repository ? `Repository: ${repository}` : undefined,
|
|
196
203
|
`Production API: https://${config.apiHostname}`,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
|
-
import { buildDeploymentVerificationCommands, buildPostScaffoldCommands } from "./post-scaffold";
|
|
2
|
+
import { buildDeploymentVerificationCommands, buildLocalVerificationCommands, buildPostScaffoldCommands } from "./post-scaffold";
|
|
3
3
|
|
|
4
4
|
describe("buildPostScaffoldCommands", () => {
|
|
5
5
|
test("runs create and deploy for HTTP services", () => {
|
|
@@ -25,6 +25,32 @@ describe("buildPostScaffoldCommands", () => {
|
|
|
25
25
|
});
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
+
describe("buildLocalVerificationCommands", () => {
|
|
29
|
+
test("uses local curl checks for Bun Hono services", () => {
|
|
30
|
+
expect(buildLocalVerificationCommands({ apiHostname: "api.launch.anmho.com", framework: "hono", runtime: "bun" })).toEqual([
|
|
31
|
+
{ command: "sh", args: ["-c", 'curl --fail --show-error --silent "http://127.0.0.1:3000/"'] },
|
|
32
|
+
{ command: "sh", args: ["-c", 'curl --fail --show-error --silent "http://127.0.0.1:3000/readyz"'] },
|
|
33
|
+
{
|
|
34
|
+
command: "sh",
|
|
35
|
+
args: [
|
|
36
|
+
"-c",
|
|
37
|
+
'TOKEN="$(service auth token)" && curl --fail --show-error --silent -H "Authorization: Bearer $TOKEN" "http://127.0.0.1:3000/v1/admin/waitlist?limit=1"',
|
|
38
|
+
],
|
|
39
|
+
},
|
|
40
|
+
]);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test("uses plaintext grpcurl for local Go ConnectRPC services", () => {
|
|
44
|
+
expect(buildLocalVerificationCommands({ apiHostname: "api.launch.anmho.com", framework: "connectrpc", runtime: "go" })).toContainEqual({
|
|
45
|
+
command: "sh",
|
|
46
|
+
args: [
|
|
47
|
+
"-c",
|
|
48
|
+
'TOKEN="$(service auth token)" && grpcurl -plaintext -H "Authorization: Bearer $TOKEN" -d \'{"limit":1}\' -proto protos/waitlist/v1/waitlist.proto "127.0.0.1:8080" waitlist.v1.WaitlistService/ListWaitlistEntries',
|
|
49
|
+
],
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
|
|
28
54
|
describe("buildDeploymentVerificationCommands", () => {
|
|
29
55
|
test("uses curl health checks for HTTP services", () => {
|
|
30
56
|
expect(buildDeploymentVerificationCommands({ apiHostname: "api.launch.anmho.com", framework: "hono", runtime: "bun" })).toEqual([
|
package/src/post-scaffold.ts
CHANGED
|
@@ -33,12 +33,26 @@ export async function runPostScaffoldFlow(config: ScaffoldConfig, cwd: string) {
|
|
|
33
33
|
for (const command of buildDeploymentVerificationCommands(config)) {
|
|
34
34
|
runWithRetries(command, { cwd, quiet: true }, DEPLOYMENT_VERIFY_ATTEMPTS, DEPLOYMENT_VERIFY_DELAY_MS);
|
|
35
35
|
}
|
|
36
|
-
|
|
36
|
+
startLocalDevelopment(config, cwd);
|
|
37
|
+
for (const command of buildLocalVerificationCommands(config)) {
|
|
38
|
+
runWithRetries(command, { cwd, quiet: true }, 18, 5_000);
|
|
39
|
+
}
|
|
40
|
+
return { message: "Dependencies installed, service created, service deployed, production verified, and local dev started" };
|
|
37
41
|
}
|
|
38
42
|
|
|
39
43
|
return { message: "Backend package generated" };
|
|
40
44
|
}
|
|
41
45
|
|
|
46
|
+
function startLocalDevelopment(config: Pick<ScaffoldConfig, "target">, cwd: string) {
|
|
47
|
+
if (config.target === "workers") {
|
|
48
|
+
run("sh", ["-c", "mkdir -p .service && bun run dev > .service/local-dev.log 2>&1 & echo $! > .service/local-dev.pid"], { cwd });
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
run("bun", ["run", "migrate"], { cwd });
|
|
53
|
+
run("sh", ["-c", "mkdir -p .service && bun run dev > .service/local-dev.log 2>&1 & echo $! > .service/local-dev.pid"], { cwd });
|
|
54
|
+
}
|
|
55
|
+
|
|
42
56
|
function runWithRetries(command: PostScaffoldCommand, options: CommandOptions, attempts: number, delayMs: number) {
|
|
43
57
|
let lastError: unknown;
|
|
44
58
|
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
@@ -68,6 +82,18 @@ export function buildDeploymentVerificationCommands(
|
|
|
68
82
|
];
|
|
69
83
|
}
|
|
70
84
|
|
|
85
|
+
export function buildLocalVerificationCommands(
|
|
86
|
+
config: Pick<ScaffoldConfig, "apiHostname" | "framework" | "runtime"> & Partial<Pick<ScaffoldConfig, "target">>
|
|
87
|
+
): PostScaffoldCommand[] {
|
|
88
|
+
const origin = localVerificationOrigin(config);
|
|
89
|
+
const tokenCommand = 'TOKEN="$(service auth token)"';
|
|
90
|
+
return [
|
|
91
|
+
shellVerificationCommand(`curl --fail --show-error --silent "${origin}/"`),
|
|
92
|
+
shellVerificationCommand(`curl --fail --show-error --silent "${origin}/readyz"`),
|
|
93
|
+
protectedLocalVerificationCommand(config, origin, tokenCommand),
|
|
94
|
+
];
|
|
95
|
+
}
|
|
96
|
+
|
|
71
97
|
function protectedVerificationCommand(
|
|
72
98
|
config: Pick<ScaffoldConfig, "apiHostname" | "framework" | "runtime"> &
|
|
73
99
|
Partial<Pick<ScaffoldConfig, "target" | "serviceName" | "gcpProject" | "region">>,
|
|
@@ -124,6 +150,33 @@ function protectedVerificationCommand(
|
|
|
124
150
|
};
|
|
125
151
|
}
|
|
126
152
|
|
|
153
|
+
function protectedLocalVerificationCommand(
|
|
154
|
+
config: Pick<ScaffoldConfig, "apiHostname" | "framework" | "runtime"> & Partial<Pick<ScaffoldConfig, "target">>,
|
|
155
|
+
origin: string,
|
|
156
|
+
tokenCommand: string
|
|
157
|
+
): PostScaffoldCommand {
|
|
158
|
+
if (config.framework === "connectrpc" && config.runtime === "go") {
|
|
159
|
+
const host = localVerificationHost(config);
|
|
160
|
+
return {
|
|
161
|
+
command: "sh",
|
|
162
|
+
args: [
|
|
163
|
+
"-c",
|
|
164
|
+
[
|
|
165
|
+
`${tokenCommand} &&`,
|
|
166
|
+
"grpcurl -plaintext",
|
|
167
|
+
'-H "Authorization: Bearer $TOKEN"',
|
|
168
|
+
"-d '{\"limit\":1}'",
|
|
169
|
+
"-proto protos/waitlist/v1/waitlist.proto",
|
|
170
|
+
`"${host}"`,
|
|
171
|
+
"waitlist.v1.WaitlistService/ListWaitlistEntries",
|
|
172
|
+
].join(" "),
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return protectedVerificationCommand(config, origin, tokenCommand);
|
|
178
|
+
}
|
|
179
|
+
|
|
127
180
|
function shellVerificationCommand(script: string): PostScaffoldCommand {
|
|
128
181
|
return { command: "sh", args: ["-c", script] };
|
|
129
182
|
}
|
|
@@ -146,6 +199,20 @@ function verificationHost(
|
|
|
146
199
|
return config.apiHostname;
|
|
147
200
|
}
|
|
148
201
|
|
|
202
|
+
function localVerificationOrigin(config: Partial<Pick<ScaffoldConfig, "target" | "runtime" | "framework">>) {
|
|
203
|
+
if (config.target === "workers") {
|
|
204
|
+
return "http://127.0.0.1:8787";
|
|
205
|
+
}
|
|
206
|
+
if (config.runtime === "bun" && config.framework === "hono") {
|
|
207
|
+
return "http://127.0.0.1:3000";
|
|
208
|
+
}
|
|
209
|
+
return "http://127.0.0.1:8080";
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
function localVerificationHost(config: Partial<Pick<ScaffoldConfig, "target" | "runtime" | "framework">>) {
|
|
213
|
+
return localVerificationOrigin(config).replace(/^https?:\/\//, "");
|
|
214
|
+
}
|
|
215
|
+
|
|
149
216
|
export function buildPostScaffoldCommands(
|
|
150
217
|
config: Pick<ScaffoldConfig, "framework"> & Partial<Pick<ScaffoldConfig, "target">>
|
|
151
218
|
): PostScaffoldCommand[] {
|