@honest-pitches/pitch-sdk 0.4.6 → 0.5.2

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/CHANGELOG.md CHANGED
@@ -11,6 +11,72 @@ and this project adheres to
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ### Fixed
15
+
16
+ - **`client.pitches.list is not a function` on every auth-required
17
+ list path (2026-07-28).** The `list` alias existed in local
18
+ source under the 0.5.1 version number but was never published
19
+ to npmjs (the 0.5.1 tarball only had `find`). Bumped to
20
+ **0.5.2** so a fresh `npm install @honest-pitches/pitch-sdk`
21
+ actually gets the alias. TSDoc updated to say stable-since
22
+ 0.5.2 (honest about the 0.5.1 publish gap). Detail:
23
+ control-repo
24
+ [`CHANGELOG.d/2026-07-28-sdk-list-alias-and-creatorid-filter.md`](../CHANGELOG.d/2026-07-28-sdk-list-alias-and-creatorid-filter.md).
25
+
26
+ ### Fixes
27
+
28
+ - **`videoSource` type widening to keep `pnpm run build:deploy:all`
29
+ green (commit `86f7ab1`, 2026-07-27).** The 2026-07-27 bug #2
30
+ commit `7f8b748` (`feat(pitcher-sdk): forward
31
+ videoSource/videoExternalId/videoExternalUrl + video helpers on
32
+ create/update`) widened `CreatePitchInput.videoSource` to a
33
+ 3-literal union (`"bunny_video_id" | "external_url" | "none" |
34
+ null`) AND added an `input.videoSource !== ""` guard at
35
+ `src/pitches.ts:215`. The guard's intent — drop empty-string
36
+ form-field values from the wire body — is correct, but the
37
+ type doesn't permit `""`, so tsc flagged the comparison as
38
+ unreachable (TS2367) and `pnpm run build:deploy:all` failed at
39
+ the SDK build step. **Fix:** widen the union to add `""` on
40
+ both `CreatePitchInput` and `UpdatePitchInput` (the latter for
41
+ symmetry, since the spread-forward site could see an
42
+ empty-string value too). `""` now lives in the canonical
43
+ "do not overwrite" club alongside `null` and absent, matching
44
+ the MCP server's `raw[key] !== ""` guard at `pitch-write`.
45
+ Two pre-existing typecheck failures from the same
46
+ `7f8b748` commit were also repaired:
47
+ - **9× TS2741** — pitch-test sections were missing the
48
+ required `mediaIds: string[]` field (the `PitchSection`
49
+ contract has required it since at least the v0.3.0
50
+ platform-libs cut). Added `mediaIds: []` to all three
51
+ test-section triples.
52
+ - **1× TS7006** — `Headers.forEach((v, k) => …)` had
53
+ implicit-any parameters because the outer
54
+ `vi.fn(async (input: any, init?: any) => …)` signature
55
+ leaves `init` untyped, so the `instanceof Headers`
56
+ narrowing does not propagate to `init.headers`. Added
57
+ explicit `(v: string, k: string)` types.
58
+
59
+ ### Tests
60
+
61
+ - **New regression test** (2026-07-27):
62
+ `pitches.test.ts#PitchesApi.create — body builder
63
+ does NOT forward videoSource/videoExternalId/videoExternalUrl
64
+ when set to empty string (regression: form-field hygiene)`.
65
+ Pins the `!== ""` guard's runtime behaviour — without it, a
66
+ future refactor that drops the guard would silently start
67
+ writing `""` to the server, which the server then rejects or
68
+ misinterprets depending on column nullability.
69
+ - **Test counts:** `pnpm test` 47/47 vitest (was 46/46);
70
+ `pnpm test:ci` 47 vitest + 54 contract assertions across 9
71
+ contract suites, 0 regressions.
72
+
73
+ ### Version
74
+
75
+ - **No version bump in this commit.** The bug #2 commit
76
+ (`7f8b748`) was unversioned at HEAD; this fix lands on top.
77
+ The next operator-pushed SDK tag should cut `v0.5.2` to ship
78
+ both fixes together.
79
+
14
80
  Next package version: `0.4.1`. See
15
81
  `CHANGELOG.d/2026-07-19-package-rename.md` for the rename to
16
82
  `@honest-pitches/pitch-sdk`.
@@ -179,6 +245,86 @@ across 6 contract files). See
179
245
  `CHANGELOG.d/2026-07-20-publish-fix-and-readme.md` for the long-form
180
246
  publish-failure root-cause analysis and the full README diff.
181
247
 
248
+ ## [0.5.1] - 2026-07-25
249
+
250
+ First publish that matches the documented design end-to-end. Three
251
+ coordinated changes:
252
+
253
+ ### Vendor-agnostic HTTP wrapper (the v0.5.0 re-architecture, finally published)
254
+
255
+ The SDK is now a pure HTTP wrapper against the pitcher-mcp server's
256
+ `/pitcher/*` routes. Consumers only need `{ apiKey: 'hp_pk_…' }` —
257
+ no `endpoint`, no `projectId`, no backend env vars, no vendor
258
+ imports in the public API surface. The package no longer depends
259
+ on `node-appwrite` (audit 3 confirmed: the bundle is `node-appwrite`-free).
260
+ The MCP server is the only layer that knows about the backend;
261
+ the SDK and the consumer are both HTTP-only.
262
+
263
+ ### ESM bundle fix (the actual blocker)
264
+
265
+ The v0.5.0 build produced an ESM bundle that threw `Dynamic require
266
+ of "path" is not supported` at module-load time on Node 20+,
267
+ 100% of consumers. Root cause: esbuild's CJS-shim `__require(x)`
268
+ in the ESM bundle fails for Node built-ins because pure ESM has no
269
+ `require`. The fix is a `banner: { js: "import { createRequire as
270
+ topLevelCreateRequire } from 'node:module'; const require =
271
+ topLevelCreateRequire(import.meta.url);" }` on the ESM esbuild
272
+ call in `build.mjs`. Same pattern as the Node-ESM target in
273
+ `honest-pitches-platform-libs/packages/pitch-core/tsup.config.ts`.
274
+
275
+ **Why v0.4.6 also failed** (transitive from
276
+ `pitcher-api-key-core`'s `require("crypto")`): the same root cause,
277
+ different inlined vendor. The 0.4.6 → 0.5.x lineage fixes it
278
+ identically.
279
+
280
+ ### Publish workflow hardening
281
+
282
+ The publish workflow now runs `pnpm test:ci` (not `pnpm test`)
283
+ so the contract tests are no longer silently skipped. The new
284
+ `scripts/esm-bundle-runtime.contract.test.mjs` (2 cases) is the
285
+ regression pin — it would have caught v0.4.6 at publish time.
286
+ `scripts/publish-workflow.contract.test.mjs` (now 15 cases) adds
287
+ a `Test step runs pnpm test:ci` assertion.
288
+
289
+ ### What ships
290
+
291
+ - `dist/index.cjs` — CJS bundle (works as before)
292
+ - `dist/index.mjs` — ESM bundle (FIXED; loads cleanly on Node 20+)
293
+ - `dist/index.d.mts` — TypeScript declarations
294
+ - `package.json` (`0.5.1`) — version bump from `0.5.0`
295
+ - `src/config.ts` — drops `endpoint`/`projectId`/`databaseId`/`client`/`initialJwt`, adds `apiKey`/`jwt`/`jwtExpiresAt`/`baseUrl`/`fetchImpl`
296
+ - `src/pitches.ts` + `src/creators.ts` — uses `fetchPitches` against `${baseUrl}/pitcher/*`
297
+ - `src/errors.ts` — adds `PitcherRequestError` (replaces `AppwriteRequestError`)
298
+ - `dist/*` typings — drop `MEDIA_API_FUNCTION_ID` / `PUBLIC_API_FUNCTION_ID` / `STRIPE_API_FUNCTION_ID` / `STUDIO_API_FUNCTION_ID` / `appwriteQueryEqual` / `appwriteQueryLimit`
299
+
300
+ ### What does NOT ship in this version
301
+
302
+ - The CLI (`@honest-pitches/hp-cli`) lives at `D:\Honest_Pitches\honest-pitches-cli` and is already a separate package.
303
+ - The `drp-*` framework IDs in the public `/agents/` page are wrong (should be `drtv_*` from the local frameworks registry). Tracked as a follow-up ticket against the public web repo, not the SDK.
304
+ - The MCP server's `/pitcher/*` route table is the live source of truth; the SDK's `fetchPitches` client mirrors it.
305
+
306
+ ### Test surface
307
+
308
+ - `pnpm test` (Vitest) — 53 unit tests pass.
309
+ - `pnpm test:ci` (Vitest + 9 contract tests) — 53 + 49 = 102 cases pass.
310
+ - `scripts/esm-bundle-runtime.contract.test.mjs` (NEW, 2 cases) — RED on 0.5.0, GREEN on 0.5.1.
311
+ - `scripts/publish-workflow.contract.test.mjs` (15 cases, +1) — asserts `pnpm test:ci` runs in the workflow.
312
+ - `scripts/no-node-appwrite-in-runtime.contract.test.mjs` (4 cases) — `node-appwrite` is absent from the bundle.
313
+ - `scripts/bundled-deps.contract.test.mjs` (10 cases) — the bundle is fat and self-contained.
314
+ - `scripts/config-shape.contract.test.mjs` (3 cases) — `endpoint`/`projectId` are absent from the public API.
315
+
316
+ ### Acceptance (brief)
317
+
318
+ - [x] `createPitcherClient({ apiKey: 'hp_pk_…' })` builds with no other config.
319
+ - [x] The build's only network surface is `${PITCHER_MCP_URL}/pitcher/*`, defaulting to `https://mcp.honestpitches.com`.
320
+ - [x] `import '@honest-pitches/pitch-sdk'` works on Node 20+ (no `Dynamic require of "path"`).
321
+ - [x] `require('@honest-pitches/pitch-sdk')` works (unchanged).
322
+ - [x] `0.4.6` is recommended for deprecation (`pnpm deprecate` is a publish pipeline action — separate follow-up).
323
+
324
+ See `CHANGELOG.d/2026-07-25-vendor-agnostic-esm-fix.md` for the
325
+ long-form root-cause analysis and audit 3 (SDK contract drift)
326
+ findings.
327
+
182
328
  ## [0.3.0] - 2026-06-17
183
329
 
184
330
  See `CHANGELOG.d/2026-06-17.md` for the change set.
package/README.md CHANGED
@@ -2,17 +2,17 @@
2
2
 
3
3
  The JavaScript / TypeScript SDK for the **Honest Pitches** platform.
4
4
  Use it to define, list, update, and transition the pitches you own on
5
- [honestpitches.com](https://www.honestpitches.com) — the place where
6
- founders publish their real numbers, real plans, and real backers, and
7
- critics respond with structured ratings instead of hot takes.
5
+ [honestpitches.com](https://www.honestpitches.com).
6
+
7
+ The SDK is a **pure HTTP wrapper** around the hosted MCP server at
8
+ `https://mcp.honestpitches.com`. It has no backend vendor config:
9
+ no `endpoint`, no `projectId`, no `databaseId`, no backend SDK
10
+ dependency. One env var (`PITCHER_API_KEY`) is all you need.
8
11
 
9
12
  This package is the **source of truth** for the pitcher-facing
10
13
  programmatic surface. The `honest-pitches-cli` and the
11
14
  `honest-pitches-pitcher-mcp` server are both thin wrappers around
12
- this SDK — they don't re-implement pitch logic. A developer who uses
13
- the CLI gets exactly the same SDK calls a developer who uses the MCP
14
- server gets: same auth, same errors, same pagination, same audit
15
- trail.
15
+ this SDK — they don't re-implement pitch logic.
16
16
 
17
17
  ## Install
18
18
 
@@ -27,22 +27,32 @@ The source remains in the private Honest Pitches Forgejo repository.
27
27
 
28
28
  ## Quickstart
29
29
 
30
- The SDK authenticates with a **per-user token** that you obtain from
31
- the platform's OAuth flow. The token is short-lived; you mint it once
32
- per session and pass it to the client factory. The SDK will refresh
33
- internally on 401 responses.
30
+ The SDK authenticates with a **per-user API key** that you mint at
31
+ `studio.honestpitches.com Settings API keys`. The key is
32
+ long-lived; you pass it to the client factory once.
34
33
 
35
34
  ```ts
36
35
  import { createPitcherClient } from "@honest-pitches/pitch-sdk";
37
36
 
38
- // Mint a per-user JWT via your platform OAuth flow, then:
37
+ // Get a key at studio.honestpitches.com Settings API keys,
38
+ // then set PITCHER_API_KEY in your environment:
39
39
  const client = createPitcherClient({
40
- endpoint: process.env.HONEST_PITCHES_ENDPOINT!, // the platform base URL
41
- projectId: process.env.HONEST_PITCHES_PROJECT_ID!,
42
- initialJwt: process.env.PITCHER_JWT!, // short-lived per-user JWT
40
+ apiKey: process.env.PITCHER_API_KEY!,
43
41
  });
44
42
 
45
- const pitches = await client.pitches.list({ status: "live" });
43
+ const pitches = await client.pitches.find({ status: "live" });
44
+ ```
45
+
46
+ `PITCHER_MCP_URL` defaults to the hosted MCP
47
+ (`https://mcp.honestpitches.com`). Set it only when self-hosting the
48
+ MCP.
49
+
50
+ The JWT variant is the same shape:
51
+
52
+ ```ts
53
+ const client = createPitcherClient({
54
+ jwt: process.env.PITCHER_JWT!, // short-lived per-user JWT (minted via the pitcher-mcp OAuth flow)
55
+ });
46
56
  ```
47
57
 
48
58
  ## API
@@ -51,17 +61,18 @@ const pitches = await client.pitches.list({ status: "live" });
51
61
 
52
62
  | Export | Kind | Notes |
53
63
  | --- | --- | --- |
54
- | `createPitcherClient(config)` | factory | builds the client; `initialJwt` is a short-lived per-user JWT, NOT a long-lived API key |
64
+ | `createPitcherClient(config)` | factory | builds the client from `{ apiKey }` or `{ jwt }` |
55
65
  | `resolvePitcherConfig(config)` | helper | merges defaults with caller-supplied overrides |
66
+ | `DEFAULT_PITCHER_BASE_URL` | constant | `https://mcp.honestpitches.com` — the hosted MCP |
56
67
 
57
68
  ### Pitch operations
58
69
 
59
70
  | Export | Kind | Notes |
60
71
  | --- | --- | --- |
61
- | `PitchesApi` | class | list / get / create / update / transition pitches |
72
+ | `PitchesApi` | class | `find` / `get` / `create` / `update` / `transition` / `uploadMedia` / `unarchive` pitches |
62
73
  | `scaffoldPitchFromFramework` | helper | builds a section set from a framework key |
63
- | `findCreatorIdForJwtUser` | helper | looks up the creator `$id` from a JWT's `sub` claim |
64
- | `findCreatorIdForApiKey` | helper | server-side variant for API-key auth |
74
+ | `findCreatorIdForJwtUser` | helper | looks up the creator `$id` from the auth principal |
75
+ | `findCreatorIdForApiKey` | helper | same, for API-key auth |
65
76
 
66
77
  ### Frameworks & segments
67
78
 
@@ -75,70 +86,28 @@ second import:
75
86
  | `getSegmentDefinition` | function | single segment by key |
76
87
  | `suggestedSectionsForFramework` | function | default section list for a framework |
77
88
 
78
- ### Query helpers
79
-
80
- The SDK uses a small query DSL internally and exposes the building
81
- blocks so you don't have to re-import them:
82
-
83
- | Export | Kind | Notes |
84
- | --- | --- | --- |
85
- | `appwriteQueryEqual` | helper | `field == value` |
86
- | `appwriteQueryLimit` | helper | pagination cap |
87
-
88
- > The `appwrite*` prefix on these helpers is a naming artifact from
89
- > the SDK's internal implementation; you don't need to know what
90
- > backs them to use them. The names are stable — they're part of
91
- > the published API.
92
-
93
- ### Token parsing
94
-
95
- | Export | Kind | Notes |
96
- | --- | --- | --- |
97
- | `decodeJwtSub` | helper | extracts the `sub` claim without verifying the signature |
98
- | `isJwtExpired` | helper | `true` if the token's `exp` is in the past |
99
-
100
- ### Routing constants
101
-
102
- | Export | Kind | Notes |
103
- | --- | --- | --- |
104
- | `MEDIA_API_FUNCTION_ID` | constant | the platform's media-handling function id |
105
- | `PUBLIC_API_FUNCTION_ID` | constant | the public read API function id |
106
- | `STRIPE_API_FUNCTION_ID` | constant | the Stripe integration function id |
107
- | `STUDIO_API_FUNCTION_ID` | constant | the studio integration function id |
108
- | `resolveConsolidatedRoute` | function | picks the right function id for a given request |
109
-
110
89
  ## Error model
111
90
 
112
91
  Every error thrown by this SDK is a `PitcherSdkError` (or one of its
113
92
  subclasses). The subclasses are:
114
93
 
115
- - `AppwriteRequestError` — the backend returned a non-2xx (the
116
- prefix is a naming artifact from the SDK's internal implementation;
117
- the error fires for any backend non-2xx, not just the Appwrite
118
- transport)
94
+ - `PitcherRequestError` — the MCP server returned a non-2xx
119
95
  - `FrameworkLockedError` — tried to change a pitch's framework after the first section was written
120
96
  - `HpCodeImmutableError` — tried to change a pitch's `hpCode` after creation
121
97
  - `InvalidSectionKindError` — section kind not in the framework's allowed set
122
98
  - `PitcherNotAuthenticatedError` — token missing or expired
123
99
  - `PitcherNotOwnedCreatorError` — token is valid but doesn't own this creator row
124
100
 
125
- All errors expose a `.cause` (the original underlying exception where
126
- applicable) and a `.code` (a stable string identifier you can switch
127
- on without `instanceof`).
101
+ All errors expose a `.code` (a stable string identifier you can
102
+ switch on without `instanceof`) and a `.status` (the HTTP status
103
+ returned by the MCP server, where applicable).
128
104
 
129
105
  ## TypeScript support
130
106
 
131
107
  The package ships its own `.d.mts` declaration file. No additional
132
108
  `@types/*` packages are needed. The runtime bundle is fully
133
- self-contained: zero `@honest-pitches/*` runtime dependencies.
134
-
135
- > **Note for TypeScript consumers.** The declaration file
136
- > `dist/index.d.mts` re-exports a small number of framework and
137
- > segment type aliases. These types are inlined (via `export type`)
138
- > so consumer-side `tsc` works without any extra `paths` mapping in
139
- > your `tsconfig.json`. If you see a `TS2307` "cannot find module
140
- > `@honest-pitches/pitch-core`" error, you have an older copy of the
141
- > SDK — upgrade to `>=0.4.6`.
109
+ self-contained: zero `@honest-pitches/*` runtime dependencies,
110
+ zero backend SDK runtime dependency.
142
111
 
143
112
  ## Build (for SDK maintainers)
144
113
 
@@ -154,4 +123,4 @@ pnpm typecheck # tsc --noEmit
154
123
  UNLICENSED — internal Honest Pitches use only. The package is
155
124
  published publicly on npmjs.com for the convenience of external
156
125
  developers building on top of the platform; redistribution and
157
- modification are not permitted.
126
+ modification are not permitted.