@publishq/sdk 0.0.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/dist/index.js ADDED
@@ -0,0 +1,1947 @@
1
+ // src/generated/core/bodySerializer.gen.ts
2
+ var serializeFormDataPair = (data, key, value) => {
3
+ if (typeof value === "string" || value instanceof Blob) {
4
+ data.append(key, value);
5
+ } else if (value instanceof Date) {
6
+ data.append(key, value.toISOString());
7
+ } else {
8
+ data.append(key, JSON.stringify(value));
9
+ }
10
+ };
11
+ var formDataBodySerializer = {
12
+ bodySerializer: (body) => {
13
+ const data = new FormData();
14
+ Object.entries(body).forEach(([key, value]) => {
15
+ if (value === void 0 || value === null) {
16
+ return;
17
+ }
18
+ if (Array.isArray(value)) {
19
+ value.forEach((v) => serializeFormDataPair(data, key, v));
20
+ } else {
21
+ serializeFormDataPair(data, key, value);
22
+ }
23
+ });
24
+ return data;
25
+ }
26
+ };
27
+ var jsonBodySerializer = {
28
+ bodySerializer: (body) => JSON.stringify(body, (_key, value) => typeof value === "bigint" ? value.toString() : value)
29
+ };
30
+
31
+ // src/generated/core/params.gen.ts
32
+ var extraPrefixesMap = {
33
+ $body_: "body",
34
+ $headers_: "headers",
35
+ $path_: "path",
36
+ $query_: "query"
37
+ };
38
+ var extraPrefixes = Object.entries(extraPrefixesMap);
39
+
40
+ // src/generated/core/serverSentEvents.gen.ts
41
+ function createSseClient({
42
+ onRequest,
43
+ onSseError,
44
+ onSseEvent,
45
+ responseTransformer,
46
+ responseValidator,
47
+ sseDefaultRetryDelay,
48
+ sseMaxRetryAttempts,
49
+ sseMaxRetryDelay,
50
+ sseSleepFn,
51
+ url: url2,
52
+ ...options
53
+ }) {
54
+ let lastEventId;
55
+ const sleep = sseSleepFn ?? ((ms) => new Promise((resolve) => setTimeout(resolve, ms)));
56
+ const createStream = async function* () {
57
+ let retryDelay = sseDefaultRetryDelay ?? 3e3;
58
+ let attempt = 0;
59
+ const signal = options.signal ?? new AbortController().signal;
60
+ while (true) {
61
+ if (signal.aborted) break;
62
+ attempt++;
63
+ const headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers);
64
+ if (lastEventId !== void 0) {
65
+ headers.set("Last-Event-ID", lastEventId);
66
+ }
67
+ try {
68
+ const requestInit = {
69
+ redirect: "follow",
70
+ ...options,
71
+ body: options.serializedBody,
72
+ headers,
73
+ signal
74
+ };
75
+ let request = new Request(url2, requestInit);
76
+ if (onRequest) {
77
+ request = await onRequest(url2, requestInit);
78
+ }
79
+ const _fetch = options.fetch ?? globalThis.fetch;
80
+ const response = await _fetch(request);
81
+ if (!response.ok) throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
82
+ if (!response.body) throw new Error("No body in SSE response");
83
+ const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
84
+ let buffer = "";
85
+ const abortHandler = () => {
86
+ try {
87
+ reader.cancel();
88
+ } catch {
89
+ }
90
+ };
91
+ signal.addEventListener("abort", abortHandler);
92
+ try {
93
+ while (true) {
94
+ const { done, value } = await reader.read();
95
+ if (done) break;
96
+ buffer += value;
97
+ buffer = buffer.replace(/\r\n?/g, "\n");
98
+ const chunks = buffer.split("\n\n");
99
+ buffer = chunks.pop() ?? "";
100
+ for (const chunk of chunks) {
101
+ const lines = chunk.split("\n");
102
+ const dataLines = [];
103
+ let eventName;
104
+ for (const line of lines) {
105
+ if (line.startsWith("data:")) {
106
+ dataLines.push(line.replace(/^data:\s*/, ""));
107
+ } else if (line.startsWith("event:")) {
108
+ eventName = line.replace(/^event:\s*/, "");
109
+ } else if (line.startsWith("id:")) {
110
+ lastEventId = line.replace(/^id:\s*/, "");
111
+ } else if (line.startsWith("retry:")) {
112
+ const parsed = Number.parseInt(line.replace(/^retry:\s*/, ""), 10);
113
+ if (!Number.isNaN(parsed)) {
114
+ retryDelay = parsed;
115
+ }
116
+ }
117
+ }
118
+ let data;
119
+ let parsedJson = false;
120
+ if (dataLines.length) {
121
+ const rawData = dataLines.join("\n");
122
+ try {
123
+ data = JSON.parse(rawData);
124
+ parsedJson = true;
125
+ } catch {
126
+ data = rawData;
127
+ }
128
+ }
129
+ if (parsedJson) {
130
+ if (responseValidator) {
131
+ await responseValidator(data);
132
+ }
133
+ if (responseTransformer) {
134
+ data = await responseTransformer(data);
135
+ }
136
+ }
137
+ onSseEvent?.({
138
+ data,
139
+ event: eventName,
140
+ id: lastEventId,
141
+ retry: retryDelay
142
+ });
143
+ if (dataLines.length) {
144
+ yield data;
145
+ }
146
+ }
147
+ }
148
+ } finally {
149
+ signal.removeEventListener("abort", abortHandler);
150
+ reader.releaseLock();
151
+ }
152
+ break;
153
+ } catch (error) {
154
+ onSseError?.(error);
155
+ if (sseMaxRetryAttempts !== void 0 && attempt >= sseMaxRetryAttempts) {
156
+ break;
157
+ }
158
+ const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 3e4);
159
+ await sleep(backoff);
160
+ }
161
+ }
162
+ };
163
+ const stream = createStream();
164
+ return { stream };
165
+ }
166
+
167
+ // src/generated/core/pathSerializer.gen.ts
168
+ var separatorArrayExplode = (style) => {
169
+ switch (style) {
170
+ case "label":
171
+ return ".";
172
+ case "matrix":
173
+ return ";";
174
+ case "simple":
175
+ return ",";
176
+ default:
177
+ return "&";
178
+ }
179
+ };
180
+ var separatorArrayNoExplode = (style) => {
181
+ switch (style) {
182
+ case "form":
183
+ return ",";
184
+ case "pipeDelimited":
185
+ return "|";
186
+ case "spaceDelimited":
187
+ return "%20";
188
+ default:
189
+ return ",";
190
+ }
191
+ };
192
+ var separatorObjectExplode = (style) => {
193
+ switch (style) {
194
+ case "label":
195
+ return ".";
196
+ case "matrix":
197
+ return ";";
198
+ case "simple":
199
+ return ",";
200
+ default:
201
+ return "&";
202
+ }
203
+ };
204
+ var serializeArrayParam = ({
205
+ allowReserved,
206
+ explode,
207
+ name,
208
+ style,
209
+ value
210
+ }) => {
211
+ if (!explode) {
212
+ const joinedValues2 = (allowReserved ? value : value.map((v) => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
213
+ switch (style) {
214
+ case "label":
215
+ return `.${joinedValues2}`;
216
+ case "matrix":
217
+ return `;${name}=${joinedValues2}`;
218
+ case "simple":
219
+ return joinedValues2;
220
+ default:
221
+ return `${name}=${joinedValues2}`;
222
+ }
223
+ }
224
+ const separator = separatorArrayExplode(style);
225
+ const joinedValues = value.map((v) => {
226
+ if (style === "label" || style === "simple") {
227
+ return allowReserved ? v : encodeURIComponent(v);
228
+ }
229
+ return serializePrimitiveParam({
230
+ allowReserved,
231
+ name,
232
+ value: v
233
+ });
234
+ }).join(separator);
235
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
236
+ };
237
+ var serializePrimitiveParam = ({
238
+ allowReserved,
239
+ name,
240
+ value
241
+ }) => {
242
+ if (value === void 0 || value === null) {
243
+ return "";
244
+ }
245
+ if (typeof value === "object") {
246
+ throw new Error(
247
+ "Deeply-nested arrays/objects aren\u2019t supported. Provide your own `querySerializer()` to handle these."
248
+ );
249
+ }
250
+ return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
251
+ };
252
+ var serializeObjectParam = ({
253
+ allowReserved,
254
+ explode,
255
+ name,
256
+ style,
257
+ value,
258
+ valueOnly
259
+ }) => {
260
+ if (value instanceof Date) {
261
+ return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
262
+ }
263
+ if (style !== "deepObject" && !explode) {
264
+ let values = [];
265
+ Object.entries(value).forEach(([key, v]) => {
266
+ values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
267
+ });
268
+ const joinedValues2 = values.join(",");
269
+ switch (style) {
270
+ case "form":
271
+ return `${name}=${joinedValues2}`;
272
+ case "label":
273
+ return `.${joinedValues2}`;
274
+ case "matrix":
275
+ return `;${name}=${joinedValues2}`;
276
+ default:
277
+ return joinedValues2;
278
+ }
279
+ }
280
+ const separator = separatorObjectExplode(style);
281
+ const joinedValues = Object.entries(value).map(
282
+ ([key, v]) => serializePrimitiveParam({
283
+ allowReserved,
284
+ name: style === "deepObject" ? `${name}[${key}]` : key,
285
+ value: v
286
+ })
287
+ ).join(separator);
288
+ return style === "label" || style === "matrix" ? separator + joinedValues : joinedValues;
289
+ };
290
+
291
+ // src/generated/core/utils.gen.ts
292
+ var PATH_PARAM_RE = /\{[^{}]+\}/g;
293
+ var defaultPathSerializer = ({ path, url: _url }) => {
294
+ let url2 = _url;
295
+ const matches = _url.match(PATH_PARAM_RE);
296
+ if (matches) {
297
+ for (const match of matches) {
298
+ let explode = false;
299
+ let name = match.substring(1, match.length - 1);
300
+ let style = "simple";
301
+ if (name.endsWith("*")) {
302
+ explode = true;
303
+ name = name.substring(0, name.length - 1);
304
+ }
305
+ if (name.startsWith(".")) {
306
+ name = name.substring(1);
307
+ style = "label";
308
+ } else if (name.startsWith(";")) {
309
+ name = name.substring(1);
310
+ style = "matrix";
311
+ }
312
+ const value = path[name];
313
+ if (value === void 0 || value === null) {
314
+ continue;
315
+ }
316
+ if (Array.isArray(value)) {
317
+ url2 = url2.replace(match, serializeArrayParam({ explode, name, style, value }));
318
+ continue;
319
+ }
320
+ if (typeof value === "object") {
321
+ url2 = url2.replace(
322
+ match,
323
+ serializeObjectParam({
324
+ explode,
325
+ name,
326
+ style,
327
+ value,
328
+ valueOnly: true
329
+ })
330
+ );
331
+ continue;
332
+ }
333
+ if (style === "matrix") {
334
+ url2 = url2.replace(
335
+ match,
336
+ `;${serializePrimitiveParam({
337
+ name,
338
+ value
339
+ })}`
340
+ );
341
+ continue;
342
+ }
343
+ const replaceValue = encodeURIComponent(
344
+ style === "label" ? `.${value}` : value
345
+ );
346
+ url2 = url2.replace(match, replaceValue);
347
+ }
348
+ }
349
+ return url2;
350
+ };
351
+ var getUrl = ({
352
+ baseUrl,
353
+ path,
354
+ query,
355
+ querySerializer,
356
+ url: _url
357
+ }) => {
358
+ const pathUrl = _url.startsWith("/") ? _url : `/${_url}`;
359
+ let url2 = (baseUrl ?? "") + pathUrl;
360
+ if (path) {
361
+ url2 = defaultPathSerializer({ path, url: url2 });
362
+ }
363
+ let search = query ? querySerializer(query) : "";
364
+ if (search.startsWith("?")) {
365
+ search = search.substring(1);
366
+ }
367
+ if (search) {
368
+ url2 += `?${search}`;
369
+ }
370
+ return url2;
371
+ };
372
+ function getValidRequestBody(options) {
373
+ const hasBody = options.body !== void 0;
374
+ const isSerializedBody = hasBody && options.bodySerializer;
375
+ if (isSerializedBody) {
376
+ if ("serializedBody" in options) {
377
+ const hasSerializedBody = options.serializedBody !== void 0 && options.serializedBody !== "";
378
+ return hasSerializedBody ? options.serializedBody : null;
379
+ }
380
+ return options.body !== "" ? options.body : null;
381
+ }
382
+ if (hasBody) {
383
+ return options.body;
384
+ }
385
+ return void 0;
386
+ }
387
+
388
+ // src/generated/core/auth.gen.ts
389
+ var getAuthToken = async (auth, callback) => {
390
+ const token = typeof callback === "function" ? await callback(auth) : callback;
391
+ if (!token) {
392
+ return;
393
+ }
394
+ if (auth.scheme === "bearer") {
395
+ return `Bearer ${token}`;
396
+ }
397
+ if (auth.scheme === "basic") {
398
+ return `Basic ${btoa(token)}`;
399
+ }
400
+ return token;
401
+ };
402
+
403
+ // src/generated/client/utils.gen.ts
404
+ var createQuerySerializer = ({
405
+ parameters = {},
406
+ ...args
407
+ } = {}) => {
408
+ const querySerializer = (queryParams) => {
409
+ const search = [];
410
+ if (queryParams && typeof queryParams === "object") {
411
+ for (const name in queryParams) {
412
+ const value = queryParams[name];
413
+ if (value === void 0 || value === null) {
414
+ continue;
415
+ }
416
+ const options = parameters[name] || args;
417
+ if (Array.isArray(value)) {
418
+ const serializedArray = serializeArrayParam({
419
+ allowReserved: options.allowReserved,
420
+ explode: true,
421
+ name,
422
+ style: "form",
423
+ value,
424
+ ...options.array
425
+ });
426
+ if (serializedArray) search.push(serializedArray);
427
+ } else if (typeof value === "object") {
428
+ const serializedObject = serializeObjectParam({
429
+ allowReserved: options.allowReserved,
430
+ explode: true,
431
+ name,
432
+ style: "deepObject",
433
+ value,
434
+ ...options.object
435
+ });
436
+ if (serializedObject) search.push(serializedObject);
437
+ } else {
438
+ const serializedPrimitive = serializePrimitiveParam({
439
+ allowReserved: options.allowReserved,
440
+ name,
441
+ value
442
+ });
443
+ if (serializedPrimitive) search.push(serializedPrimitive);
444
+ }
445
+ }
446
+ }
447
+ return search.join("&");
448
+ };
449
+ return querySerializer;
450
+ };
451
+ var getParseAs = (contentType) => {
452
+ if (!contentType) {
453
+ return "stream";
454
+ }
455
+ const cleanContent = contentType.split(";")[0]?.trim();
456
+ if (!cleanContent) {
457
+ return;
458
+ }
459
+ if (cleanContent.startsWith("application/json") || cleanContent.endsWith("+json")) {
460
+ return "json";
461
+ }
462
+ if (cleanContent === "multipart/form-data") {
463
+ return "formData";
464
+ }
465
+ if (["application/", "audio/", "image/", "video/"].some((type) => cleanContent.startsWith(type))) {
466
+ return "blob";
467
+ }
468
+ if (cleanContent.startsWith("text/")) {
469
+ return "text";
470
+ }
471
+ return;
472
+ };
473
+ var checkForExistence = (options, name) => {
474
+ if (!name) {
475
+ return false;
476
+ }
477
+ if (options.headers.has(name) || options.query?.[name] || options.headers.get("Cookie")?.includes(`${name}=`)) {
478
+ return true;
479
+ }
480
+ return false;
481
+ };
482
+ async function setAuthParams(options) {
483
+ for (const auth of options.security ?? []) {
484
+ if (checkForExistence(options, auth.name)) {
485
+ continue;
486
+ }
487
+ const token = await getAuthToken(auth, options.auth);
488
+ if (!token) {
489
+ continue;
490
+ }
491
+ const name = auth.name ?? "Authorization";
492
+ switch (auth.in) {
493
+ case "query":
494
+ if (!options.query) {
495
+ options.query = {};
496
+ }
497
+ options.query[name] = token;
498
+ break;
499
+ case "cookie":
500
+ options.headers.append("Cookie", `${name}=${token}`);
501
+ break;
502
+ case "header":
503
+ default:
504
+ options.headers.set(name, token);
505
+ break;
506
+ }
507
+ }
508
+ }
509
+ var buildUrl = (options) => getUrl({
510
+ baseUrl: options.baseUrl,
511
+ path: options.path,
512
+ query: options.query,
513
+ querySerializer: typeof options.querySerializer === "function" ? options.querySerializer : createQuerySerializer(options.querySerializer),
514
+ url: options.url
515
+ });
516
+ var mergeConfigs = (a, b) => {
517
+ const config = { ...a, ...b };
518
+ if (config.baseUrl?.endsWith("/")) {
519
+ config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
520
+ }
521
+ config.headers = mergeHeaders(a.headers, b.headers);
522
+ return config;
523
+ };
524
+ var headersEntries = (headers) => {
525
+ const entries = [];
526
+ headers.forEach((value, key) => {
527
+ entries.push([key, value]);
528
+ });
529
+ return entries;
530
+ };
531
+ var mergeHeaders = (...headers) => {
532
+ const mergedHeaders = new Headers();
533
+ for (const header of headers) {
534
+ if (!header) {
535
+ continue;
536
+ }
537
+ const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
538
+ for (const [key, value] of iterator) {
539
+ if (value === null) {
540
+ mergedHeaders.delete(key);
541
+ } else if (Array.isArray(value)) {
542
+ for (const v of value) {
543
+ mergedHeaders.append(key, v);
544
+ }
545
+ } else if (value !== void 0) {
546
+ mergedHeaders.set(
547
+ key,
548
+ typeof value === "object" ? JSON.stringify(value) : value
549
+ );
550
+ }
551
+ }
552
+ }
553
+ return mergedHeaders;
554
+ };
555
+ var Interceptors = class {
556
+ fns = [];
557
+ clear() {
558
+ this.fns = [];
559
+ }
560
+ eject(id) {
561
+ const index = this.getInterceptorIndex(id);
562
+ if (this.fns[index]) {
563
+ this.fns[index] = null;
564
+ }
565
+ }
566
+ exists(id) {
567
+ const index = this.getInterceptorIndex(id);
568
+ return Boolean(this.fns[index]);
569
+ }
570
+ getInterceptorIndex(id) {
571
+ if (typeof id === "number") {
572
+ return this.fns[id] ? id : -1;
573
+ }
574
+ return this.fns.indexOf(id);
575
+ }
576
+ update(id, fn) {
577
+ const index = this.getInterceptorIndex(id);
578
+ if (this.fns[index]) {
579
+ this.fns[index] = fn;
580
+ return id;
581
+ }
582
+ return false;
583
+ }
584
+ use(fn) {
585
+ this.fns.push(fn);
586
+ return this.fns.length - 1;
587
+ }
588
+ };
589
+ var createInterceptors = () => ({
590
+ error: new Interceptors(),
591
+ request: new Interceptors(),
592
+ response: new Interceptors()
593
+ });
594
+ var defaultQuerySerializer = createQuerySerializer({
595
+ allowReserved: false,
596
+ array: {
597
+ explode: true,
598
+ style: "form"
599
+ },
600
+ object: {
601
+ explode: true,
602
+ style: "deepObject"
603
+ }
604
+ });
605
+ var defaultHeaders = {
606
+ "Content-Type": "application/json"
607
+ };
608
+ var createConfig = (override = {}) => ({
609
+ ...jsonBodySerializer,
610
+ headers: defaultHeaders,
611
+ parseAs: "auto",
612
+ querySerializer: defaultQuerySerializer,
613
+ ...override
614
+ });
615
+
616
+ // src/generated/client/client.gen.ts
617
+ var createClient = (config = {}) => {
618
+ let _config = mergeConfigs(createConfig(), config);
619
+ const getConfig = () => ({ ..._config });
620
+ const setConfig = (config2) => {
621
+ _config = mergeConfigs(_config, config2);
622
+ return getConfig();
623
+ };
624
+ const interceptors = createInterceptors();
625
+ const beforeRequest = async (options) => {
626
+ const opts = {
627
+ ..._config,
628
+ ...options,
629
+ fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
630
+ headers: mergeHeaders(_config.headers, options.headers),
631
+ serializedBody: void 0
632
+ };
633
+ if (opts.security) {
634
+ await setAuthParams(opts);
635
+ }
636
+ if (opts.requestValidator) {
637
+ await opts.requestValidator(opts);
638
+ }
639
+ if (opts.body !== void 0 && opts.bodySerializer) {
640
+ opts.serializedBody = opts.bodySerializer(opts.body);
641
+ }
642
+ if (opts.body === void 0 || opts.serializedBody === "") {
643
+ opts.headers.delete("Content-Type");
644
+ }
645
+ const resolvedOpts = opts;
646
+ const url2 = buildUrl(resolvedOpts);
647
+ return { opts: resolvedOpts, url: url2 };
648
+ };
649
+ const request = async (options) => {
650
+ const throwOnError = options.throwOnError ?? _config.throwOnError;
651
+ const responseStyle = options.responseStyle ?? _config.responseStyle;
652
+ let request2;
653
+ let response;
654
+ try {
655
+ const { opts, url: url2 } = await beforeRequest(options);
656
+ const requestInit = {
657
+ redirect: "follow",
658
+ ...opts,
659
+ body: getValidRequestBody(opts)
660
+ };
661
+ request2 = new Request(url2, requestInit);
662
+ for (const fn of interceptors.request.fns) {
663
+ if (fn) {
664
+ request2 = await fn(request2, opts);
665
+ }
666
+ }
667
+ const _fetch = opts.fetch;
668
+ response = await _fetch(request2);
669
+ for (const fn of interceptors.response.fns) {
670
+ if (fn) {
671
+ response = await fn(response, request2, opts);
672
+ }
673
+ }
674
+ const result = {
675
+ request: request2,
676
+ response
677
+ };
678
+ if (response.ok) {
679
+ const parseAs = (opts.parseAs === "auto" ? getParseAs(response.headers.get("Content-Type")) : opts.parseAs) ?? "json";
680
+ if (response.status === 204 || response.headers.get("Content-Length") === "0") {
681
+ let emptyData;
682
+ switch (parseAs) {
683
+ case "arrayBuffer":
684
+ case "blob":
685
+ case "text":
686
+ emptyData = await response[parseAs]();
687
+ break;
688
+ case "formData":
689
+ emptyData = new FormData();
690
+ break;
691
+ case "stream":
692
+ emptyData = response.body;
693
+ break;
694
+ case "json":
695
+ default:
696
+ emptyData = {};
697
+ break;
698
+ }
699
+ return opts.responseStyle === "data" ? emptyData : {
700
+ data: emptyData,
701
+ ...result
702
+ };
703
+ }
704
+ let data;
705
+ switch (parseAs) {
706
+ case "arrayBuffer":
707
+ case "blob":
708
+ case "formData":
709
+ case "text":
710
+ data = await response[parseAs]();
711
+ break;
712
+ case "json": {
713
+ const text = await response.text();
714
+ data = text ? JSON.parse(text) : {};
715
+ break;
716
+ }
717
+ case "stream":
718
+ return opts.responseStyle === "data" ? response.body : {
719
+ data: response.body,
720
+ ...result
721
+ };
722
+ }
723
+ if (parseAs === "json") {
724
+ if (opts.responseValidator) {
725
+ await opts.responseValidator(data);
726
+ }
727
+ if (opts.responseTransformer) {
728
+ data = await opts.responseTransformer(data);
729
+ }
730
+ }
731
+ return opts.responseStyle === "data" ? data : {
732
+ data,
733
+ ...result
734
+ };
735
+ }
736
+ const textError = await response.text();
737
+ let jsonError;
738
+ try {
739
+ jsonError = JSON.parse(textError);
740
+ } catch {
741
+ }
742
+ throw jsonError ?? textError;
743
+ } catch (error) {
744
+ let finalError = error;
745
+ for (const fn of interceptors.error.fns) {
746
+ if (fn) {
747
+ finalError = await fn(finalError, response, request2, options);
748
+ }
749
+ }
750
+ finalError = finalError || {};
751
+ if (throwOnError) {
752
+ throw finalError;
753
+ }
754
+ return responseStyle === "data" ? void 0 : {
755
+ error: finalError,
756
+ request: request2,
757
+ response
758
+ };
759
+ }
760
+ };
761
+ const makeMethodFn = (method) => (options) => request({ ...options, method });
762
+ const makeSseFn = (method) => async (options) => {
763
+ const { opts, url: url2 } = await beforeRequest(options);
764
+ return createSseClient({
765
+ ...opts,
766
+ body: opts.body,
767
+ method,
768
+ onRequest: async (url3, init) => {
769
+ let request2 = new Request(url3, init);
770
+ for (const fn of interceptors.request.fns) {
771
+ if (fn) {
772
+ request2 = await fn(request2, opts);
773
+ }
774
+ }
775
+ return request2;
776
+ },
777
+ serializedBody: getValidRequestBody(opts),
778
+ url: url2
779
+ });
780
+ };
781
+ const _buildUrl = (options) => buildUrl({ ..._config, ...options });
782
+ return {
783
+ buildUrl: _buildUrl,
784
+ connect: makeMethodFn("CONNECT"),
785
+ delete: makeMethodFn("DELETE"),
786
+ get: makeMethodFn("GET"),
787
+ getConfig,
788
+ head: makeMethodFn("HEAD"),
789
+ interceptors,
790
+ options: makeMethodFn("OPTIONS"),
791
+ patch: makeMethodFn("PATCH"),
792
+ post: makeMethodFn("POST"),
793
+ put: makeMethodFn("PUT"),
794
+ request,
795
+ setConfig,
796
+ sse: {
797
+ connect: makeSseFn("CONNECT"),
798
+ delete: makeSseFn("DELETE"),
799
+ get: makeSseFn("GET"),
800
+ head: makeSseFn("HEAD"),
801
+ options: makeSseFn("OPTIONS"),
802
+ patch: makeSseFn("PATCH"),
803
+ post: makeSseFn("POST"),
804
+ put: makeSseFn("PUT"),
805
+ trace: makeSseFn("TRACE")
806
+ },
807
+ trace: makeMethodFn("TRACE")
808
+ };
809
+ };
810
+
811
+ // src/generated/client.gen.ts
812
+ var client = createClient(createConfig({ baseUrl: "https://publishq.com/api/v1" }));
813
+
814
+ // src/generated/sdk.gen.ts
815
+ var Posts = class {
816
+ /**
817
+ * List posts
818
+ *
819
+ * Returns a paginated list of posts.
820
+ */
821
+ static listPosts(options) {
822
+ return (options?.client ?? client).get({
823
+ security: [{ scheme: "bearer", type: "http" }],
824
+ url: "/posts",
825
+ ...options
826
+ });
827
+ }
828
+ /**
829
+ * Create posts
830
+ *
831
+ * Creates a post for one or more connected accounts.
832
+ */
833
+ static createPost(options) {
834
+ return (options.client ?? client).post({
835
+ security: [{ scheme: "bearer", type: "http" }],
836
+ url: "/posts",
837
+ ...options,
838
+ headers: {
839
+ "Content-Type": "application/json",
840
+ ...options.headers
841
+ }
842
+ });
843
+ }
844
+ /**
845
+ * Delete post
846
+ *
847
+ * Deletes a scheduled or draft post by its ID. Returns no body on success.
848
+ */
849
+ static deletePost(options) {
850
+ return (options.client ?? client).delete({
851
+ security: [{ scheme: "bearer", type: "http" }],
852
+ url: "/posts/{id}",
853
+ ...options
854
+ });
855
+ }
856
+ /**
857
+ * Get post
858
+ *
859
+ * Get one post by its PublishQ post ID. Returns the post details and the connected account metadata needed to identify where it belongs.
860
+ */
861
+ static getPost(options) {
862
+ return (options.client ?? client).get({
863
+ security: [{ scheme: "bearer", type: "http" }],
864
+ url: "/posts/{id}",
865
+ ...options
866
+ });
867
+ }
868
+ /**
869
+ * Update post
870
+ *
871
+ * Update a draft or scheduled post. You can change the content, the scheduled date, or both. Published and publishing posts cannot be updated.
872
+ */
873
+ static updatePost(options) {
874
+ return (options.client ?? client).patch({
875
+ security: [{ scheme: "bearer", type: "http" }],
876
+ url: "/posts/{id}",
877
+ ...options,
878
+ headers: {
879
+ "Content-Type": "application/json",
880
+ ...options.headers
881
+ }
882
+ });
883
+ }
884
+ /**
885
+ * Remove account from post
886
+ *
887
+ * Removes one account from an existing post so it will no longer be published there. Other accounts in the same post are not changed.
888
+ */
889
+ static removePostAccount(options) {
890
+ return (options.client ?? client).delete({
891
+ security: [{ scheme: "bearer", type: "http" }],
892
+ url: "/posts/{id}/accounts/{accountId}",
893
+ ...options
894
+ });
895
+ }
896
+ };
897
+ var Accounts = class {
898
+ /**
899
+ * List accounts
900
+ *
901
+ * List connected social accounts for the authenticated API key owner. You can filter by workspace and by one or more platforms.
902
+ */
903
+ static listAccounts(options) {
904
+ return (options?.client ?? client).get({
905
+ security: [{ scheme: "bearer", type: "http" }],
906
+ url: "/accounts",
907
+ ...options
908
+ });
909
+ }
910
+ /**
911
+ * Get TikTok creator info
912
+ *
913
+ * Returns the TikTok creator's current privacy options, interaction settings, and maximum video duration. Call this before posting to TikTok — the `privacyLevel` you set must match one of the returned `privacyLevelOptions`.
914
+ */
915
+ static getTikTokCreatorInfo(options) {
916
+ return (options.client ?? client).get({
917
+ security: [{ scheme: "bearer", type: "http" }],
918
+ url: "/accounts/{id}/tiktok-creator-info",
919
+ ...options
920
+ });
921
+ }
922
+ };
923
+ var Workspaces = class {
924
+ /**
925
+ * List workspaces
926
+ *
927
+ * Return your workspaces, including their names, colors, and account counts.
928
+ */
929
+ static listWorkspaces(options) {
930
+ return (options?.client ?? client).get({
931
+ security: [{ scheme: "bearer", type: "http" }],
932
+ url: "/workspaces",
933
+ ...options
934
+ });
935
+ }
936
+ /**
937
+ * Create workspace
938
+ *
939
+ * Create a workspace to organize your connected social accounts.
940
+ */
941
+ static createWorkspace(options) {
942
+ return (options.client ?? client).post({
943
+ security: [{ scheme: "bearer", type: "http" }],
944
+ url: "/workspaces",
945
+ ...options,
946
+ headers: {
947
+ "Content-Type": "application/json",
948
+ ...options.headers
949
+ }
950
+ });
951
+ }
952
+ /**
953
+ * Get workspace
954
+ *
955
+ * Return one workspace by ID, including its name, color, description, and account count.
956
+ */
957
+ static getWorkspace(options) {
958
+ return (options.client ?? client).get({
959
+ security: [{ scheme: "bearer", type: "http" }],
960
+ url: "/workspaces/{id}",
961
+ ...options
962
+ });
963
+ }
964
+ };
965
+ var Media = class {
966
+ /**
967
+ * List media
968
+ *
969
+ * Return your uploaded and generated media files. You can filter by ID, type, and source before reusing them in posts.
970
+ */
971
+ static listMedia(options) {
972
+ return (options?.client ?? client).get({
973
+ security: [{ scheme: "bearer", type: "http" }],
974
+ url: "/media",
975
+ ...options
976
+ });
977
+ }
978
+ /**
979
+ * Upload media
980
+ *
981
+ * Upload one media file with multipart form data. The returned media ID can then be attached to posts.
982
+ */
983
+ static uploadMedia(options) {
984
+ return (options.client ?? client).post({
985
+ ...formDataBodySerializer,
986
+ security: [{ scheme: "bearer", type: "http" }],
987
+ url: "/media",
988
+ ...options,
989
+ headers: {
990
+ "Content-Type": null,
991
+ ...options.headers
992
+ }
993
+ });
994
+ }
995
+ /**
996
+ * Get media
997
+ *
998
+ * Return one media file by ID, including its URL, source, and usage count.
999
+ */
1000
+ static getMedia(options) {
1001
+ return (options.client ?? client).get({
1002
+ security: [{ scheme: "bearer", type: "http" }],
1003
+ url: "/media/{id}",
1004
+ ...options
1005
+ });
1006
+ }
1007
+ };
1008
+
1009
+ // src/generated/zod.gen.ts
1010
+ import * as z from "zod/mini";
1011
+ var zApiErrorCode = z.enum([
1012
+ "missing_auth",
1013
+ "invalid_auth_format",
1014
+ "invalid_api_key",
1015
+ "api_key_expired",
1016
+ "insufficient_scope",
1017
+ "validation_failed",
1018
+ "route_not_found",
1019
+ "internal_server_error",
1020
+ "rate_limit_exceeded",
1021
+ "post_not_found",
1022
+ "post_forbidden",
1023
+ "post_not_editable",
1024
+ "media_not_found",
1025
+ "media_in_use",
1026
+ "storage_limit_exceeded",
1027
+ "free_media_limit_exceeded",
1028
+ "free_pending_media_limit_exceeded",
1029
+ "file_required",
1030
+ "file_too_large",
1031
+ "unsupported_file_type",
1032
+ "unsupported_media_type",
1033
+ "invalid_file_extension",
1034
+ "social_accounts_not_found",
1035
+ "social_accounts_expired",
1036
+ "platform_validation_failed",
1037
+ "posting_limits_exceeded",
1038
+ "scheduled_at_required",
1039
+ "invalid_scheduled_at",
1040
+ "scheduled_at_too_soon",
1041
+ "reschedulable_posts_not_found",
1042
+ "workspace_not_found",
1043
+ "workspace_forbidden",
1044
+ "workspace_owner_required",
1045
+ "workspace_account_not_found",
1046
+ "workspace_account_conflict",
1047
+ "workspace_member_not_found",
1048
+ "workspace_member_conflict",
1049
+ "workspace_invitation_invalid",
1050
+ "workspace_invitation_expired"
1051
+ ]);
1052
+ var zApiError = z.object({
1053
+ error: z.object({
1054
+ title: z.string(),
1055
+ status: z.int(),
1056
+ code: zApiErrorCode,
1057
+ message: z.string(),
1058
+ instance: z.optional(z.string()),
1059
+ details: z.optional(z.record(z.string(), z.record(z.string(), z.unknown())))
1060
+ })
1061
+ });
1062
+ var zPagination = z.object({
1063
+ page: z.int().register(z.globalRegistry, {
1064
+ description: "Current page number (starting from 1)."
1065
+ }),
1066
+ limit: z.int().register(z.globalRegistry, {
1067
+ description: "Maximum number of items returned per page."
1068
+ }),
1069
+ total: z.int().register(z.globalRegistry, {
1070
+ description: "Total number of matching items."
1071
+ }),
1072
+ totalPages: z.int().register(z.globalRegistry, {
1073
+ description: "Total number of pages for the current limit."
1074
+ }),
1075
+ hasNext: z.boolean().register(z.globalRegistry, {
1076
+ description: "Whether another page exists after the current one."
1077
+ }),
1078
+ hasPrev: z.boolean().register(z.globalRegistry, {
1079
+ description: "Whether another page exists before the current one."
1080
+ })
1081
+ });
1082
+ var zBlueskyPlatformSpecificSettings = z.record(z.string(), z.never()).register(z.globalRegistry, {
1083
+ description: "Bluesky-specific publishing settings. No settings are currently available."
1084
+ });
1085
+ var zInstagramPlatformSpecificSettings = z.object({
1086
+ contentType: z.optional(z.enum(["story", "reels"]).register(z.globalRegistry, {
1087
+ description: 'Set to "story" for ephemeral content that disappears after 24 hours. Set to "reels" to explicitly publish as a Reel. Omit for a regular feed post or carousel \u2014 single videos are automatically published as Reels.'
1088
+ })),
1089
+ shareToFeed: z.optional(z.boolean().register(z.globalRegistry, {
1090
+ description: "Reels only. When true (default), the reel can appear in both the Feed and Reels tabs. When false, it only appears in the Reels tab. Neither value guarantees placement \u2014 Instagram's algorithm decides based on eligibility and relevance."
1091
+ })),
1092
+ trialParams: z.optional(z.object({
1093
+ graduationStrategy: z.enum(["MANUAL", "SS_PERFORMANCE"]).register(z.globalRegistry, {
1094
+ description: "MANUAL: the trial reel can be graduated (converted to a public reel) manually in the Instagram app. SS_PERFORMANCE: Instagram automatically graduates the reel if it performs well with non-followers."
1095
+ })
1096
+ }).register(z.globalRegistry, {
1097
+ description: "Reels only. Publish as a trial reel \u2014 shown only to non-followers first. Instagram requires a public account with at least 200 followers and rejects the post otherwise."
1098
+ })),
1099
+ audioName: z.optional(z.string().register(z.globalRegistry, {
1100
+ description: "Reels only. Custom name for the audio track of your reel. Can only be set once \u2014 either at creation time or later from the audio page in the Instagram app."
1101
+ }))
1102
+ }).register(z.globalRegistry, {
1103
+ description: "Instagram-specific post settings. All fields are optional \u2014 omit the entire object for a regular feed post or carousel."
1104
+ });
1105
+ var zFacebookPlatformSpecificSettings = z.object({
1106
+ contentType: z.optional(z.enum(["story"]).register(z.globalRegistry, {
1107
+ description: 'Set to "story" for ephemeral content that disappears after 24 hours. Omit for a regular post \u2014 single videos are automatically published as Reels (Facebook no longer has a separate video format).'
1108
+ }))
1109
+ }).register(z.globalRegistry, {
1110
+ description: "Facebook-specific post settings. All fields are optional \u2014 omit the entire object for a regular post."
1111
+ });
1112
+ var zInstagramTrialParams = z.object({
1113
+ graduationStrategy: z.enum(["MANUAL", "SS_PERFORMANCE"]).register(z.globalRegistry, {
1114
+ description: "MANUAL: the trial reel can be graduated (converted to a public reel) manually in the Instagram app. SS_PERFORMANCE: Instagram automatically graduates the reel if it performs well with non-followers."
1115
+ })
1116
+ }).register(z.globalRegistry, {
1117
+ description: "Trial reel graduation settings. Trial reels are shown only to non-followers first. If the reel performs well (SS_PERFORMANCE) or you manually approve it (MANUAL), it gets promoted to a regular reel visible to followers."
1118
+ });
1119
+ var zYouTubePlatformSpecificSettings = z.object({
1120
+ description: z.optional(z.string().check(z.maxLength(5e3)).register(z.globalRegistry, {
1121
+ description: "Video description. Max 5000 characters. Shown below the video title on the watch page."
1122
+ })),
1123
+ privacyStatus: z.optional(z.enum([
1124
+ "public",
1125
+ "unlisted",
1126
+ "private"
1127
+ ]).register(z.globalRegistry, {
1128
+ description: "Video privacy status. Defaults to public. Unverified API projects are restricted to private."
1129
+ })),
1130
+ madeForKids: z.optional(z.boolean().register(z.globalRegistry, {
1131
+ description: "Declare the video as made for kids (COPPA). When true, personalized ads are disabled and some features (comments, notifications) are turned off."
1132
+ })),
1133
+ containsSyntheticMedia: z.optional(z.boolean().register(z.globalRegistry, {
1134
+ description: "Disclose that the video contains realistic altered or synthetic (AI-generated) content."
1135
+ })),
1136
+ categoryId: z.optional(z.enum([
1137
+ "1",
1138
+ "2",
1139
+ "10",
1140
+ "15",
1141
+ "17",
1142
+ "19",
1143
+ "20",
1144
+ "22",
1145
+ "23",
1146
+ "24",
1147
+ "25",
1148
+ "26",
1149
+ "27",
1150
+ "28",
1151
+ "29"
1152
+ ]).register(z.globalRegistry, {
1153
+ description: 'YouTube video category. Defaults to "22" (People & Blogs). Valid IDs: 1 (Film & Animation), 2 (Autos & Vehicles), 10 (Music), 15 (Pets & Animals), 17 (Sports), 19 (Travel & Events), 20 (Gaming), 22 (People & Blogs), 23 (Comedy), 24 (Entertainment), 25 (News & Politics), 26 (Howto & Style), 27 (Education), 28 (Science & Technology), 29 (Nonprofits & Activism).'
1154
+ })),
1155
+ tags: z.optional(z.array(z.string()).register(z.globalRegistry, {
1156
+ description: "Keyword tags for the video. Duplicates are removed. Total of all tags must be under 500 characters. Tags with spaces count as quoted (2 extra chars). Commas between tags also count."
1157
+ })),
1158
+ embeddable: z.optional(z.boolean().register(z.globalRegistry, {
1159
+ description: "Whether the video can be embedded on other websites. Defaults to true."
1160
+ })),
1161
+ playlistId: z.optional(z.string().register(z.globalRegistry, {
1162
+ description: "Playlist ID to add the video to after upload."
1163
+ }))
1164
+ }).register(z.globalRegistry, {
1165
+ description: "YouTube-specific upload settings, such as description and privacy."
1166
+ });
1167
+ var zTikTokPlatformSpecificSettings = z.object({
1168
+ privacyLevel: z.enum([
1169
+ "PUBLIC_TO_EVERYONE",
1170
+ "FOLLOWER_OF_CREATOR",
1171
+ "MUTUAL_FOLLOW_FRIENDS",
1172
+ "SELF_ONLY"
1173
+ ]).register(z.globalRegistry, {
1174
+ description: "Who can view this post. The value must match one of the options returned by the TikTok creator_info/query endpoint for the target account."
1175
+ }),
1176
+ disableComment: z.boolean().register(z.globalRegistry, {
1177
+ description: 'If true, other TikTok users cannot comment on this post. Ignored if the creator has set comments to "No one" in their privacy settings.'
1178
+ }),
1179
+ disableDuet: z.boolean().register(z.globalRegistry, {
1180
+ description: "If true, other TikTok users cannot create Duets with this post. Only applies to video posts. Ignored for photo posts and private accounts."
1181
+ }),
1182
+ disableStitch: z.boolean().register(z.globalRegistry, {
1183
+ description: "If true, other TikTok users cannot create Stitches with this post. Only applies to video posts. Ignored for photo posts and private accounts."
1184
+ }),
1185
+ brandContentToggle: z.boolean().register(z.globalRegistry, {
1186
+ description: "Set to true if this is a paid partnership promoting a third-party business. Required by TikTok for branded content disclosure."
1187
+ }),
1188
+ brandOrganicToggle: z.boolean().register(z.globalRegistry, {
1189
+ description: "Set to true if this post promotes the creator's own business."
1190
+ }),
1191
+ autoAddMusic: z.optional(z.boolean().register(z.globalRegistry, {
1192
+ description: "Photo posts only. If true, TikTok automatically adds recommended background music to the photo carousel. Users can change the music later in the TikTok app."
1193
+ })),
1194
+ videoMadeWithAi: z.optional(z.boolean().register(z.globalRegistry, {
1195
+ description: 'Video posts only. Set to true if the video is AI-generated content. The video will be labeled with a "Creator labeled as AI-generated" tag.'
1196
+ })),
1197
+ description: z.optional(z.string().check(z.maxLength(4e3)).register(z.globalRegistry, {
1198
+ description: "Photo posts only. Additional description text (max 4000 characters). Hashtags and mentions in the description are parsed by TikTok."
1199
+ })),
1200
+ photoCoverIndex: z.optional(z.int().check(z.gte(0)).register(z.globalRegistry, {
1201
+ description: "Photo posts only. Zero-based index of the image to use as the carousel cover. Defaults to 0 (first image)."
1202
+ }))
1203
+ }).register(z.globalRegistry, {
1204
+ description: "TikTok-specific publishing settings. Privacy level and brand toggles are required for all posts. Duet/stitch settings only apply to video posts. autoAddMusic only applies to photo posts."
1205
+ });
1206
+ var zLinkedInPlatformSpecificSettings = z.object({
1207
+ visibility: z.optional(z.enum(["CONNECTIONS", "PUBLIC"]).register(z.globalRegistry, {
1208
+ description: "Who can see the post. PUBLIC (anyone on LinkedIn) or CONNECTIONS (only your connections). Defaults to PUBLIC. Only available for personal profiles \u2014 company pages are always public."
1209
+ }))
1210
+ }).register(z.globalRegistry, {
1211
+ description: "LinkedIn-specific publishing settings, such as post visibility."
1212
+ });
1213
+ var zThreadsPlatformSpecificSettings = z.object({
1214
+ topicTag: z.optional(z.string().check(z.minLength(1), z.maxLength(50)).register(z.globalRegistry, {
1215
+ description: "A topic tag for the post (without the # prefix). Max 50 characters. Periods (.) and ampersands (&) are not allowed. Overrides any auto-detected topic from inline hashtags."
1216
+ }))
1217
+ }).register(z.globalRegistry, {
1218
+ description: "Threads-specific publishing settings."
1219
+ });
1220
+ var zTwitterPlatformSpecificSettings = z.object({
1221
+ communityId: z.optional(z.string().check(z.regex(/^[0-9]{1,19}$/)).register(z.globalRegistry, {
1222
+ description: "Post to a specific X Community. The authenticated user must be a member of the community."
1223
+ })),
1224
+ shareWithFollowers: z.optional(z.boolean().register(z.globalRegistry, {
1225
+ description: "When posting to a community, also share the post with your followers. Only applies when `communityId` is set."
1226
+ })),
1227
+ forSuperFollowersOnly: z.optional(z.boolean().register(z.globalRegistry, {
1228
+ description: "Make this post exclusive to your subscribers (super followers)."
1229
+ })),
1230
+ replySettings: z.optional(z.enum([
1231
+ "following",
1232
+ "mentionedUsers",
1233
+ "subscribers",
1234
+ "verified"
1235
+ ]).register(z.globalRegistry, {
1236
+ description: "Control who can reply. `following`: only people you follow. `mentionedUsers`: only people mentioned in the post. `subscribers`: only your subscribers. `verified`: only verified users."
1237
+ })),
1238
+ quoteTweetId: z.optional(z.string().check(z.regex(/^[0-9]{1,19}$/)).register(z.globalRegistry, {
1239
+ description: "ID of an existing tweet to quote. Mutually exclusive with poll and media."
1240
+ })),
1241
+ replyToTweetId: z.optional(z.string().check(z.regex(/^[0-9]{1,19}$/)).register(z.globalRegistry, {
1242
+ description: "ID of an existing tweet to reply to. Your post will appear as a reply in that tweet's thread."
1243
+ })),
1244
+ poll: z.optional(z.object({
1245
+ options: z.array(z.string().check(z.minLength(1), z.maxLength(25))).check(z.minLength(2), z.maxLength(4)).register(z.globalRegistry, {
1246
+ description: "Poll choices. 2-4 options, max 25 characters each."
1247
+ }),
1248
+ durationMinutes: z.int().check(z.gte(5), z.lte(10080)).register(z.globalRegistry, {
1249
+ description: "How long the poll stays open, in minutes. Min 5 minutes, max 7 days (10080)."
1250
+ })
1251
+ }).register(z.globalRegistry, {
1252
+ description: "Create a poll. Mutually exclusive with media and `quoteTweetId`."
1253
+ }))
1254
+ }).register(z.globalRegistry, {
1255
+ description: "X (Twitter) specific post settings. All fields are optional."
1256
+ });
1257
+ var zSocialPlatform = z.enum([
1258
+ "TWITTER",
1259
+ "INSTAGRAM",
1260
+ "FACEBOOK",
1261
+ "LINKEDIN",
1262
+ "YOUTUBE",
1263
+ "TIKTOK",
1264
+ "THREADS",
1265
+ "BLUESKY"
1266
+ ]);
1267
+ var zPostStatus = z.enum([
1268
+ "DRAFT",
1269
+ "SCHEDULED",
1270
+ "PUBLISHING",
1271
+ "PUBLISHED",
1272
+ "FAILED"
1273
+ ]);
1274
+ var zPostOverrides = z.object({
1275
+ content: z.optional(z.string().register(z.globalRegistry, {
1276
+ description: "Custom text for this account, overriding the post-level content."
1277
+ })),
1278
+ thumbnailTimestamp: z.optional(z.int().check(z.gte(0)).register(z.globalRegistry, {
1279
+ description: "Video thumbnail timestamp in milliseconds. Applies to Instagram and TikTok."
1280
+ })),
1281
+ mediaIds: z.optional(z.array(z.uuid()).register(z.globalRegistry, {
1282
+ description: "Replacement media for this account. Completely replaces the post-level media."
1283
+ }))
1284
+ });
1285
+ var zPlatformSpecificSettings = z.union([
1286
+ z.object({
1287
+ description: z.optional(z.string().check(z.maxLength(5e3)).register(z.globalRegistry, {
1288
+ description: "Video description. Max 5000 characters. Shown below the video title on the watch page."
1289
+ })),
1290
+ privacyStatus: z.optional(z.enum([
1291
+ "public",
1292
+ "unlisted",
1293
+ "private"
1294
+ ]).register(z.globalRegistry, {
1295
+ description: "Video privacy status. Defaults to public. Unverified API projects are restricted to private."
1296
+ })),
1297
+ madeForKids: z.optional(z.boolean().register(z.globalRegistry, {
1298
+ description: "Declare the video as made for kids (COPPA). When true, personalized ads are disabled and some features (comments, notifications) are turned off."
1299
+ })),
1300
+ containsSyntheticMedia: z.optional(z.boolean().register(z.globalRegistry, {
1301
+ description: "Disclose that the video contains realistic altered or synthetic (AI-generated) content."
1302
+ })),
1303
+ categoryId: z.optional(z.enum([
1304
+ "1",
1305
+ "2",
1306
+ "10",
1307
+ "15",
1308
+ "17",
1309
+ "19",
1310
+ "20",
1311
+ "22",
1312
+ "23",
1313
+ "24",
1314
+ "25",
1315
+ "26",
1316
+ "27",
1317
+ "28",
1318
+ "29"
1319
+ ]).register(z.globalRegistry, {
1320
+ description: 'YouTube video category. Defaults to "22" (People & Blogs). Valid IDs: 1 (Film & Animation), 2 (Autos & Vehicles), 10 (Music), 15 (Pets & Animals), 17 (Sports), 19 (Travel & Events), 20 (Gaming), 22 (People & Blogs), 23 (Comedy), 24 (Entertainment), 25 (News & Politics), 26 (Howto & Style), 27 (Education), 28 (Science & Technology), 29 (Nonprofits & Activism).'
1321
+ })),
1322
+ tags: z.optional(z.array(z.string()).register(z.globalRegistry, {
1323
+ description: "Keyword tags for the video. Duplicates are removed. Total of all tags must be under 500 characters. Tags with spaces count as quoted (2 extra chars). Commas between tags also count."
1324
+ })),
1325
+ embeddable: z.optional(z.boolean().register(z.globalRegistry, {
1326
+ description: "Whether the video can be embedded on other websites. Defaults to true."
1327
+ })),
1328
+ playlistId: z.optional(z.string().register(z.globalRegistry, {
1329
+ description: "Playlist ID to add the video to after upload."
1330
+ }))
1331
+ }).register(z.globalRegistry, {
1332
+ description: "YouTube-specific upload settings, such as description and privacy."
1333
+ }),
1334
+ z.object({
1335
+ privacyLevel: z.enum([
1336
+ "PUBLIC_TO_EVERYONE",
1337
+ "FOLLOWER_OF_CREATOR",
1338
+ "MUTUAL_FOLLOW_FRIENDS",
1339
+ "SELF_ONLY"
1340
+ ]).register(z.globalRegistry, {
1341
+ description: "Who can view this post. The value must match one of the options returned by the TikTok creator_info/query endpoint for the target account."
1342
+ }),
1343
+ disableComment: z.boolean().register(z.globalRegistry, {
1344
+ description: 'If true, other TikTok users cannot comment on this post. Ignored if the creator has set comments to "No one" in their privacy settings.'
1345
+ }),
1346
+ disableDuet: z.boolean().register(z.globalRegistry, {
1347
+ description: "If true, other TikTok users cannot create Duets with this post. Only applies to video posts. Ignored for photo posts and private accounts."
1348
+ }),
1349
+ disableStitch: z.boolean().register(z.globalRegistry, {
1350
+ description: "If true, other TikTok users cannot create Stitches with this post. Only applies to video posts. Ignored for photo posts and private accounts."
1351
+ }),
1352
+ brandContentToggle: z.boolean().register(z.globalRegistry, {
1353
+ description: "Set to true if this is a paid partnership promoting a third-party business. Required by TikTok for branded content disclosure."
1354
+ }),
1355
+ brandOrganicToggle: z.boolean().register(z.globalRegistry, {
1356
+ description: "Set to true if this post promotes the creator's own business."
1357
+ }),
1358
+ autoAddMusic: z.optional(z.boolean().register(z.globalRegistry, {
1359
+ description: "Photo posts only. If true, TikTok automatically adds recommended background music to the photo carousel. Users can change the music later in the TikTok app."
1360
+ })),
1361
+ videoMadeWithAi: z.optional(z.boolean().register(z.globalRegistry, {
1362
+ description: 'Video posts only. Set to true if the video is AI-generated content. The video will be labeled with a "Creator labeled as AI-generated" tag.'
1363
+ })),
1364
+ description: z.optional(z.string().check(z.maxLength(4e3)).register(z.globalRegistry, {
1365
+ description: "Photo posts only. Additional description text (max 4000 characters). Hashtags and mentions in the description are parsed by TikTok."
1366
+ })),
1367
+ photoCoverIndex: z.optional(z.int().check(z.gte(0)).register(z.globalRegistry, {
1368
+ description: "Photo posts only. Zero-based index of the image to use as the carousel cover. Defaults to 0 (first image)."
1369
+ }))
1370
+ }).register(z.globalRegistry, {
1371
+ description: "TikTok-specific publishing settings. Privacy level and brand toggles are required for all posts. Duet/stitch settings only apply to video posts. autoAddMusic only applies to photo posts."
1372
+ }),
1373
+ z.object({
1374
+ contentType: z.optional(z.enum(["story", "reels"]).register(z.globalRegistry, {
1375
+ description: 'Set to "story" for ephemeral content that disappears after 24 hours. Set to "reels" to explicitly publish as a Reel. Omit for a regular feed post or carousel \u2014 single videos are automatically published as Reels.'
1376
+ })),
1377
+ shareToFeed: z.optional(z.boolean().register(z.globalRegistry, {
1378
+ description: "Reels only. When true (default), the reel can appear in both the Feed and Reels tabs. When false, it only appears in the Reels tab. Neither value guarantees placement \u2014 Instagram's algorithm decides based on eligibility and relevance."
1379
+ })),
1380
+ trialParams: z.optional(z.object({
1381
+ graduationStrategy: z.enum(["MANUAL", "SS_PERFORMANCE"]).register(z.globalRegistry, {
1382
+ description: "MANUAL: the trial reel can be graduated (converted to a public reel) manually in the Instagram app. SS_PERFORMANCE: Instagram automatically graduates the reel if it performs well with non-followers."
1383
+ })
1384
+ }).register(z.globalRegistry, {
1385
+ description: "Reels only. Publish as a trial reel \u2014 shown only to non-followers first. Instagram requires a public account with at least 200 followers and rejects the post otherwise."
1386
+ })),
1387
+ audioName: z.optional(z.string().register(z.globalRegistry, {
1388
+ description: "Reels only. Custom name for the audio track of your reel. Can only be set once \u2014 either at creation time or later from the audio page in the Instagram app."
1389
+ }))
1390
+ }).register(z.globalRegistry, {
1391
+ description: "Instagram-specific post settings. All fields are optional \u2014 omit the entire object for a regular feed post or carousel."
1392
+ }),
1393
+ z.object({
1394
+ contentType: z.optional(z.enum(["story"]).register(z.globalRegistry, {
1395
+ description: 'Set to "story" for ephemeral content that disappears after 24 hours. Omit for a regular post \u2014 single videos are automatically published as Reels (Facebook no longer has a separate video format).'
1396
+ }))
1397
+ }).register(z.globalRegistry, {
1398
+ description: "Facebook-specific post settings. All fields are optional \u2014 omit the entire object for a regular post."
1399
+ }),
1400
+ z.object({
1401
+ topicTag: z.optional(z.string().check(z.minLength(1), z.maxLength(50)).register(z.globalRegistry, {
1402
+ description: "A topic tag for the post (without the # prefix). Max 50 characters. Periods (.) and ampersands (&) are not allowed. Overrides any auto-detected topic from inline hashtags."
1403
+ }))
1404
+ }).register(z.globalRegistry, {
1405
+ description: "Threads-specific publishing settings."
1406
+ }),
1407
+ z.object({
1408
+ communityId: z.optional(z.string().check(z.regex(/^[0-9]{1,19}$/)).register(z.globalRegistry, {
1409
+ description: "Post to a specific X Community. The authenticated user must be a member of the community."
1410
+ })),
1411
+ shareWithFollowers: z.optional(z.boolean().register(z.globalRegistry, {
1412
+ description: "When posting to a community, also share the post with your followers. Only applies when `communityId` is set."
1413
+ })),
1414
+ forSuperFollowersOnly: z.optional(z.boolean().register(z.globalRegistry, {
1415
+ description: "Make this post exclusive to your subscribers (super followers)."
1416
+ })),
1417
+ replySettings: z.optional(z.enum([
1418
+ "following",
1419
+ "mentionedUsers",
1420
+ "subscribers",
1421
+ "verified"
1422
+ ]).register(z.globalRegistry, {
1423
+ description: "Control who can reply. `following`: only people you follow. `mentionedUsers`: only people mentioned in the post. `subscribers`: only your subscribers. `verified`: only verified users."
1424
+ })),
1425
+ quoteTweetId: z.optional(z.string().check(z.regex(/^[0-9]{1,19}$/)).register(z.globalRegistry, {
1426
+ description: "ID of an existing tweet to quote. Mutually exclusive with poll and media."
1427
+ })),
1428
+ replyToTweetId: z.optional(z.string().check(z.regex(/^[0-9]{1,19}$/)).register(z.globalRegistry, {
1429
+ description: "ID of an existing tweet to reply to. Your post will appear as a reply in that tweet's thread."
1430
+ })),
1431
+ poll: z.optional(z.object({
1432
+ options: z.array(z.string().check(z.minLength(1), z.maxLength(25))).check(z.minLength(2), z.maxLength(4)).register(z.globalRegistry, {
1433
+ description: "Poll choices. 2-4 options, max 25 characters each."
1434
+ }),
1435
+ durationMinutes: z.int().check(z.gte(5), z.lte(10080)).register(z.globalRegistry, {
1436
+ description: "How long the poll stays open, in minutes. Min 5 minutes, max 7 days (10080)."
1437
+ })
1438
+ }).register(z.globalRegistry, {
1439
+ description: "Create a poll. Mutually exclusive with media and `quoteTweetId`."
1440
+ }))
1441
+ }).register(z.globalRegistry, {
1442
+ description: "X (Twitter) specific post settings. All fields are optional."
1443
+ }),
1444
+ z.object({
1445
+ visibility: z.optional(z.enum(["CONNECTIONS", "PUBLIC"]).register(z.globalRegistry, {
1446
+ description: "Who can see the post. PUBLIC (anyone on LinkedIn) or CONNECTIONS (only your connections). Defaults to PUBLIC. Only available for personal profiles \u2014 company pages are always public."
1447
+ }))
1448
+ }).register(z.globalRegistry, {
1449
+ description: "LinkedIn-specific publishing settings, such as post visibility."
1450
+ }),
1451
+ z.record(z.string(), z.never()).register(z.globalRegistry, {
1452
+ description: "Bluesky-specific publishing settings. No settings are currently available."
1453
+ }),
1454
+ z.record(z.string(), z.unknown())
1455
+ ]);
1456
+ var zPostAccount = z.object({
1457
+ accountId: z.uuid().register(z.globalRegistry, {
1458
+ description: "The connected social account identifier."
1459
+ }),
1460
+ platform: zSocialPlatform,
1461
+ accountName: z.string().register(z.globalRegistry, {
1462
+ description: "Display name or username of the connected account."
1463
+ }),
1464
+ status: zPostStatus,
1465
+ externalUrl: z.optional(z.url().register(z.globalRegistry, {
1466
+ description: "Link to the published post on the social platform. Present only after successful publishing."
1467
+ })),
1468
+ publishedAt: z.optional(z.iso.datetime().register(z.globalRegistry, {
1469
+ description: "When this account's post was published."
1470
+ })),
1471
+ errorMessage: z.optional(z.string().register(z.globalRegistry, {
1472
+ description: "Error message from the platform if publishing failed for this account."
1473
+ })),
1474
+ postOverrides: z.optional(zPostOverrides),
1475
+ platformSpecificSettings: z.optional(zPlatformSpecificSettings)
1476
+ });
1477
+ var zPost = z.object({
1478
+ id: z.uuid().register(z.globalRegistry, {
1479
+ description: "Unique post identifier."
1480
+ }),
1481
+ content: z.string().register(z.globalRegistry, {
1482
+ description: "The shared text content of the post."
1483
+ }),
1484
+ status: zPostStatus,
1485
+ errorMessage: z.optional(z.string().register(z.globalRegistry, {
1486
+ description: "Human-readable error summary when one or more accounts failed."
1487
+ })),
1488
+ mediaIds: z.optional(z.array(z.uuid()).register(z.globalRegistry, {
1489
+ description: "Media attached to this post."
1490
+ })),
1491
+ deletedMediaCount: z.optional(z.int().check(z.gte(0)).register(z.globalRegistry, {
1492
+ description: "How many media were attached to this post but have since been deleted (rendered as placeholders). Lets a client tell a post that HAD media apart from one posted with none."
1493
+ })),
1494
+ scheduledAt: z.optional(z.iso.datetime().register(z.globalRegistry, {
1495
+ description: "When the post is scheduled to be published."
1496
+ })),
1497
+ publishedAt: z.optional(z.iso.datetime().register(z.globalRegistry, {
1498
+ description: "When the post was published. Present only when all accounts are published."
1499
+ })),
1500
+ createdAt: z.iso.datetime().register(z.globalRegistry, {
1501
+ description: "When the post was created."
1502
+ }),
1503
+ accounts: z.array(zPostAccount).register(z.globalRegistry, {
1504
+ description: "Individual account entries. Each represents the post on one connected social account."
1505
+ })
1506
+ });
1507
+ var zPostsResponse = z.object({
1508
+ posts: z.array(zPost),
1509
+ pagination: zPagination
1510
+ });
1511
+ var zCreatePostAccount = z.object({
1512
+ accountId: z.uuid().register(z.globalRegistry, {
1513
+ description: "ID of a connected social account to post to."
1514
+ }),
1515
+ postOverrides: z.optional(z.intersection(zPostOverrides, z.unknown().register(z.globalRegistry, {
1516
+ description: "Override the post-level content or media for this specific account."
1517
+ }))),
1518
+ platformSpecificSettings: z.optional(z.intersection(zPlatformSpecificSettings, z.unknown().register(z.globalRegistry, {
1519
+ description: "Platform-specific settings. The accepted shape depends on the account platform."
1520
+ })))
1521
+ });
1522
+ var zCreatePostRequest = z.object({
1523
+ content: z._default(z.optional(z.string().register(z.globalRegistry, {
1524
+ description: "The text content of the post, shared across all accounts unless overridden. Optional when media is attached (platform-dependent)."
1525
+ })), ""),
1526
+ mediaIds: z.optional(z.array(z.uuid()).register(z.globalRegistry, {
1527
+ description: "Media to attach to the post. Shared across all accounts unless an account provides its own mediaIds in postOverrides."
1528
+ })),
1529
+ thumbnailTimestamp: z.optional(z.int().check(z.gte(0)).register(z.globalRegistry, {
1530
+ description: "Default video thumbnail timestamp in milliseconds for Instagram and TikTok. Can be overridden per account."
1531
+ })),
1532
+ accounts: z.array(zCreatePostAccount).check(z.minLength(1)).register(z.globalRegistry, {
1533
+ description: "Accounts to post to. Each entry can optionally include content overrides and platform-specific settings."
1534
+ }),
1535
+ scheduledAt: z.optional(z.iso.datetime().register(z.globalRegistry, {
1536
+ description: "Schedule the post for a future date. If omitted and publishNow is false or absent, the post is saved as a draft."
1537
+ })),
1538
+ publishNow: z.optional(z.boolean().register(z.globalRegistry, {
1539
+ description: "Publish immediately. Cannot be combined with scheduledAt."
1540
+ }))
1541
+ }).register(z.globalRegistry, {
1542
+ description: "Create a post across one or more connected social accounts."
1543
+ });
1544
+ var zUpdatePostRequest = z.object({
1545
+ content: z.optional(z.string().register(z.globalRegistry, {
1546
+ description: "New shared text content for the post."
1547
+ })),
1548
+ scheduledAt: z.optional(z.iso.datetime().register(z.globalRegistry, {
1549
+ description: "New scheduled date for the post. Must be at least 1 minute in the future."
1550
+ })),
1551
+ mediaIds: z.optional(z.array(z.uuid()).register(z.globalRegistry, {
1552
+ description: "Full replacement for the post media. If omitted, the existing media stays unchanged. If provided, it replaces the current media across all accounts in the post. Send an empty array to remove all media from the post."
1553
+ })),
1554
+ thumbnailTimestamp: z.optional(z.int().check(z.gte(0)).register(z.globalRegistry, {
1555
+ description: "New video thumbnail timestamp in milliseconds for Instagram and TikTok media. Does not change which media files are attached. Combine with mediaIds if you want to replace media and set the new thumbnail timestamp in the same request."
1556
+ })),
1557
+ accounts: z.optional(z.array(zCreatePostAccount).check(z.minLength(1)).register(z.globalRegistry, {
1558
+ description: "Accounts whose content overrides or platform-specific settings should be updated, plus any additional connected accounts to add to the post. Existing accounts omitted from this array remain unchanged and must be removed through the account-specific delete endpoint."
1559
+ })),
1560
+ publishNow: z.optional(z.boolean().register(z.globalRegistry, {
1561
+ description: "Publish an existing draft immediately. Cannot be combined with scheduledAt."
1562
+ }))
1563
+ }).register(z.globalRegistry, {
1564
+ description: "Update a draft or scheduled post. Published and publishing posts cannot be updated. Media behavior is explicit: omit mediaIds to keep existing media unchanged, provide mediaIds to replace all current media, or provide an empty mediaIds array to remove all media."
1565
+ });
1566
+ var zSuccessMessage = z.object({
1567
+ deleted: z.literal(true),
1568
+ id: z.uuid()
1569
+ });
1570
+ var zAccount = z.object({
1571
+ id: z.uuid().register(z.globalRegistry, {
1572
+ description: "Unique social account identifier in PublishQ."
1573
+ }),
1574
+ platform: z.intersection(zSocialPlatform, z.unknown().register(z.globalRegistry, {
1575
+ description: "Social platform that this connected account belongs to."
1576
+ })),
1577
+ platformName: z.nullish(z.string()),
1578
+ platformUsername: z.string().register(z.globalRegistry, {
1579
+ description: "Primary username or handle on the connected social platform."
1580
+ }),
1581
+ platformUserId: z.string().register(z.globalRegistry, {
1582
+ description: "Unique user or channel identifier provided by the social platform."
1583
+ }),
1584
+ platformPicture: z.nullish(z.string()),
1585
+ workspaceId: z.nullish(z.uuid())
1586
+ });
1587
+ var zAccountsResponse = z.object({
1588
+ accounts: z.array(zAccount).register(z.globalRegistry, {
1589
+ description: "Connected social accounts visible to the authenticated API key."
1590
+ })
1591
+ });
1592
+ var zWorkspace = z.object({
1593
+ id: z.uuid().register(z.globalRegistry, {
1594
+ description: "Unique workspace identifier in PublishQ."
1595
+ }),
1596
+ name: z.string().register(z.globalRegistry, {
1597
+ description: "Workspace name shown in the PublishQ UI."
1598
+ }),
1599
+ description: z.nullish(z.string()),
1600
+ color: z.string().register(z.globalRegistry, {
1601
+ description: "Workspace accent color in hex format."
1602
+ }),
1603
+ accountCount: z.int().register(z.globalRegistry, {
1604
+ description: "Number of social accounts assigned to this workspace."
1605
+ }),
1606
+ createdAt: z.iso.datetime().register(z.globalRegistry, {
1607
+ description: "When the workspace was created."
1608
+ })
1609
+ });
1610
+ var zCreateWorkspaceRequest = z.object({
1611
+ name: z.string().check(z.minLength(1), z.maxLength(50)).register(z.globalRegistry, {
1612
+ description: "Workspace name shown in PublishQ."
1613
+ }),
1614
+ description: z.optional(z.string().check(z.maxLength(500)).register(z.globalRegistry, {
1615
+ description: "Optional short description of the workspace."
1616
+ })),
1617
+ color: z._default(z.optional(z.string().check(z.regex(/^#[0-9A-Fa-f]{6}$/)).register(z.globalRegistry, {
1618
+ description: "Workspace accent color as a hex string like `#6366f1`."
1619
+ })), "#6366f1")
1620
+ }).register(z.globalRegistry, {
1621
+ description: "Create a new workspace."
1622
+ });
1623
+ var zWorkspacesResponse = z.object({
1624
+ workspaces: z.array(zWorkspace).register(z.globalRegistry, {
1625
+ description: "Workspaces visible to the authenticated API key owner."
1626
+ })
1627
+ });
1628
+ var zMediaType = z.enum(["IMAGE", "VIDEO"]).register(z.globalRegistry, {
1629
+ description: "Media file type."
1630
+ });
1631
+ var zMediaSource = z.enum([
1632
+ "UPLOAD",
1633
+ "GENERATED",
1634
+ "AI_GENERATED"
1635
+ ]).register(z.globalRegistry, {
1636
+ description: "How the media was created: uploaded by the user, generated inside PublishQ, or AI-generated inside PublishQ."
1637
+ });
1638
+ var zMedia = z.object({
1639
+ id: z.uuid().register(z.globalRegistry, {
1640
+ description: "Unique media identifier in PublishQ."
1641
+ }),
1642
+ type: zMediaType,
1643
+ url: z.url().register(z.globalRegistry, {
1644
+ description: "Direct URL to the uploaded or generated media file."
1645
+ }),
1646
+ source: zMediaSource,
1647
+ created_at: z.iso.datetime().register(z.globalRegistry, {
1648
+ description: "When the media item was created in PublishQ."
1649
+ }),
1650
+ usageCount: z.int().register(z.globalRegistry, {
1651
+ description: "Number of posts this media item was used in."
1652
+ })
1653
+ });
1654
+ var zMediaListResponse = z.object({
1655
+ media: z.array(zMedia),
1656
+ pagination: zPagination
1657
+ });
1658
+ var zUploadMediaRequest = z.object({
1659
+ file: z.string()
1660
+ });
1661
+ var zTikTokCreatorInfoResponse = z.object({
1662
+ privacyLevelOptions: z.array(z.string()).register(z.globalRegistry, {
1663
+ description: "Privacy levels available for this account. Use one of these values as `privacyLevel` in `platformSpecificSettings`."
1664
+ }),
1665
+ commentDisabled: z.boolean().register(z.globalRegistry, {
1666
+ description: "True if the creator has disabled comments at the account level."
1667
+ }),
1668
+ duetDisabled: z.boolean().register(z.globalRegistry, {
1669
+ description: "True if the creator has disabled Duets at the account level."
1670
+ }),
1671
+ stitchDisabled: z.boolean().register(z.globalRegistry, {
1672
+ description: "True if the creator has disabled Stitches at the account level."
1673
+ }),
1674
+ maxVideoPostDurationSec: z.number().register(z.globalRegistry, {
1675
+ description: "Maximum video duration in seconds this creator can post (typically 180, 300, or 600)."
1676
+ })
1677
+ });
1678
+ var zApiKeyScope = z.enum([
1679
+ "posts:read",
1680
+ "posts:write",
1681
+ "accounts:read",
1682
+ "workspaces:read",
1683
+ "workspaces:write",
1684
+ "media:read",
1685
+ "media:write"
1686
+ ]);
1687
+ var zListPostsQuery = z.object({
1688
+ page: z._default(z.optional(z.int().check(z.gt(0)).register(z.globalRegistry, {
1689
+ description: "Page number (starts from 1)."
1690
+ })), 1),
1691
+ limit: z._default(z.optional(z.int().check(z.gt(0), z.lte(100)).register(z.globalRegistry, {
1692
+ description: "Page size. Max 100."
1693
+ })), 20)
1694
+ });
1695
+ var zListPostsResponse = zPostsResponse;
1696
+ var zCreatePostBody = zCreatePostRequest;
1697
+ var zCreatePostResponse = zPost;
1698
+ var zDeletePostPath = z.object({
1699
+ id: z.uuid()
1700
+ });
1701
+ var zDeletePostResponse = z.void().register(z.globalRegistry, {
1702
+ description: "Post deleted successfully"
1703
+ });
1704
+ var zGetPostPath = z.object({
1705
+ id: z.uuid()
1706
+ });
1707
+ var zGetPostResponse = zPost;
1708
+ var zUpdatePostBody = zUpdatePostRequest;
1709
+ var zUpdatePostPath = z.object({
1710
+ id: z.uuid()
1711
+ });
1712
+ var zUpdatePostResponse = zPost;
1713
+ var zRemovePostAccountPath = z.object({
1714
+ id: z.uuid(),
1715
+ accountId: z.uuid()
1716
+ });
1717
+ var zRemovePostAccountResponse = z.void().register(z.globalRegistry, {
1718
+ description: "Account removed from post successfully"
1719
+ });
1720
+ var zListAccountsQuery = z.object({
1721
+ workspaceId: z.optional(z.uuid().register(z.globalRegistry, {
1722
+ description: "Return only accounts assigned to the specified workspace. If omitted, accounts from all workspaces are returned."
1723
+ })),
1724
+ platform: z.optional(z.array(zSocialPlatform).register(z.globalRegistry, {
1725
+ description: "Return only accounts connected to the specified social platforms. Repeat the parameter to apply OR logic, for example `?platform=twitter&platform=instagram`."
1726
+ }))
1727
+ });
1728
+ var zListAccountsResponse = zAccountsResponse;
1729
+ var zGetTikTokCreatorInfoPath = z.object({
1730
+ id: z.uuid()
1731
+ });
1732
+ var zGetTikTokCreatorInfoResponse = zTikTokCreatorInfoResponse;
1733
+ var zListWorkspacesResponse = zWorkspacesResponse;
1734
+ var zCreateWorkspaceBody = zCreateWorkspaceRequest;
1735
+ var zCreateWorkspaceResponse = zWorkspace;
1736
+ var zGetWorkspacePath = z.object({
1737
+ id: z.uuid()
1738
+ });
1739
+ var zGetWorkspaceResponse = zWorkspace;
1740
+ var zListMediaQuery = z.object({
1741
+ page: z._default(z.optional(z.int().check(z.gt(0)).register(z.globalRegistry, {
1742
+ description: "Page number (starts from 1)."
1743
+ })), 1),
1744
+ limit: z._default(z.optional(z.int().check(z.gt(0), z.lte(100)).register(z.globalRegistry, {
1745
+ description: "Page size. Max 100."
1746
+ })), 20),
1747
+ ids: z.optional(z.array(z.uuid()).register(z.globalRegistry, {
1748
+ description: "Return only the specified media IDs. Repeat the parameter to apply OR logic, for example `?ids=id1&ids=id2`."
1749
+ })),
1750
+ mediaTypes: z.optional(z.array(zMediaType).register(z.globalRegistry, {
1751
+ description: "Return only media items of the specified types. Repeat the parameter to apply OR logic, for example `?mediaTypes=image&mediaTypes=video`."
1752
+ })),
1753
+ sources: z.optional(z.array(zMediaSource).register(z.globalRegistry, {
1754
+ description: "Return only media items from the specified sources. Repeat the parameter to apply OR logic, for example `?sources=upload&sources=ai_generated`."
1755
+ }))
1756
+ });
1757
+ var zListMediaResponse = zMediaListResponse;
1758
+ var zUploadMediaBody = zUploadMediaRequest;
1759
+ var zUploadMediaResponse = zMedia;
1760
+ var zGetMediaPath = z.object({
1761
+ id: z.uuid()
1762
+ });
1763
+ var zGetMediaResponse = zMedia;
1764
+
1765
+ // src/index.ts
1766
+ var rawErrorBodies = /* @__PURE__ */ new WeakMap();
1767
+ async function preserveApiError(call) {
1768
+ const result = await call;
1769
+ const response = result.response;
1770
+ const rawBody = response ? rawErrorBodies.get(response) : void 0;
1771
+ if (!response || response.ok || !rawBody) {
1772
+ return result;
1773
+ }
1774
+ const text = await rawBody;
1775
+ if (text.length === 0) {
1776
+ return { ...result, error: void 0 };
1777
+ }
1778
+ let error = text;
1779
+ try {
1780
+ error = JSON.parse(text);
1781
+ } catch {
1782
+ }
1783
+ return { ...result, error };
1784
+ }
1785
+ var PublishQ = class {
1786
+ /**
1787
+ * Post resources — create, list, retrieve, update, and delete posts across
1788
+ * the connected accounts this API key is scoped to.
1789
+ */
1790
+ posts;
1791
+ /**
1792
+ * Account resources — list connected social accounts and read the TikTok
1793
+ * creator info required before posting to TikTok.
1794
+ */
1795
+ accounts;
1796
+ /**
1797
+ * Workspace resources — list, create, and retrieve the workspaces that
1798
+ * organize your connected accounts.
1799
+ */
1800
+ workspaces;
1801
+ /**
1802
+ * Media resources — upload, list, and retrieve media files you can attach
1803
+ * to posts.
1804
+ */
1805
+ media;
1806
+ constructor(options) {
1807
+ const client2 = createClient(
1808
+ createConfig({
1809
+ baseUrl: options.baseUrl ?? "https://publishq.com/api/v1",
1810
+ headers: {
1811
+ Authorization: `Bearer ${options.apiKey}`
1812
+ }
1813
+ })
1814
+ );
1815
+ client2.interceptors.response.use((response) => {
1816
+ if (!response.ok) {
1817
+ rawErrorBodies.set(response, response.clone().text());
1818
+ }
1819
+ return response;
1820
+ });
1821
+ this.posts = createPostsNamespace(client2);
1822
+ this.accounts = createAccountsNamespace(client2);
1823
+ this.workspaces = createWorkspacesNamespace(client2);
1824
+ this.media = createMediaNamespace(client2);
1825
+ }
1826
+ };
1827
+ function createPostsNamespace(client2) {
1828
+ return {
1829
+ /** List posts. Optionally filter by status/workspace/account and paginate. Wraps `Posts.listPosts`. */
1830
+ list: (query) => preserveApiError(Posts.listPosts({ client: client2, query })),
1831
+ /** Create a post for one or more connected accounts. Wraps `Posts.createPost`. */
1832
+ create: (body) => preserveApiError(Posts.createPost({ client: client2, body })),
1833
+ /** Get one post by its PublishQ post ID. Wraps `Posts.getPost`. */
1834
+ get: (id) => preserveApiError(Posts.getPost({ client: client2, path: { id } })),
1835
+ /** Update a draft or scheduled post. Wraps `Posts.updatePost`. */
1836
+ update: (id, body) => preserveApiError(Posts.updatePost({ client: client2, path: { id }, body })),
1837
+ /** Delete a scheduled or draft post by its ID. Wraps `Posts.deletePost`. */
1838
+ delete: (id) => preserveApiError(Posts.deletePost({ client: client2, path: { id } })),
1839
+ /** Remove one account from a post so it's no longer published there. Wraps `Posts.removePostAccount`. */
1840
+ removeAccount: (id, accountId) => preserveApiError(
1841
+ Posts.removePostAccount({ client: client2, path: { id, accountId } })
1842
+ )
1843
+ };
1844
+ }
1845
+ function createAccountsNamespace(client2) {
1846
+ return {
1847
+ /** List connected social accounts. Filter by workspace and platform. Wraps `Accounts.listAccounts`. */
1848
+ list: (query) => preserveApiError(Accounts.listAccounts({ client: client2, query })),
1849
+ /** Get a TikTok account's creator info (privacy options, limits) before posting. Wraps `Accounts.getTikTokCreatorInfo`. */
1850
+ getTikTokCreatorInfo: (id) => preserveApiError(
1851
+ Accounts.getTikTokCreatorInfo({ client: client2, path: { id } })
1852
+ )
1853
+ };
1854
+ }
1855
+ function createWorkspacesNamespace(client2) {
1856
+ return {
1857
+ /** List your workspaces with names, colors, and account counts. Wraps `Workspaces.listWorkspaces`. */
1858
+ list: () => preserveApiError(Workspaces.listWorkspaces({ client: client2 })),
1859
+ /** Create a workspace to organize your connected accounts. Wraps `Workspaces.createWorkspace`. */
1860
+ create: (body) => preserveApiError(Workspaces.createWorkspace({ client: client2, body })),
1861
+ /** Get one workspace by ID. Wraps `Workspaces.getWorkspace`. */
1862
+ get: (id) => preserveApiError(Workspaces.getWorkspace({ client: client2, path: { id } }))
1863
+ };
1864
+ }
1865
+ function createMediaNamespace(client2) {
1866
+ return {
1867
+ /** List your uploaded and generated media files. Filter by id, type, source. Wraps `Media.listMedia`. */
1868
+ list: (query) => preserveApiError(Media.listMedia({ client: client2, query })),
1869
+ /** Upload one media file (multipart) and get back a media ID to attach to posts. Wraps `Media.uploadMedia`. */
1870
+ upload: (body) => preserveApiError(Media.uploadMedia({ client: client2, body })),
1871
+ /** Get one media file by ID. Wraps `Media.getMedia`. */
1872
+ get: (id) => preserveApiError(Media.getMedia({ client: client2, path: { id } }))
1873
+ };
1874
+ }
1875
+ var index_default = PublishQ;
1876
+ export {
1877
+ Accounts,
1878
+ Media as Media2,
1879
+ Posts,
1880
+ PublishQ,
1881
+ Workspaces,
1882
+ index_default as default,
1883
+ zAccount,
1884
+ zAccountsResponse,
1885
+ zApiError,
1886
+ zApiErrorCode,
1887
+ zApiKeyScope,
1888
+ zBlueskyPlatformSpecificSettings,
1889
+ zCreatePostAccount,
1890
+ zCreatePostBody,
1891
+ zCreatePostRequest,
1892
+ zCreatePostResponse,
1893
+ zCreateWorkspaceBody,
1894
+ zCreateWorkspaceRequest,
1895
+ zCreateWorkspaceResponse,
1896
+ zDeletePostPath,
1897
+ zDeletePostResponse,
1898
+ zFacebookPlatformSpecificSettings,
1899
+ zGetMediaPath,
1900
+ zGetMediaResponse,
1901
+ zGetPostPath,
1902
+ zGetPostResponse,
1903
+ zGetTikTokCreatorInfoPath,
1904
+ zGetTikTokCreatorInfoResponse,
1905
+ zGetWorkspacePath,
1906
+ zGetWorkspaceResponse,
1907
+ zInstagramPlatformSpecificSettings,
1908
+ zInstagramTrialParams,
1909
+ zLinkedInPlatformSpecificSettings,
1910
+ zListAccountsQuery,
1911
+ zListAccountsResponse,
1912
+ zListMediaQuery,
1913
+ zListMediaResponse,
1914
+ zListPostsQuery,
1915
+ zListPostsResponse,
1916
+ zListWorkspacesResponse,
1917
+ zMedia,
1918
+ zMediaListResponse,
1919
+ zMediaSource,
1920
+ zMediaType,
1921
+ zPagination,
1922
+ zPlatformSpecificSettings,
1923
+ zPost,
1924
+ zPostAccount,
1925
+ zPostOverrides,
1926
+ zPostStatus,
1927
+ zPostsResponse,
1928
+ zRemovePostAccountPath,
1929
+ zRemovePostAccountResponse,
1930
+ zSocialPlatform,
1931
+ zSuccessMessage,
1932
+ zThreadsPlatformSpecificSettings,
1933
+ zTikTokCreatorInfoResponse,
1934
+ zTikTokPlatformSpecificSettings,
1935
+ zTwitterPlatformSpecificSettings,
1936
+ zUpdatePostBody,
1937
+ zUpdatePostPath,
1938
+ zUpdatePostRequest,
1939
+ zUpdatePostResponse,
1940
+ zUploadMediaBody,
1941
+ zUploadMediaRequest,
1942
+ zUploadMediaResponse,
1943
+ zWorkspace,
1944
+ zWorkspacesResponse,
1945
+ zYouTubePlatformSpecificSettings
1946
+ };
1947
+ //# sourceMappingURL=index.js.map