@honest-pitches/pitch-sdk 0.4.6 → 0.5.1
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 +80 -0
- package/README.md +38 -69
- package/dist/index.cjs +156 -547
- package/dist/index.cjs.map +4 -4
- package/dist/index.d.mts +3 -4
- package/dist/index.mjs +156 -540
- package/dist/index.mjs.map +4 -4
- package/package.json +6 -6
package/dist/index.cjs
CHANGED
|
@@ -31,168 +31,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
31
31
|
));
|
|
32
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
33
|
|
|
34
|
-
// vendor/platform-libs/pitcher-api-key-core/dist/index.cjs
|
|
35
|
-
var require_dist = __commonJS({
|
|
36
|
-
"vendor/platform-libs/pitcher-api-key-core/dist/index.cjs"(exports2, module2) {
|
|
37
|
-
"use strict";
|
|
38
|
-
var __defProp2 = Object.defineProperty;
|
|
39
|
-
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
40
|
-
var __getOwnPropNames2 = Object.getOwnPropertyNames;
|
|
41
|
-
var __hasOwnProp2 = Object.prototype.hasOwnProperty;
|
|
42
|
-
var __export2 = (target, all) => {
|
|
43
|
-
for (var name in all)
|
|
44
|
-
__defProp2(target, name, { get: all[name], enumerable: true });
|
|
45
|
-
};
|
|
46
|
-
var __copyProps2 = (to, from, except, desc) => {
|
|
47
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
48
|
-
for (let key of __getOwnPropNames2(from))
|
|
49
|
-
if (!__hasOwnProp2.call(to, key) && key !== except)
|
|
50
|
-
__defProp2(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc2(from, key)) || desc.enumerable });
|
|
51
|
-
}
|
|
52
|
-
return to;
|
|
53
|
-
};
|
|
54
|
-
var __toCommonJS2 = (mod) => __copyProps2(__defProp2({}, "__esModule", { value: true }), mod);
|
|
55
|
-
var index_exports2 = {};
|
|
56
|
-
__export2(index_exports2, {
|
|
57
|
-
ALL_API_KEY_SCOPES: () => ALL_API_KEY_SCOPES,
|
|
58
|
-
API_KEY_PREFIX: () => API_KEY_PREFIX,
|
|
59
|
-
API_KEY_PREFIX_LEN: () => API_KEY_PREFIX_LEN,
|
|
60
|
-
API_KEY_RANDOM_LEN: () => API_KEY_RANDOM_LEN,
|
|
61
|
-
HASH_ALGO: () => HASH_ALGO,
|
|
62
|
-
extractKeyPrefix: () => extractKeyPrefix2,
|
|
63
|
-
generateApiKeyRandomSegment: () => generateApiKeyRandomSegment,
|
|
64
|
-
hashApiKey: () => hashApiKey,
|
|
65
|
-
isApiKeyScope: () => isApiKeyScope,
|
|
66
|
-
isApiKeyUsable: () => isApiKeyUsable2,
|
|
67
|
-
isWellFormedApiKey: () => isWellFormedApiKey2,
|
|
68
|
-
mintApiKey: () => mintApiKey,
|
|
69
|
-
parseApiKeyScopes: () => parseApiKeyScopes,
|
|
70
|
-
parseBearerHeader: () => parseBearerHeader,
|
|
71
|
-
verifyApiKey: () => verifyApiKey2
|
|
72
|
-
});
|
|
73
|
-
module2.exports = __toCommonJS2(index_exports2);
|
|
74
|
-
var import_node_crypto = require("crypto");
|
|
75
|
-
var API_KEY_PREFIX = "hp_pk_";
|
|
76
|
-
var API_KEY_PREFIX_LEN = 8;
|
|
77
|
-
var API_KEY_RANDOM_LEN = 48;
|
|
78
|
-
var HASH_ALGO = "sha256";
|
|
79
|
-
var BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
|
80
|
-
function generateApiKeyRandomSegment(len) {
|
|
81
|
-
if (!Number.isInteger(len) || len <= 0) {
|
|
82
|
-
throw new Error("len must be a positive integer");
|
|
83
|
-
}
|
|
84
|
-
const out = [];
|
|
85
|
-
while (out.length < len) {
|
|
86
|
-
const buf = (0, import_node_crypto.randomBytes)(len + 4);
|
|
87
|
-
for (let i = 0; i < buf.length && out.length < len; i++) {
|
|
88
|
-
const byte = buf[i];
|
|
89
|
-
if (byte < 248) {
|
|
90
|
-
out.push(BASE62[byte % 62]);
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
return out.join("");
|
|
95
|
-
}
|
|
96
|
-
function hashApiKey(rawToken) {
|
|
97
|
-
if (typeof rawToken !== "string" || rawToken.length === 0) {
|
|
98
|
-
throw new Error("hashApiKey: rawToken must be a non-empty string");
|
|
99
|
-
}
|
|
100
|
-
return (0, import_node_crypto.createHash)(HASH_ALGO).update(rawToken, "utf8").digest("hex");
|
|
101
|
-
}
|
|
102
|
-
function isWellFormedApiKey2(rawToken) {
|
|
103
|
-
if (typeof rawToken !== "string") return false;
|
|
104
|
-
if (!rawToken.startsWith(API_KEY_PREFIX)) return false;
|
|
105
|
-
const rest = rawToken.slice(API_KEY_PREFIX.length);
|
|
106
|
-
if (rest.length !== API_KEY_RANDOM_LEN) return false;
|
|
107
|
-
for (let i = 0; i < rest.length; i++) {
|
|
108
|
-
const code = rest.charCodeAt(i);
|
|
109
|
-
const isDigit = code >= 48 && code <= 57;
|
|
110
|
-
const isUpper = code >= 65 && code <= 90;
|
|
111
|
-
const isLower = code >= 97 && code <= 122;
|
|
112
|
-
if (!isDigit && !isUpper && !isLower) return false;
|
|
113
|
-
}
|
|
114
|
-
return true;
|
|
115
|
-
}
|
|
116
|
-
function extractKeyPrefix2(rawToken) {
|
|
117
|
-
if (!isWellFormedApiKey2(rawToken)) return null;
|
|
118
|
-
return rawToken.slice(API_KEY_PREFIX.length, API_KEY_PREFIX.length + API_KEY_PREFIX_LEN);
|
|
119
|
-
}
|
|
120
|
-
var ALL_API_KEY_SCOPES = ["mcp", "sdk"];
|
|
121
|
-
function isApiKeyScope(value) {
|
|
122
|
-
return value === "mcp" || value === "sdk";
|
|
123
|
-
}
|
|
124
|
-
function parseApiKeyScopes(input) {
|
|
125
|
-
if (!Array.isArray(input)) {
|
|
126
|
-
throw new Error("scopes must be an array of strings");
|
|
127
|
-
}
|
|
128
|
-
const seen = /* @__PURE__ */ new Set();
|
|
129
|
-
for (const raw of input) {
|
|
130
|
-
if (!isApiKeyScope(raw)) {
|
|
131
|
-
throw new Error(
|
|
132
|
-
`unknown scope: ${JSON.stringify(raw)}. Valid scopes: ${ALL_API_KEY_SCOPES.join(", ")}`
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
seen.add(raw);
|
|
136
|
-
}
|
|
137
|
-
return Array.from(seen);
|
|
138
|
-
}
|
|
139
|
-
function mintApiKey(input) {
|
|
140
|
-
if (typeof input.label !== "string" || input.label.length === 0) {
|
|
141
|
-
throw new Error("mintApiKey: label must be a non-empty string");
|
|
142
|
-
}
|
|
143
|
-
if (input.label.length > 128) {
|
|
144
|
-
throw new Error("mintApiKey: label must be <= 128 chars");
|
|
145
|
-
}
|
|
146
|
-
if (!Array.isArray(input.scopes) || input.scopes.length === 0) {
|
|
147
|
-
throw new Error("mintApiKey: scopes must be a non-empty array");
|
|
148
|
-
}
|
|
149
|
-
if (input.expiresAt != null && typeof input.expiresAt !== "number") {
|
|
150
|
-
throw new Error("mintApiKey: expiresAt must be a number (epoch ms) or null");
|
|
151
|
-
}
|
|
152
|
-
const randomSegment = generateApiKeyRandomSegment(API_KEY_RANDOM_LEN);
|
|
153
|
-
const rawToken = `${API_KEY_PREFIX}${randomSegment}`;
|
|
154
|
-
const keyHash = hashApiKey(rawToken);
|
|
155
|
-
const keyPrefix = extractKeyPrefix2(rawToken);
|
|
156
|
-
if (keyPrefix === null) {
|
|
157
|
-
throw new Error("mintApiKey: generated key is not well-formed");
|
|
158
|
-
}
|
|
159
|
-
return { rawToken, keyHash, keyPrefix };
|
|
160
|
-
}
|
|
161
|
-
function constantTimeEqualHex(a, b) {
|
|
162
|
-
if (a.length !== b.length) return false;
|
|
163
|
-
let diff = 0;
|
|
164
|
-
for (let i = 0; i < a.length; i++) {
|
|
165
|
-
diff |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
166
|
-
}
|
|
167
|
-
return diff === 0;
|
|
168
|
-
}
|
|
169
|
-
function verifyApiKey2(presented, storedHash) {
|
|
170
|
-
if (typeof presented !== "string" || typeof storedHash !== "string") return false;
|
|
171
|
-
if (presented.length === 0 || storedHash.length === 0) return false;
|
|
172
|
-
let presentedHash;
|
|
173
|
-
try {
|
|
174
|
-
presentedHash = hashApiKey(presented);
|
|
175
|
-
} catch {
|
|
176
|
-
return false;
|
|
177
|
-
}
|
|
178
|
-
return constantTimeEqualHex(presentedHash, storedHash);
|
|
179
|
-
}
|
|
180
|
-
function isApiKeyUsable2(row, now = Date.now()) {
|
|
181
|
-
if (row.revokedAt != null) return false;
|
|
182
|
-
if (row.expiresAt != null && row.expiresAt <= now) return false;
|
|
183
|
-
return true;
|
|
184
|
-
}
|
|
185
|
-
function parseBearerHeader(header) {
|
|
186
|
-
if (!header || typeof header !== "string") return null;
|
|
187
|
-
const match = /^Bearer\s+(\S+)\s*$/i.exec(header.trim());
|
|
188
|
-
if (!match) return null;
|
|
189
|
-
return { token: match[1] };
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
|
|
194
34
|
// vendor/platform-libs/hp-codes/dist/index.cjs
|
|
195
|
-
var
|
|
35
|
+
var require_dist = __commonJS({
|
|
196
36
|
"vendor/platform-libs/hp-codes/dist/index.cjs"(exports2, module2) {
|
|
197
37
|
"use strict";
|
|
198
38
|
var __defProp2 = Object.defineProperty;
|
|
@@ -333,7 +173,7 @@ var require_dist2 = __commonJS({
|
|
|
333
173
|
});
|
|
334
174
|
|
|
335
175
|
// vendor/platform-libs/pitch-core/dist/index.cjs
|
|
336
|
-
var
|
|
176
|
+
var require_dist2 = __commonJS({
|
|
337
177
|
"vendor/platform-libs/pitch-core/dist/index.cjs"(exports2, module2) {
|
|
338
178
|
"use strict";
|
|
339
179
|
var __create2 = Object.create;
|
|
@@ -12342,7 +12182,7 @@ and ensure you are accounting for this risk.
|
|
|
12342
12182
|
TEST_CONCLUSIONS: () => TEST_CONCLUSIONS,
|
|
12343
12183
|
TEST_PRIMARY_METRICS: () => TEST_PRIMARY_METRICS,
|
|
12344
12184
|
TEST_STATUSES: () => TEST_STATUSES,
|
|
12345
|
-
assertFrameworkSwitchable: () =>
|
|
12185
|
+
assertFrameworkSwitchable: () => assertFrameworkSwitchable,
|
|
12346
12186
|
assertSameTestBase: () => assertSameTestBase,
|
|
12347
12187
|
baseKey: () => baseKey,
|
|
12348
12188
|
buildPitchVariantIndexes: () => buildPitchVariantIndexes,
|
|
@@ -12374,13 +12214,13 @@ and ensure you are accounting for this risk.
|
|
|
12374
12214
|
lifecycleFromRow: () => lifecycleFromRow2,
|
|
12375
12215
|
loadFrameworkGuidance: () => loadFrameworkGuidance,
|
|
12376
12216
|
loadFrameworks: () => loadFrameworks3,
|
|
12377
|
-
loadPitchSections: () =>
|
|
12217
|
+
loadPitchSections: () => loadPitchSections,
|
|
12378
12218
|
loadSegments: () => loadSegments2,
|
|
12379
12219
|
mergeSectionsForFramework: () => mergeSectionsForFramework,
|
|
12380
12220
|
mismatchedSectionKinds: () => mismatchedSectionKinds,
|
|
12381
12221
|
normalizeClips: () => normalizeClips,
|
|
12382
12222
|
normalizeCreatePitchInput: () => normalizeCreatePitchInput,
|
|
12383
|
-
normalizePitchContent: () =>
|
|
12223
|
+
normalizePitchContent: () => normalizePitchContent,
|
|
12384
12224
|
normalizePitchLayout: () => normalizePitchLayout,
|
|
12385
12225
|
parseClipsJson: () => parseClipsJson,
|
|
12386
12226
|
parsePitchSectionsColumn: () => parsePitchSectionsColumn,
|
|
@@ -14248,7 +14088,7 @@ Please report this to https://github.com/markedjs/marked.`, e) {
|
|
|
14248
14088
|
function sectionsFromDescription(description) {
|
|
14249
14089
|
return [{ kind: "problem", body: description, mediaIds: [] }];
|
|
14250
14090
|
}
|
|
14251
|
-
function
|
|
14091
|
+
function normalizePitchContent(row) {
|
|
14252
14092
|
const frameworkRaw = String(row.framework ?? "pas");
|
|
14253
14093
|
const framework = isFrameworkId3(frameworkRaw) ? frameworkRaw : "pas";
|
|
14254
14094
|
const parsed = parseSectionsJson2(
|
|
@@ -15598,7 +15438,7 @@ ${raw.slice(0, 200)}`
|
|
|
15598
15438
|
}
|
|
15599
15439
|
return { ok: true };
|
|
15600
15440
|
}
|
|
15601
|
-
var import_hp_codes =
|
|
15441
|
+
var import_hp_codes = require_dist();
|
|
15602
15442
|
function baseKey(pitch) {
|
|
15603
15443
|
const result = (0, import_hp_codes.validateCode)(pitch.hpCode);
|
|
15604
15444
|
if (!result.valid || !result.payload || !result.checkDigit) {
|
|
@@ -15798,7 +15638,7 @@ ${raw.slice(0, 200)}`
|
|
|
15798
15638
|
"expired",
|
|
15799
15639
|
"archived"
|
|
15800
15640
|
];
|
|
15801
|
-
function
|
|
15641
|
+
function assertFrameworkSwitchable(input) {
|
|
15802
15642
|
if (input.status === "draft") return { ok: true };
|
|
15803
15643
|
if (input.status === "live" || input.status === "expired" || input.status === "archived") {
|
|
15804
15644
|
return { ok: false, reason: "immutable" };
|
|
@@ -15810,7 +15650,7 @@ ${raw.slice(0, 200)}`
|
|
|
15810
15650
|
if (from === "draft" && to !== "draft") {
|
|
15811
15651
|
return { ok: false, reason: "locked" };
|
|
15812
15652
|
}
|
|
15813
|
-
return
|
|
15653
|
+
return assertFrameworkSwitchable({ status: from });
|
|
15814
15654
|
}
|
|
15815
15655
|
function isPitchLifecycleState(value) {
|
|
15816
15656
|
return PITCH_LIFECYCLE_STATES.includes(value);
|
|
@@ -16645,7 +16485,7 @@ ${raw.slice(0, 200)}`
|
|
|
16645
16485
|
};
|
|
16646
16486
|
});
|
|
16647
16487
|
}
|
|
16648
|
-
function
|
|
16488
|
+
function loadPitchSections({
|
|
16649
16489
|
pitchId,
|
|
16650
16490
|
doc,
|
|
16651
16491
|
rows,
|
|
@@ -16735,20 +16575,15 @@ ${raw.slice(0, 200)}`
|
|
|
16735
16575
|
// src/index.ts
|
|
16736
16576
|
var index_exports = {};
|
|
16737
16577
|
__export(index_exports, {
|
|
16738
|
-
|
|
16578
|
+
DEFAULT_PITCHER_BASE_URL: () => DEFAULT_PITCHER_BASE_URL,
|
|
16739
16579
|
FrameworkLockedError: () => FrameworkLockedError,
|
|
16740
16580
|
HpCodeImmutableError: () => HpCodeImmutableError,
|
|
16741
16581
|
InvalidSectionKindError: () => InvalidSectionKindError,
|
|
16742
|
-
MEDIA_API_FUNCTION_ID: () => MEDIA_API_FUNCTION_ID,
|
|
16743
|
-
PUBLIC_API_FUNCTION_ID: () => PUBLIC_API_FUNCTION_ID,
|
|
16744
16582
|
PitcherNotAuthenticatedError: () => PitcherNotAuthenticatedError,
|
|
16745
16583
|
PitcherNotOwnedCreatorError: () => PitcherNotOwnedCreatorError,
|
|
16584
|
+
PitcherRequestError: () => PitcherRequestError,
|
|
16746
16585
|
PitcherSdkError: () => PitcherSdkError,
|
|
16747
16586
|
PitchesApi: () => PitchesApi,
|
|
16748
|
-
STRIPE_API_FUNCTION_ID: () => STRIPE_API_FUNCTION_ID,
|
|
16749
|
-
STUDIO_API_FUNCTION_ID: () => STUDIO_API_FUNCTION_ID,
|
|
16750
|
-
appwriteQueryEqual: () => appwriteQueryEqual,
|
|
16751
|
-
appwriteQueryLimit: () => appwriteQueryLimit,
|
|
16752
16587
|
createPitcherClient: () => createPitcherClient,
|
|
16753
16588
|
decodeJwtSub: () => decodeJwtSub,
|
|
16754
16589
|
findCreatorIdForApiKey: () => findCreatorIdForApiKey,
|
|
@@ -16764,9 +16599,6 @@ __export(index_exports, {
|
|
|
16764
16599
|
});
|
|
16765
16600
|
module.exports = __toCommonJS(index_exports);
|
|
16766
16601
|
|
|
16767
|
-
// src/config.ts
|
|
16768
|
-
var import_node_appwrite = require("node-appwrite");
|
|
16769
|
-
|
|
16770
16602
|
// src/errors.ts
|
|
16771
16603
|
var PitcherSdkError = class extends Error {
|
|
16772
16604
|
code;
|
|
@@ -16806,71 +16638,50 @@ var HpCodeImmutableError = class extends PitcherSdkError {
|
|
|
16806
16638
|
this.name = "HpCodeImmutableError";
|
|
16807
16639
|
}
|
|
16808
16640
|
};
|
|
16809
|
-
var
|
|
16641
|
+
var PitcherRequestError = class extends PitcherSdkError {
|
|
16810
16642
|
status;
|
|
16811
|
-
constructor(status, message) {
|
|
16812
|
-
super("
|
|
16813
|
-
this.name = "
|
|
16643
|
+
constructor(status, code, message) {
|
|
16644
|
+
super(code || "PITCHER_REQUEST", message);
|
|
16645
|
+
this.name = "PitcherRequestError";
|
|
16814
16646
|
this.status = status;
|
|
16815
16647
|
}
|
|
16816
16648
|
};
|
|
16817
16649
|
|
|
16818
16650
|
// src/config.ts
|
|
16651
|
+
var DEFAULT_PITCHER_BASE_URL = "https://mcp.honestpitches.com";
|
|
16819
16652
|
function resolvePitcherConfig(input) {
|
|
16820
|
-
if (input.
|
|
16653
|
+
if (input.jwt && input.apiKey) {
|
|
16821
16654
|
throw new PitcherSdkError(
|
|
16822
16655
|
"PITCHER_AUTH_AMBIGUOUS",
|
|
16823
|
-
"Set either
|
|
16656
|
+
"Set either jwt or apiKey, not both \u2014 the SDK can only act as one principal per client"
|
|
16824
16657
|
);
|
|
16825
16658
|
}
|
|
16826
|
-
const
|
|
16827
|
-
|
|
16828
|
-
|
|
16829
|
-
|
|
16830
|
-
|
|
16831
|
-
const c = new import_node_appwrite.Client().setEndpoint(endpoint).setProject(input.projectId);
|
|
16832
|
-
return c;
|
|
16833
|
-
})();
|
|
16834
|
-
if (input.initialJwt) {
|
|
16835
|
-
try {
|
|
16836
|
-
client.setJWT(input.initialJwt);
|
|
16837
|
-
} catch {
|
|
16838
|
-
}
|
|
16839
|
-
}
|
|
16840
|
-
let jwt = input.initialJwt ?? null;
|
|
16841
|
-
let jwtExpiresAt = input.initialJwtExpiresAt ?? null;
|
|
16659
|
+
const baseUrl = (input.baseUrl ?? DEFAULT_PITCHER_BASE_URL).replace(/\/$/, "");
|
|
16660
|
+
const state = {
|
|
16661
|
+
jwt: input.jwt ?? null,
|
|
16662
|
+
jwtExpiresAt: input.jwtExpiresAt ?? null
|
|
16663
|
+
};
|
|
16842
16664
|
const apiKey = input.apiKey ?? null;
|
|
16665
|
+
const fetchImpl = input.fetchImpl ?? globalThis.fetch;
|
|
16666
|
+
if (!fetchImpl) {
|
|
16667
|
+
throw new PitcherSdkError(
|
|
16668
|
+
"PITCHER_NO_FETCH",
|
|
16669
|
+
"PitcherClient requires a fetch implementation \u2014 Node 20+ provides globalThis.fetch; older runtimes must pass { fetchImpl }"
|
|
16670
|
+
);
|
|
16671
|
+
}
|
|
16843
16672
|
return {
|
|
16844
|
-
|
|
16845
|
-
|
|
16846
|
-
|
|
16847
|
-
pitchesTableId: input.pitchesTableId ?? "pitches",
|
|
16848
|
-
creatorsTableId: input.creatorsTableId ?? "creators",
|
|
16849
|
-
pitchSectionsTableId: input.pitchSectionsTableId ?? "pitch_sections",
|
|
16850
|
-
pitchCreateFunctionId: input.pitchCreateFunctionId ?? "pitch-write",
|
|
16851
|
-
pitchAssetUploadFunctionId: input.pitchAssetUploadFunctionId ?? "pitch-asset-upload",
|
|
16852
|
-
pitcherApiKeysTableId: input.pitcherApiKeysTableId ?? "pitcher_api_keys",
|
|
16853
|
-
client,
|
|
16854
|
-
getJwt: () => jwt,
|
|
16855
|
-
getJwtExpiresAt: () => jwtExpiresAt,
|
|
16673
|
+
baseUrl,
|
|
16674
|
+
getJwt: () => state.jwt,
|
|
16675
|
+
getJwtExpiresAt: () => state.jwtExpiresAt,
|
|
16856
16676
|
setJwt: (next, expiresAt) => {
|
|
16857
|
-
jwt = next;
|
|
16858
|
-
jwtExpiresAt = expiresAt ?? null;
|
|
16859
|
-
if (!apiKey) {
|
|
16860
|
-
try {
|
|
16861
|
-
client.setJWT(next);
|
|
16862
|
-
} catch {
|
|
16863
|
-
}
|
|
16864
|
-
}
|
|
16677
|
+
state.jwt = next;
|
|
16678
|
+
state.jwtExpiresAt = expiresAt ?? null;
|
|
16865
16679
|
},
|
|
16866
|
-
getApiKey: () => apiKey
|
|
16680
|
+
getApiKey: () => apiKey,
|
|
16681
|
+
fetchImpl
|
|
16867
16682
|
};
|
|
16868
16683
|
}
|
|
16869
16684
|
|
|
16870
|
-
// src/creators.ts
|
|
16871
|
-
var import_node_appwrite3 = require("node-appwrite");
|
|
16872
|
-
var import_pitcher_api_key_core = __toESM(require_dist(), 1);
|
|
16873
|
-
|
|
16874
16685
|
// src/jwt.ts
|
|
16875
16686
|
function decodeJwtSub(jwt) {
|
|
16876
16687
|
const parts = jwt.split(".");
|
|
@@ -16893,214 +16704,92 @@ function isJwtExpired(expiresAt) {
|
|
|
16893
16704
|
return Date.now() >= expiresAt;
|
|
16894
16705
|
}
|
|
16895
16706
|
|
|
16896
|
-
// src/
|
|
16897
|
-
|
|
16898
|
-
|
|
16899
|
-
|
|
16900
|
-
var PUBLIC_API_FUNCTION_ID = "honest-pitches-public-api";
|
|
16901
|
-
var STRIPE_API_FUNCTION_ID = "stripe-api";
|
|
16902
|
-
var STUDIO_API_FUNCTION_ID = "honest-pitches-studio-api";
|
|
16903
|
-
var MEDIA_API_FUNCTION_ID = "honest-pitches-media";
|
|
16904
|
-
var FUNCTION_BUNDLE_MAP = {
|
|
16905
|
-
"pitch-write": STUDIO_API_FUNCTION_ID,
|
|
16906
|
-
"pitch-transition": STUDIO_API_FUNCTION_ID,
|
|
16907
|
-
"pitch-asset-upload": MEDIA_API_FUNCTION_ID,
|
|
16908
|
-
"agent-magic-link-issue": STUDIO_API_FUNCTION_ID
|
|
16909
|
-
};
|
|
16910
|
-
function resolveConsolidatedRoute(functionId, path) {
|
|
16911
|
-
const bundle = FUNCTION_BUNDLE_MAP[functionId];
|
|
16912
|
-
if (!bundle) return { functionId, path };
|
|
16913
|
-
const sub = path.startsWith("/") ? path : `/${path}`;
|
|
16914
|
-
const prefixed = sub === "/" ? `/${functionId}` : `/${functionId}${sub}`;
|
|
16915
|
-
return { functionId: bundle, path: prefixed };
|
|
16916
|
-
}
|
|
16917
|
-
|
|
16918
|
-
// src/http.ts
|
|
16919
|
-
function requireJwt(config) {
|
|
16707
|
+
// src/fetch-pitcher.ts
|
|
16708
|
+
function requireAuthHeader(config) {
|
|
16709
|
+
const apiKey = config.getApiKey();
|
|
16710
|
+
if (apiKey) return `Bearer ${apiKey}`;
|
|
16920
16711
|
const jwt = config.getJwt();
|
|
16921
16712
|
if (!jwt) {
|
|
16922
|
-
throw new PitcherNotAuthenticatedError(
|
|
16713
|
+
throw new PitcherNotAuthenticatedError(
|
|
16714
|
+
"PitcherClient requires { apiKey: 'hp_pk_\u2026' } or { jwt: '<jwt>' }"
|
|
16715
|
+
);
|
|
16923
16716
|
}
|
|
16924
16717
|
if (isJwtExpired(config.getJwtExpiresAt())) {
|
|
16925
|
-
throw new PitcherNotAuthenticatedError(
|
|
16718
|
+
throw new PitcherNotAuthenticatedError(
|
|
16719
|
+
"JWT expired \u2014 refresh via pitcher-mcp OAuth"
|
|
16720
|
+
);
|
|
16926
16721
|
}
|
|
16927
|
-
return jwt
|
|
16722
|
+
return `Bearer ${jwt}`;
|
|
16928
16723
|
}
|
|
16929
|
-
function
|
|
16930
|
-
|
|
16931
|
-
|
|
16932
|
-
|
|
16933
|
-
|
|
16934
|
-
|
|
16935
|
-
|
|
16936
|
-
|
|
16937
|
-
|
|
16938
|
-
|
|
16939
|
-
|
|
16940
|
-
|
|
16941
|
-
const code = err.code;
|
|
16942
|
-
const message = err.message;
|
|
16943
|
-
const status = typeof code === "number" && code > 0 ? code : 500;
|
|
16944
|
-
if (status === 401) {
|
|
16945
|
-
throw new PitcherNotAuthenticatedError(message || "Unauthorized");
|
|
16946
|
-
}
|
|
16947
|
-
throw new AppwriteRequestError(status, message || fallbackMessage);
|
|
16724
|
+
async function fetchPitches(config, opts) {
|
|
16725
|
+
const auth = requireAuthHeader(config);
|
|
16726
|
+
const url = `${config.baseUrl}/pitcher${opts.path.startsWith("/") ? opts.path : `/${opts.path}`}`;
|
|
16727
|
+
const headers = {
|
|
16728
|
+
Authorization: auth,
|
|
16729
|
+
Accept: "application/json",
|
|
16730
|
+
"User-Agent": "@honest-pitches/pitch-sdk/0.5.0"
|
|
16731
|
+
};
|
|
16732
|
+
let body;
|
|
16733
|
+
if (opts.body !== void 0 && (opts.method === "POST" || opts.method === "PATCH")) {
|
|
16734
|
+
headers["Content-Type"] = "application/json";
|
|
16735
|
+
body = JSON.stringify(opts.body);
|
|
16948
16736
|
}
|
|
16949
|
-
|
|
16950
|
-
500,
|
|
16951
|
-
err instanceof Error ? err.message : fallbackMessage
|
|
16952
|
-
);
|
|
16953
|
-
}
|
|
16954
|
-
function tablesDB(config) {
|
|
16955
|
-
return new import_node_appwrite2.TablesDB(config.client);
|
|
16956
|
-
}
|
|
16957
|
-
function functions(config) {
|
|
16958
|
-
return new import_node_appwrite2.Functions(config.client);
|
|
16959
|
-
}
|
|
16960
|
-
function applyApiKeyHeader(config) {
|
|
16961
|
-
const apiKey = config.getApiKey();
|
|
16962
|
-
if (!apiKey) return;
|
|
16963
|
-
config.client.addHeader("Authorization", `Bearer ${apiKey}`);
|
|
16964
|
-
}
|
|
16965
|
-
async function executePitchFunction(config, opts) {
|
|
16966
|
-
if (!config.getApiKey()) requireJwt(config);
|
|
16967
|
-
applyApiKeyHeader(config);
|
|
16968
|
-
const fn = functions(config);
|
|
16969
|
-
const legacyFn = opts.functionId ?? config.pitchCreateFunctionId;
|
|
16970
|
-
const route = resolveConsolidatedRoute(legacyFn, opts.path ?? "/");
|
|
16737
|
+
let res;
|
|
16971
16738
|
try {
|
|
16972
|
-
|
|
16973
|
-
functionId: route.functionId,
|
|
16974
|
-
body: JSON.stringify(opts.body),
|
|
16975
|
-
async: false,
|
|
16739
|
+
res = await config.fetchImpl(url, {
|
|
16976
16740
|
method: opts.method,
|
|
16977
|
-
|
|
16978
|
-
|
|
16979
|
-
|
|
16980
|
-
const status = execution.responseStatusCode ?? 201;
|
|
16981
|
-
const responseBody = execution.responseBody ?? "";
|
|
16982
|
-
if (status >= 400) {
|
|
16983
|
-
let message = responseBody;
|
|
16984
|
-
try {
|
|
16985
|
-
const parsed = JSON.parse(responseBody);
|
|
16986
|
-
message = parsed.error ?? responseBody;
|
|
16987
|
-
} catch {
|
|
16988
|
-
}
|
|
16989
|
-
throw new AppwriteRequestError(status, message);
|
|
16990
|
-
}
|
|
16991
|
-
if (!responseBody) {
|
|
16992
|
-
throw new AppwriteRequestError(status, "Empty response from pitch-write");
|
|
16993
|
-
}
|
|
16994
|
-
return JSON.parse(responseBody);
|
|
16995
|
-
} catch (err) {
|
|
16996
|
-
if (err instanceof AppwriteRequestError) throw err;
|
|
16997
|
-
if (err instanceof PitcherNotAuthenticatedError) throw err;
|
|
16998
|
-
mapAppwriteException(err, "pitch-write execution failed");
|
|
16999
|
-
}
|
|
17000
|
-
}
|
|
17001
|
-
async function tablesListRows(config, tableId, queries) {
|
|
17002
|
-
if (!config.getApiKey()) requireJwt(config);
|
|
17003
|
-
applyApiKeyHeader(config);
|
|
17004
|
-
try {
|
|
17005
|
-
const result = await tablesDB(config).listRows({
|
|
17006
|
-
databaseId: config.databaseId,
|
|
17007
|
-
tableId,
|
|
17008
|
-
queries
|
|
16741
|
+
headers,
|
|
16742
|
+
...body !== void 0 ? { body } : {},
|
|
16743
|
+
...opts.signal ? { signal: opts.signal } : {}
|
|
17009
16744
|
});
|
|
17010
|
-
const total = result.total ?? 0;
|
|
17011
|
-
const rows = result.rows ?? [];
|
|
17012
|
-
return { total, documents: rows };
|
|
17013
16745
|
} catch (err) {
|
|
17014
|
-
|
|
16746
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
16747
|
+
throw new PitcherRequestError(0, "PITCHER_NETWORK", `fetchPitches failed: ${message}`);
|
|
17015
16748
|
}
|
|
17016
|
-
|
|
17017
|
-
|
|
17018
|
-
if (!config.getApiKey()) requireJwt(config);
|
|
17019
|
-
applyApiKeyHeader(config);
|
|
16749
|
+
const text = await res.text();
|
|
16750
|
+
let envelope = null;
|
|
17020
16751
|
try {
|
|
17021
|
-
|
|
17022
|
-
|
|
17023
|
-
|
|
17024
|
-
|
|
17025
|
-
|
|
17026
|
-
|
|
17027
|
-
} catch (err) {
|
|
17028
|
-
mapAppwriteException(err, `getRow(${tableId}/${rowId}) failed`);
|
|
17029
|
-
}
|
|
17030
|
-
}
|
|
17031
|
-
|
|
17032
|
-
// src/creators.ts
|
|
17033
|
-
async function findCreatorIdForJwtUser(config) {
|
|
17034
|
-
const jwt = config.getJwt();
|
|
17035
|
-
if (!jwt) throw new PitcherNotAuthenticatedError();
|
|
17036
|
-
const userId = decodeJwtSub(jwt);
|
|
17037
|
-
if (!userId) {
|
|
17038
|
-
throw new PitcherNotAuthenticatedError(
|
|
17039
|
-
"JWT missing userId/sub \u2014 use account.createJWT().jwt from studio"
|
|
17040
|
-
);
|
|
17041
|
-
}
|
|
17042
|
-
const json = await tablesListRows(
|
|
17043
|
-
config,
|
|
17044
|
-
config.creatorsTableId,
|
|
17045
|
-
[import_node_appwrite3.Query.equal("userId", userId), import_node_appwrite3.Query.limit(1)]
|
|
17046
|
-
);
|
|
17047
|
-
const doc = json.documents?.[0];
|
|
17048
|
-
return doc?.$id ? String(doc.$id) : null;
|
|
17049
|
-
}
|
|
17050
|
-
async function findCreatorIdForApiKey(config) {
|
|
17051
|
-
const apiKey = config.getApiKey();
|
|
17052
|
-
if (!apiKey) {
|
|
17053
|
-
throw new PitcherNotAuthenticatedError(
|
|
17054
|
-
"findCreatorIdForApiKey requires the SDK to be configured with { apiKey: 'hp_pk_\u2026' }; for JWT auth use findCreatorIdForJwtUser instead"
|
|
16752
|
+
envelope = JSON.parse(text);
|
|
16753
|
+
} catch {
|
|
16754
|
+
throw new PitcherRequestError(
|
|
16755
|
+
res.status,
|
|
16756
|
+
"PITCHER_NON_JSON",
|
|
16757
|
+
`MCP server returned non-JSON body (status ${res.status}): ${text.slice(0, 256)}`
|
|
17055
16758
|
);
|
|
17056
16759
|
}
|
|
17057
|
-
if (
|
|
17058
|
-
return
|
|
16760
|
+
if (envelope && envelope.ok === true) {
|
|
16761
|
+
return envelope.data;
|
|
17059
16762
|
}
|
|
17060
|
-
|
|
17061
|
-
|
|
17062
|
-
|
|
16763
|
+
if (envelope && envelope.ok === false) {
|
|
16764
|
+
throw new PitcherRequestError(
|
|
16765
|
+
res.status,
|
|
16766
|
+
envelope.error.code,
|
|
16767
|
+
envelope.error.message
|
|
16768
|
+
);
|
|
17063
16769
|
}
|
|
17064
|
-
|
|
17065
|
-
|
|
17066
|
-
|
|
17067
|
-
|
|
17068
|
-
);
|
|
17069
|
-
const keyDoc = apiKeyRows.documents?.[0];
|
|
17070
|
-
if (!keyDoc) return null;
|
|
17071
|
-
const keyHash = String(keyDoc["keyHash"] ?? "");
|
|
17072
|
-
if (!(0, import_pitcher_api_key_core.verifyApiKey)(apiKey, keyHash)) return null;
|
|
17073
|
-
const rowShape = {
|
|
17074
|
-
revokedAt: typeof keyDoc["revokedAt"] === "string" ? Date.parse(String(keyDoc["revokedAt"])) : null,
|
|
17075
|
-
expiresAt: typeof keyDoc["expiresAt"] === "string" ? Date.parse(String(keyDoc["expiresAt"])) : null
|
|
17076
|
-
};
|
|
17077
|
-
if (!(0, import_pitcher_api_key_core.isApiKeyUsable)(rowShape)) return null;
|
|
17078
|
-
const userId = String(keyDoc["userId"] ?? "");
|
|
17079
|
-
if (!userId) return null;
|
|
17080
|
-
const creatorRows = await tablesListRows(
|
|
17081
|
-
config,
|
|
17082
|
-
config.creatorsTableId,
|
|
17083
|
-
[import_node_appwrite3.Query.equal("userId", userId), import_node_appwrite3.Query.limit(1)]
|
|
16770
|
+
throw new PitcherRequestError(
|
|
16771
|
+
res.status,
|
|
16772
|
+
"PITCHER_MALFORMED",
|
|
16773
|
+
`MCP server returned malformed envelope: ${text.slice(0, 256)}`
|
|
17084
16774
|
);
|
|
17085
|
-
const creatorDoc = creatorRows.documents?.[0];
|
|
17086
|
-
return creatorDoc?.$id ? String(creatorDoc.$id) : null;
|
|
17087
16775
|
}
|
|
17088
16776
|
|
|
17089
|
-
// src/
|
|
17090
|
-
|
|
17091
|
-
|
|
17092
|
-
|
|
17093
|
-
|
|
17094
|
-
|
|
17095
|
-
return
|
|
16777
|
+
// src/creators.ts
|
|
16778
|
+
async function findCreatorIdForJwtUser(config) {
|
|
16779
|
+
const result = await fetchPitches(config, {
|
|
16780
|
+
method: "GET",
|
|
16781
|
+
path: "/creators/me"
|
|
16782
|
+
});
|
|
16783
|
+
return result.creatorId;
|
|
17096
16784
|
}
|
|
17097
|
-
function
|
|
17098
|
-
return
|
|
16785
|
+
async function findCreatorIdForApiKey(config) {
|
|
16786
|
+
return findCreatorIdForJwtUser(config);
|
|
17099
16787
|
}
|
|
17100
16788
|
|
|
17101
16789
|
// src/pitches.ts
|
|
17102
|
-
|
|
17103
|
-
|
|
16790
|
+
var import_pitch_core = __toESM(require_dist2(), 1);
|
|
16791
|
+
function rowToPitch(doc) {
|
|
16792
|
+
const sections = Array.isArray(doc.sections) ? doc.sections : [];
|
|
17104
16793
|
const lifecycle = (0, import_pitch_core.lifecycleFromRow)({
|
|
17105
16794
|
status: String(doc.status ?? "draft"),
|
|
17106
16795
|
previewToken: doc.previewToken
|
|
@@ -17112,14 +16801,6 @@ function rowToPitch(doc, precomputedSections) {
|
|
|
17112
16801
|
status: String(doc.status ?? "draft")
|
|
17113
16802
|
};
|
|
17114
16803
|
}
|
|
17115
|
-
async function loadPitchSectionsFor(config, pitchId) {
|
|
17116
|
-
const json = await tablesListRows(
|
|
17117
|
-
config,
|
|
17118
|
-
config.pitchSectionsTableId,
|
|
17119
|
-
[appwriteQueryEqual("pitchId", pitchId)]
|
|
17120
|
-
);
|
|
17121
|
-
return json.documents ?? [];
|
|
17122
|
-
}
|
|
17123
16804
|
function validatePitchContent(framework, sections) {
|
|
17124
16805
|
if (!(0, import_pitch_core.isFrameworkId)(framework)) {
|
|
17125
16806
|
throw new InvalidSectionKindError(`Unknown framework: ${framework}`);
|
|
@@ -17132,7 +16813,9 @@ function validatePitchContent(framework, sections) {
|
|
|
17132
16813
|
}
|
|
17133
16814
|
}
|
|
17134
16815
|
async function assertCreatorOwnedByAuthContext(config, creatorId) {
|
|
17135
|
-
if (!config.getJwt()
|
|
16816
|
+
if (!config.getJwt() && !config.getApiKey()) {
|
|
16817
|
+
throw new PitcherNotAuthenticatedError();
|
|
16818
|
+
}
|
|
17136
16819
|
const owningCreatorId = await findCreatorIdForJwtUser(config);
|
|
17137
16820
|
if (!owningCreatorId) {
|
|
17138
16821
|
throw new PitcherNotAuthenticatedError(
|
|
@@ -17149,10 +16832,8 @@ var PitchesApi = class {
|
|
|
17149
16832
|
}
|
|
17150
16833
|
config;
|
|
17151
16834
|
async create(input) {
|
|
17152
|
-
await assertCreatorOwnedByAuthContext(this.config, input.creatorId);
|
|
17153
16835
|
validatePitchContent(input.framework, input.sections);
|
|
17154
|
-
|
|
17155
|
-
if (!switchCheck.ok) throw new FrameworkLockedError();
|
|
16836
|
+
await assertCreatorOwnedByAuthContext(this.config, input.creatorId);
|
|
17156
16837
|
const payload = {
|
|
17157
16838
|
creatorId: input.creatorId,
|
|
17158
16839
|
slug: input.slug,
|
|
@@ -17167,151 +16848,76 @@ var PitchesApi = class {
|
|
|
17167
16848
|
ctaLabel: input.ctaLabel ?? "Get it now",
|
|
17168
16849
|
intendedAudience: input.intendedAudience ?? "",
|
|
17169
16850
|
visibility: input.visibility ?? "private"
|
|
17170
|
-
// 2026-06-21: `listingMode` removed (clean-break).
|
|
17171
16851
|
};
|
|
17172
16852
|
if (input.categorySlug != null) payload.categorySlug = input.categorySlug;
|
|
17173
16853
|
if (input.priceNote != null && input.priceNote !== "") {
|
|
17174
16854
|
payload.priceNote = String(input.priceNote).slice(0, 64);
|
|
17175
16855
|
}
|
|
17176
|
-
const doc = await
|
|
16856
|
+
const doc = await fetchPitches(this.config, {
|
|
17177
16857
|
method: "POST",
|
|
17178
|
-
path: "/",
|
|
16858
|
+
path: "/pitches",
|
|
17179
16859
|
body: payload
|
|
17180
16860
|
});
|
|
17181
16861
|
return rowToPitch(doc);
|
|
17182
16862
|
}
|
|
17183
16863
|
async get(id) {
|
|
17184
|
-
const doc = await
|
|
17185
|
-
|
|
17186
|
-
|
|
17187
|
-
id
|
|
17188
|
-
);
|
|
17189
|
-
const rows = await loadPitchSectionsFor(this.config, id);
|
|
17190
|
-
const resolved = (0, import_pitch_core.loadPitchSections)({
|
|
17191
|
-
pitchId: id,
|
|
17192
|
-
doc,
|
|
17193
|
-
rows,
|
|
17194
|
-
// The SDK is silent on the self-heal path; the build log
|
|
17195
|
-
// catches disagreement via its own `loadPitchSections`
|
|
17196
|
-
// invocation. Keeping the SDK quiet preserves the
|
|
17197
|
-
// "read-only" contract of `pitches.get`.
|
|
17198
|
-
log: () => {
|
|
17199
|
-
}
|
|
16864
|
+
const doc = await fetchPitches(this.config, {
|
|
16865
|
+
method: "GET",
|
|
16866
|
+
path: `/pitches/${encodeURIComponent(id)}`
|
|
17200
16867
|
});
|
|
17201
|
-
return rowToPitch(doc
|
|
16868
|
+
return rowToPitch(doc);
|
|
17202
16869
|
}
|
|
17203
16870
|
async find(opts = {}) {
|
|
17204
|
-
const
|
|
17205
|
-
if (opts.status)
|
|
17206
|
-
|
|
17207
|
-
|
|
17208
|
-
const
|
|
17209
|
-
|
|
17210
|
-
|
|
17211
|
-
queries
|
|
17212
|
-
);
|
|
17213
|
-
const docs = json.documents ?? [];
|
|
17214
|
-
if (docs.length === 0) return [];
|
|
17215
|
-
const pitchIds = docs.map((d) => String(d["$id"] ?? ""));
|
|
17216
|
-
const sectionRowsByPitch = /* @__PURE__ */ new Map();
|
|
17217
|
-
for (const pitchId of pitchIds) {
|
|
17218
|
-
if (!pitchId) continue;
|
|
17219
|
-
if (sectionRowsByPitch.has(pitchId)) continue;
|
|
17220
|
-
const rows = await loadPitchSectionsFor(this.config, pitchId);
|
|
17221
|
-
sectionRowsByPitch.set(pitchId, rows);
|
|
17222
|
-
}
|
|
17223
|
-
return docs.map((doc) => {
|
|
17224
|
-
const pitchId = String(doc["$id"] ?? "");
|
|
17225
|
-
const rows = sectionRowsByPitch.get(pitchId) ?? [];
|
|
17226
|
-
const resolved = (0, import_pitch_core.loadPitchSections)({
|
|
17227
|
-
pitchId,
|
|
17228
|
-
doc,
|
|
17229
|
-
rows,
|
|
17230
|
-
log: () => {
|
|
17231
|
-
}
|
|
17232
|
-
});
|
|
17233
|
-
return rowToPitch(doc, resolved.sections);
|
|
16871
|
+
const params = new URLSearchParams();
|
|
16872
|
+
if (opts.status) params.set("status", opts.status);
|
|
16873
|
+
if (typeof opts.limit === "number") params.set("limit", String(opts.limit));
|
|
16874
|
+
const qs = params.toString();
|
|
16875
|
+
const docs = await fetchPitches(this.config, {
|
|
16876
|
+
method: "GET",
|
|
16877
|
+
path: `/pitches${qs ? `?${qs}` : ""}`
|
|
17234
16878
|
});
|
|
16879
|
+
return docs.map((d) => rowToPitch(d));
|
|
17235
16880
|
}
|
|
17236
16881
|
async update(id, input) {
|
|
17237
|
-
const
|
|
17238
|
-
await assertCreatorOwnedByAuthContext(this.config, String(existing.creatorId));
|
|
17239
|
-
const nextFramework = input.framework ?? existing.framework;
|
|
17240
|
-
const nextSections = input.sections ?? (0, import_pitch_core.parseSectionsJson)(existing.sections);
|
|
17241
|
-
if (input.framework != null && input.framework !== existing.framework) {
|
|
17242
|
-
const from = existing.lifecycle;
|
|
17243
|
-
const check = (0, import_pitch_core.canChangeFramework)(from, from);
|
|
17244
|
-
if (!check.ok) throw new FrameworkLockedError(check.reason);
|
|
17245
|
-
}
|
|
17246
|
-
validatePitchContent(nextFramework, nextSections);
|
|
17247
|
-
const body = { ...input };
|
|
17248
|
-
const doc = await executePitchFunction(this.config, {
|
|
16882
|
+
const doc = await fetchPitches(this.config, {
|
|
17249
16883
|
method: "PATCH",
|
|
17250
|
-
path:
|
|
17251
|
-
body
|
|
16884
|
+
path: `/pitches/${encodeURIComponent(id)}`,
|
|
16885
|
+
body: { ...input }
|
|
17252
16886
|
});
|
|
17253
16887
|
return rowToPitch(doc);
|
|
17254
16888
|
}
|
|
17255
16889
|
async transition(id, input) {
|
|
17256
|
-
const
|
|
17257
|
-
await assertCreatorOwnedByAuthContext(this.config, String(existing.creatorId));
|
|
17258
|
-
const doc = await executePitchFunction(this.config, {
|
|
16890
|
+
const doc = await fetchPitches(this.config, {
|
|
17259
16891
|
method: "POST",
|
|
17260
|
-
path:
|
|
17261
|
-
body: {
|
|
17262
|
-
to: input.to,
|
|
17263
|
-
previewToken: input.previewToken
|
|
17264
|
-
}
|
|
16892
|
+
path: `/pitches/${encodeURIComponent(id)}/transition`,
|
|
16893
|
+
body: { to: input.to, previewToken: input.previewToken }
|
|
17265
16894
|
});
|
|
17266
16895
|
return rowToPitch(doc);
|
|
17267
16896
|
}
|
|
17268
16897
|
/**
|
|
17269
16898
|
* Upload a media file (thumbnail, og-image, video-poster, etc.)
|
|
17270
|
-
*
|
|
17271
|
-
*
|
|
17272
|
-
*
|
|
17273
|
-
* Added 2026-06-23 to address Finding #4 of
|
|
17274
|
-
* `docs-new/hp-cli-cycle-finds-2026-06-23.md`. The CLI's
|
|
17275
|
-
* `hp pitches media upload` command calls this method.
|
|
17276
|
-
*
|
|
17277
|
-
* The `kind` must be one of the `AssetKind` values exported by
|
|
17278
|
-
* `@honest-pitches/pitch-asset-core`. The server reads the bytes
|
|
17279
|
-
* from `bytesBase64` (the base64 of `bytes`), uploads them to
|
|
17280
|
-
* Bunny Storage, and writes a `pitch_assets` row. The returned
|
|
17281
|
-
* record carries the wired `bunnyPath` and `cdnUrl`.
|
|
16899
|
+
* via the MCP server's `POST /pitcher/pitches/:id/media` route.
|
|
16900
|
+
* The MCP server handles the Bunny Storage upload + the
|
|
16901
|
+
* `pitch_assets` row insert.
|
|
17282
16902
|
*/
|
|
17283
16903
|
async uploadMedia(input) {
|
|
17284
|
-
const doc = await
|
|
17285
|
-
functionId: this.config.pitchAssetUploadFunctionId,
|
|
16904
|
+
const doc = await fetchPitches(this.config, {
|
|
17286
16905
|
method: "POST",
|
|
17287
|
-
path:
|
|
16906
|
+
path: `/pitches/${encodeURIComponent(input.pitchId)}/media`,
|
|
17288
16907
|
body: {
|
|
17289
|
-
pitchId: input.pitchId,
|
|
17290
16908
|
kind: input.kind,
|
|
17291
16909
|
mimeType: input.mimeType,
|
|
17292
|
-
|
|
17293
|
-
isPublic: input.isPublic ?? true
|
|
17294
|
-
// Buffer.from(Uint8Array) is the canonical Node 22 path to
|
|
17295
|
-
// get the raw bytes. In browsers this is also covered by the
|
|
17296
|
-
// same Buffer.from(uint8) shim, but the SDK is Node-only
|
|
17297
|
-
// today so we don't need a cross-runtime polyfill.
|
|
17298
|
-
bytesBase64: Buffer.from(input.bytes).toString("base64")
|
|
16910
|
+
bytesBase64: Buffer.from(input.bytes).toString("base64"),
|
|
16911
|
+
isPublic: input.isPublic ?? true
|
|
17299
16912
|
}
|
|
17300
16913
|
});
|
|
17301
16914
|
return doc;
|
|
17302
16915
|
}
|
|
17303
16916
|
/**
|
|
17304
|
-
* Restore an archived pitch to `draft
|
|
17305
|
-
*
|
|
17306
|
-
*
|
|
17307
|
-
*
|
|
17308
|
-
* the unarchive path reuses the same token so subsequent
|
|
17309
|
-
* `draft → preview` moves don't require a re-mint).
|
|
17310
|
-
*
|
|
17311
|
-
* Added 2026-06-23 to address Finding #5 of
|
|
17312
|
-
* `docs-new/hp-cli-cycle-finds-2026-06-23.md`. The CLI's
|
|
17313
|
-
* `hp pitches transition <id> --to draft` command routes through
|
|
17314
|
-
* this method when the current lifecycle is `archived`.
|
|
16917
|
+
* Restore an archived pitch to `draft`. Same as `transition(id, {
|
|
16918
|
+
* to: "draft", previewToken })` but with a placeholder previewToken
|
|
16919
|
+
* if the caller didn't pass one. The server's "to=draft" path
|
|
16920
|
+
* mirrors the existing "to=preview" pre-condition.
|
|
17315
16921
|
*/
|
|
17316
16922
|
async unarchive(id, opts = {}) {
|
|
17317
16923
|
return this.transition(id, {
|
|
@@ -17328,25 +16934,16 @@ function createPitcherClient(config) {
|
|
|
17328
16934
|
pitches: new PitchesApi(resolved),
|
|
17329
16935
|
setJwt: (jwt, expiresAt) => resolved.setJwt(jwt, expiresAt),
|
|
17330
16936
|
getJwt: () => resolved.getJwt(),
|
|
17331
|
-
resolveCreatorId: async () => {
|
|
17332
|
-
const id = await findCreatorIdForJwtUser(resolved);
|
|
17333
|
-
if (!id) {
|
|
17334
|
-
throw new Error(
|
|
17335
|
-
"No creators row for this user \u2014 sign in via studio once so user-onboard runs"
|
|
17336
|
-
);
|
|
17337
|
-
}
|
|
17338
|
-
return id;
|
|
17339
|
-
},
|
|
17340
16937
|
findCreatorIdForJwtUser: () => findCreatorIdForJwtUser(resolved),
|
|
17341
16938
|
findCreatorIdForApiKey: () => findCreatorIdForApiKey(resolved)
|
|
17342
16939
|
};
|
|
17343
16940
|
}
|
|
17344
16941
|
|
|
17345
16942
|
// src/index.ts
|
|
17346
|
-
var import_pitch_core3 = __toESM(
|
|
16943
|
+
var import_pitch_core3 = __toESM(require_dist2(), 1);
|
|
17347
16944
|
|
|
17348
16945
|
// src/scaffold.ts
|
|
17349
|
-
var import_pitch_core2 = __toESM(
|
|
16946
|
+
var import_pitch_core2 = __toESM(require_dist2(), 1);
|
|
17350
16947
|
function scaffoldPitchFromFramework(input) {
|
|
17351
16948
|
if (!(0, import_pitch_core2.isFrameworkId)(input.framework)) {
|
|
17352
16949
|
throw new Error(`Unknown framework id: ${input.framework}`);
|
|
@@ -17367,22 +16964,34 @@ function scaffoldPitchFromFramework(input) {
|
|
|
17367
16964
|
ctaLabel: input.ctaLabel
|
|
17368
16965
|
};
|
|
17369
16966
|
}
|
|
16967
|
+
|
|
16968
|
+
// src/resolve-consolidated-route.ts
|
|
16969
|
+
var STUDIO_API_FUNCTION_ID = "honest-pitches-studio-api";
|
|
16970
|
+
var MEDIA_API_FUNCTION_ID = "honest-pitches-media";
|
|
16971
|
+
var FUNCTION_BUNDLE_MAP = {
|
|
16972
|
+
"pitch-write": STUDIO_API_FUNCTION_ID,
|
|
16973
|
+
"pitch-transition": STUDIO_API_FUNCTION_ID,
|
|
16974
|
+
"pitch-asset-upload": MEDIA_API_FUNCTION_ID,
|
|
16975
|
+
"agent-magic-link-issue": STUDIO_API_FUNCTION_ID
|
|
16976
|
+
};
|
|
16977
|
+
function resolveConsolidatedRoute(functionId, path) {
|
|
16978
|
+
const bundle = FUNCTION_BUNDLE_MAP[functionId];
|
|
16979
|
+
if (!bundle) return { functionId, path };
|
|
16980
|
+
const sub = path.startsWith("/") ? path : `/${path}`;
|
|
16981
|
+
const prefixed = sub === "/" ? `/${functionId}` : `/${functionId}${sub}`;
|
|
16982
|
+
return { functionId: bundle, path: prefixed };
|
|
16983
|
+
}
|
|
17370
16984
|
// Annotate the CommonJS export names for ESM import in node:
|
|
17371
16985
|
0 && (module.exports = {
|
|
17372
|
-
|
|
16986
|
+
DEFAULT_PITCHER_BASE_URL,
|
|
17373
16987
|
FrameworkLockedError,
|
|
17374
16988
|
HpCodeImmutableError,
|
|
17375
16989
|
InvalidSectionKindError,
|
|
17376
|
-
MEDIA_API_FUNCTION_ID,
|
|
17377
|
-
PUBLIC_API_FUNCTION_ID,
|
|
17378
16990
|
PitcherNotAuthenticatedError,
|
|
17379
16991
|
PitcherNotOwnedCreatorError,
|
|
16992
|
+
PitcherRequestError,
|
|
17380
16993
|
PitcherSdkError,
|
|
17381
16994
|
PitchesApi,
|
|
17382
|
-
STRIPE_API_FUNCTION_ID,
|
|
17383
|
-
STUDIO_API_FUNCTION_ID,
|
|
17384
|
-
appwriteQueryEqual,
|
|
17385
|
-
appwriteQueryLimit,
|
|
17386
16995
|
createPitcherClient,
|
|
17387
16996
|
decodeJwtSub,
|
|
17388
16997
|
findCreatorIdForApiKey,
|