Skip to content

Commit e90616e

Browse files
tonyxiaoclaude
andcommitted
Fix connector-loading e2e: hoist resolver flags to all CLI commands
Two bugs: 1. `--no-connectors-from-path` only worked on `serve`, not on one-shot commands like `check`. Fix: pre-parse connector flags from process.argv before building the resolver, and declare them as rootArgs so all subcommands accept them. 2. Test helpers passed `--stripe-api-key`/`--postgres-url` which aren't real flags on the generated `check` command (they were silently ignored). Fix: pass `--x-sync-params` with the full JSON blob instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Committed-By-Agent: claude
1 parent 2f83af2 commit e90616e

2 files changed

Lines changed: 61 additions & 19 deletions

File tree

apps/engine/src/cli/command.ts

Lines changed: 56 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,29 +2,35 @@ import 'dotenv/config'
22
import { Readable } from 'node:stream'
33
import { defineCommand } from 'citty'
44
import { createCliFromSpec } from '@stripe/sync-ts-cli/openapi'
5+
import { parseJsonOrFile } from '@stripe/sync-ts-cli'
56
import { createConnectorResolver } from '../lib/index.js'
67
import { createApp } from '../api/app.js'
78
import { serveAction } from '../serve-command.js'
89

10+
/** Connector discovery flags shared by all commands (serve + one-shot). */
11+
const connectorArgs = {
12+
connectorsFromCommandMap: {
13+
type: 'string' as const,
14+
description: 'Explicit connector command mappings (JSON object or @file)',
15+
},
16+
noConnectorsFromPath: {
17+
type: 'boolean' as const,
18+
default: false,
19+
description: 'Disable PATH-based connector discovery',
20+
},
21+
connectorsFromNpm: {
22+
type: 'boolean' as const,
23+
default: false,
24+
description: 'Enable npm auto-download of connectors (disabled by default)',
25+
},
26+
}
27+
928
// Hand-written workflow command: start HTTP server
1029
const serveCmd = defineCommand({
1130
meta: { name: 'serve', description: 'Start the HTTP API server' },
1231
args: {
1332
port: { type: 'string', description: 'Port to listen on (or PORT env)' },
14-
connectorsFromCommandMap: {
15-
type: 'string',
16-
description: 'Explicit connector command mappings (JSON object or @file)',
17-
},
18-
noConnectorsFromPath: {
19-
type: 'boolean',
20-
default: false,
21-
description: 'Disable PATH-based connector discovery',
22-
},
23-
connectorsFromNpm: {
24-
type: 'boolean',
25-
default: false,
26-
description: 'Enable npm auto-download of connectors (disabled by default)',
27-
},
33+
...connectorArgs,
2834
},
2935
async run({ args }) {
3036
serveAction({
@@ -36,8 +42,42 @@ const serveCmd = defineCommand({
3642
},
3743
})
3844

45+
/**
46+
* Pre-parse connector discovery flags from process.argv so the resolver
47+
* is configured before the one-shot CLI commands (check, read, etc.) run.
48+
*/
49+
function parseConnectorFlags(): {
50+
connectorsFromPath: boolean
51+
connectorsFromNpm: boolean
52+
connectorsFromCommandMap?: string
53+
} {
54+
const argv = process.argv
55+
const noPath = argv.includes('--no-connectors-from-path')
56+
const npm = argv.includes('--connectors-from-npm')
57+
let commandMap: string | undefined
58+
const cmdMapIdx = argv.indexOf('--connectors-from-command-map')
59+
if (cmdMapIdx !== -1 && cmdMapIdx + 1 < argv.length) {
60+
commandMap = argv[cmdMapIdx + 1]
61+
}
62+
return {
63+
connectorsFromPath: !noPath,
64+
connectorsFromNpm: npm,
65+
connectorsFromCommandMap: commandMap,
66+
}
67+
}
68+
3969
export async function createProgram() {
40-
const resolver = createConnectorResolver({})
70+
const flags = parseConnectorFlags()
71+
const resolver = createConnectorResolver(
72+
{},
73+
{
74+
path: flags.connectorsFromPath,
75+
npm: flags.connectorsFromNpm,
76+
commandMap: parseJsonOrFile(flags.connectorsFromCommandMap) as
77+
| Record<string, string>
78+
| undefined,
79+
}
80+
)
4181
const app = createApp(resolver)
4282
const res = await app.request('/openapi.json')
4383
const spec = await res.json()
@@ -48,6 +88,7 @@ export async function createProgram() {
4888
exclude: ['health'],
4989
ndjsonBodyStream: () =>
5090
process.stdin.isTTY ? null : (Readable.toWeb(process.stdin) as ReadableStream),
91+
rootArgs: connectorArgs,
5192
meta: {
5293
name: 'sync-engine',
5394
description: 'Stripe Sync Engine — sync Stripe data to Postgres',

e2e/connector-loading.test.sh

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,14 +105,16 @@ echo ""
105105
# Helpers
106106
# ---------------------------------------------------------------------------
107107

108+
# JSON-encoded X-Sync-Params header value for check requests.
109+
SYNC_PARAMS='{"source_name":"stripe","source_config":{"api_key":"sk_test_fake"},"destination_name":"postgres","destination_config":{"connection_string":"postgresql://fake:fake@localhost/fake"},"streams":[{"name":"products"}]}'
110+
108111
# Run `sync-engine check` with fake credentials and given extra flags.
109112
# Exits non-zero (bad credentials) but must NOT output "not found".
110113
# Usage: check_loads [extra flags...]
111114
check_loads() {
112115
local output
113116
output=$(npx sync-engine check \
114-
--stripe-api-key sk_test_fake \
115-
--postgres-url "postgresql://fake:fake@localhost/fake" \
117+
--x-sync-params "$SYNC_PARAMS" \
116118
"$@" 2>&1 || true)
117119
if echo "$output" | grep -qi "not found"; then
118120
echo " FAIL: got 'not found' — connector loading failed"
@@ -125,8 +127,7 @@ check_loads() {
125127
check_not_found() {
126128
local output
127129
output=$(npx sync-engine check \
128-
--stripe-api-key sk_test_fake \
129-
--postgres-url "postgresql://fake:fake@localhost/fake" \
130+
--x-sync-params "$SYNC_PARAMS" \
130131
"$@" 2>&1 || true)
131132
if echo "$output" | grep -qi "not found"; then
132133
return 0

0 commit comments

Comments
 (0)