@rolino/contracts 0.1.0 → 0.3.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  // src/index.ts
2
2
  import { z } from "zod";
3
3
  var API_VERSION = "v1";
4
- var CONTRACT_VERSION = "0.12.0";
4
+ var CONTRACT_VERSION = "0.14.0";
5
5
  var RequestMetadataSchema = z.object({
6
6
  requestId: z.string().min(1)
7
7
  });
@@ -187,9 +187,11 @@ var PlatformPostStatusSchema = z.enum([
187
187
  ]);
188
188
  var PostMediaSchema = z.object({
189
189
  id: z.string().min(1),
190
+ assetId: z.string().min(1).nullable().optional(),
190
191
  type: z.enum(["IMAGE", "VIDEO"]),
191
192
  url: z.string().url(),
192
193
  mimeType: z.string().min(1),
194
+ sizeBytes: z.number().int().positive().nullable().optional(),
193
195
  width: z.number().int().positive().nullable(),
194
196
  height: z.number().int().positive().nullable(),
195
197
  durationMs: z.number().int().nonnegative().nullable(),
@@ -244,54 +246,23 @@ var MediaAssetUploadCompleteInputSchema = MediaAssetUploadInputSchema.extend({
244
246
  durationMs: z.number().int().nonnegative().max(864e5).nullable().optional()
245
247
  }).strict();
246
248
  var MediaAssetResponseSchema = successEnvelopeSchema(MediaAssetSchema);
247
- var PostDestinationSchema = z.object({
248
- provider: z.enum(["INSTAGRAM", "TIKTOK", "YOUTUBE", "BLUESKY"]),
249
- status: PlatformPostStatusSchema,
250
- captionOverride: z.string().nullable(),
251
- scheduledAt: z.string().datetime().nullable(),
252
- publishedAt: z.string().datetime().nullable(),
253
- remoteUrl: z.string().url().nullable(),
254
- attemptCount: z.number().int().nonnegative()
255
- });
256
249
  var PublishingProviderSchema = z.enum([
257
250
  "INSTAGRAM",
258
251
  "TIKTOK",
259
252
  "YOUTUBE",
260
- "BLUESKY"
253
+ "BLUESKY",
254
+ "LINKEDIN"
261
255
  ]);
262
256
  var PUBLISHING_PROVIDER_COUNT = PublishingProviderSchema.options.length;
263
- var PostSchema = z.object({
264
- id: z.string().min(1),
265
- projectId: z.string().min(1),
266
- version: z.number().int().positive(),
267
- campaign: z.object({
268
- id: z.string().min(1),
269
- title: z.string().min(1)
270
- }).nullable(),
271
- caption: z.string(),
272
- status: PostStatusSchema,
257
+ var PostDestinationSchema = z.object({
258
+ provider: PublishingProviderSchema,
259
+ status: PlatformPostStatusSchema,
260
+ captionOverride: z.string().nullable(),
273
261
  scheduledAt: z.string().datetime().nullable(),
274
- timezone: z.string().nullable(),
275
262
  publishedAt: z.string().datetime().nullable(),
276
- createdAt: z.string().datetime(),
277
- updatedAt: z.string().datetime(),
278
- media: z.array(PostMediaSchema),
279
- destinations: z.array(PostDestinationSchema)
280
- });
281
- var PostListQuerySchema = z.object({
282
- limit: z.coerce.number().int().min(1).max(100).default(50),
283
- cursor: z.string().min(1).optional(),
284
- status: PostStatusSchema.optional()
285
- });
286
- var PostListDataSchema = z.object({
287
- items: z.array(PostSchema),
288
- page: z.object({
289
- limit: z.number().int().min(1).max(100),
290
- nextCursor: z.string().min(1).nullable()
291
- })
263
+ remoteUrl: z.string().url().nullable(),
264
+ attemptCount: z.number().int().nonnegative()
292
265
  });
293
- var PostListResponseSchema = successEnvelopeSchema(PostListDataSchema);
294
- var PostResponseSchema = successEnvelopeSchema(PostSchema);
295
266
  var TikTokPostSettingsSchema = z.object({
296
267
  postMode: z.enum(["DIRECT_POST", "MEDIA_UPLOAD"]).default("DIRECT_POST"),
297
268
  privacyLevel: z.string().trim().min(1).max(100).nullable().default(null),
@@ -305,6 +276,91 @@ var TikTokPostSettingsSchema = z.object({
305
276
  videoCoverTimestampMs: z.number().int().nonnegative().nullable().default(null),
306
277
  consentedAt: z.union([z.string().datetime(), z.literal("")]).default("")
307
278
  }).strict();
279
+ var TikTokDraftSettingsSchema = z.object({
280
+ postMode: z.enum(["DIRECT_POST", "MEDIA_UPLOAD"]).optional(),
281
+ privacyLevel: z.string().trim().min(1).max(100).nullable().optional(),
282
+ allowComment: z.boolean().optional(),
283
+ allowDuet: z.boolean().optional(),
284
+ allowStitch: z.boolean().optional(),
285
+ commercialContentEnabled: z.boolean().optional(),
286
+ promotesOwnBrand: z.boolean().optional(),
287
+ promotesThirdParty: z.boolean().optional(),
288
+ isAiGenerated: z.boolean().optional(),
289
+ videoCoverTimestampMs: z.number().int().nonnegative().nullable().optional(),
290
+ reviewed: z.boolean().optional(),
291
+ consentedAt: z.union([z.string().datetime(), z.literal("")]).optional()
292
+ }).strict().superRefine((input, context) => {
293
+ const requestsReview = input.reviewed === true || Boolean(input.consentedAt);
294
+ if (input.postMode === "MEDIA_UPLOAD") {
295
+ if (input.privacyLevel != null || input.allowComment === true || input.allowDuet === true || input.allowStitch === true || input.commercialContentEnabled === true || input.promotesOwnBrand === true || input.promotesThirdParty === true || input.isAiGenerated === true || input.videoCoverTimestampMs != null) {
296
+ context.addIssue({
297
+ code: "custom",
298
+ message: "TikTok inbox drafts do not apply direct-post visibility, interaction, disclosure, AI, or cover settings."
299
+ });
300
+ }
301
+ return;
302
+ }
303
+ if (!requestsReview) return;
304
+ if (!input.postMode) {
305
+ context.addIssue({
306
+ code: "custom",
307
+ path: ["postMode"],
308
+ message: "Choose TikTok direct publishing or inbox draft delivery explicitly."
309
+ });
310
+ return;
311
+ }
312
+ const requiredBooleanFields = [
313
+ "allowComment",
314
+ "allowDuet",
315
+ "allowStitch",
316
+ "commercialContentEnabled",
317
+ "promotesOwnBrand",
318
+ "promotesThirdParty",
319
+ "isAiGenerated"
320
+ ];
321
+ if (!input.privacyLevel) {
322
+ context.addIssue({
323
+ code: "custom",
324
+ path: ["privacyLevel"],
325
+ message: "Choose TikTok visibility explicitly before reviewing the settings."
326
+ });
327
+ }
328
+ for (const field of requiredBooleanFields) {
329
+ if (input[field] === void 0) {
330
+ context.addIssue({
331
+ code: "custom",
332
+ path: [field],
333
+ message: "Choose yes or no explicitly before reviewing TikTok settings."
334
+ });
335
+ }
336
+ }
337
+ if (input.commercialContentEnabled === true && input.promotesOwnBrand !== true && input.promotesThirdParty !== true) {
338
+ context.addIssue({
339
+ code: "custom",
340
+ path: ["commercialContentEnabled"],
341
+ message: "Commercial TikTok content must identify own-brand or third-party promotion."
342
+ });
343
+ }
344
+ if (input.commercialContentEnabled === false && (input.promotesOwnBrand === true || input.promotesThirdParty === true)) {
345
+ context.addIssue({
346
+ code: "custom",
347
+ path: ["commercialContentEnabled"],
348
+ message: "Promotion declarations require commercial content to be enabled."
349
+ });
350
+ }
351
+ }).transform((input) => ({
352
+ postMode: input.postMode ?? "DIRECT_POST",
353
+ privacyLevel: input.privacyLevel ?? null,
354
+ allowComment: input.allowComment ?? false,
355
+ allowDuet: input.allowDuet ?? false,
356
+ allowStitch: input.allowStitch ?? false,
357
+ commercialContentEnabled: input.commercialContentEnabled ?? false,
358
+ promotesOwnBrand: input.promotesOwnBrand ?? false,
359
+ promotesThirdParty: input.promotesThirdParty ?? false,
360
+ isAiGenerated: input.isAiGenerated ?? false,
361
+ videoCoverTimestampMs: input.videoCoverTimestampMs ?? null,
362
+ reviewed: input.reviewed === true || Boolean(input.consentedAt)
363
+ }));
308
364
  function youtubeTagLength(tags) {
309
365
  return tags.reduce((total, tag, index) => total + (index ? 1 : 0) + tag.length + (tag.includes(" ") ? 2 : 0), 0);
310
366
  }
@@ -326,6 +382,43 @@ var YouTubePostSettingsSchema = z.object({
326
382
  "YouTube tags exceed the 500-character aggregate limit."
327
383
  ).default([])
328
384
  }).strict();
385
+ var PostProviderSettingsSchema = z.object({
386
+ TIKTOK: TikTokPostSettingsSchema.nullable().optional(),
387
+ YOUTUBE: YouTubePostSettingsSchema.nullable().optional()
388
+ }).strict().default({});
389
+ var PostSchema = z.object({
390
+ id: z.string().min(1),
391
+ projectId: z.string().min(1),
392
+ version: z.number().int().positive(),
393
+ campaign: z.object({
394
+ id: z.string().min(1),
395
+ title: z.string().min(1)
396
+ }).nullable(),
397
+ caption: z.string(),
398
+ status: PostStatusSchema,
399
+ scheduledAt: z.string().datetime().nullable(),
400
+ timezone: z.string().nullable(),
401
+ publishedAt: z.string().datetime().nullable(),
402
+ createdAt: z.string().datetime(),
403
+ updatedAt: z.string().datetime(),
404
+ media: z.array(PostMediaSchema),
405
+ destinations: z.array(PostDestinationSchema),
406
+ providerSettings: PostProviderSettingsSchema.optional()
407
+ });
408
+ var PostListQuerySchema = z.object({
409
+ limit: z.coerce.number().int().min(1).max(100).default(50),
410
+ cursor: z.string().min(1).optional(),
411
+ status: PostStatusSchema.optional()
412
+ });
413
+ var PostListDataSchema = z.object({
414
+ items: z.array(PostSchema),
415
+ page: z.object({
416
+ limit: z.number().int().min(1).max(100),
417
+ nextCursor: z.string().min(1).nullable()
418
+ })
419
+ });
420
+ var PostListResponseSchema = successEnvelopeSchema(PostListDataSchema);
421
+ var PostResponseSchema = successEnvelopeSchema(PostSchema);
329
422
  var blueskyGraphemeSegmenter = new Intl.Segmenter("en", {
330
423
  granularity: "grapheme"
331
424
  });
@@ -338,24 +431,27 @@ var YouTubeDescriptionSchema = z.string().max(5e3).refine(
338
431
  (value) => utf8Encoder.encode(value).length <= 5e3,
339
432
  "YouTube descriptions cannot exceed 5,000 UTF-8 bytes."
340
433
  );
341
- var DraftCaptionOverridesSchema = z.object({
434
+ var DraftCaptionOverridesObjectSchema = z.object({
342
435
  INSTAGRAM: z.string().max(2200).nullable().optional(),
343
436
  TIKTOK: z.string().max(2200).nullable().optional(),
344
437
  YOUTUBE: YouTubeDescriptionSchema.nullable().optional(),
345
- BLUESKY: BlueskyCaptionSchema.nullable().optional()
346
- }).strict().default({});
438
+ BLUESKY: BlueskyCaptionSchema.nullable().optional(),
439
+ LINKEDIN: z.string().max(3e3).nullable().optional()
440
+ }).strict();
441
+ var DraftPlatformsSchema = z.array(PublishingProviderSchema).max(PUBLISHING_PROVIDER_COUNT).refine(
442
+ (providers) => new Set(providers).size === providers.length,
443
+ "Publishing destinations must be unique."
444
+ );
445
+ var DraftMediaAssetIdsSchema = z.array(z.string().trim().min(1).max(200)).max(10).refine(
446
+ (ids) => new Set(ids).size === ids.length,
447
+ "Media asset IDs must be unique."
448
+ );
347
449
  var DraftPostInputSchema = z.object({
348
- caption: z.string().max(2200).transform((value) => value.trim()).default(""),
349
- platforms: z.array(PublishingProviderSchema).max(PUBLISHING_PROVIDER_COUNT).refine(
350
- (providers) => new Set(providers).size === providers.length,
351
- "Publishing destinations must be unique."
352
- ).default([]),
353
- mediaAssetIds: z.array(z.string().trim().min(1).max(200)).max(10).refine(
354
- (ids) => new Set(ids).size === ids.length,
355
- "Media asset IDs must be unique."
356
- ).default([]),
357
- captionOverrides: DraftCaptionOverridesSchema,
358
- tiktokSettings: TikTokPostSettingsSchema.nullable().default(null),
450
+ caption: z.string().max(3e3).transform((value) => value.trim()).default(""),
451
+ platforms: DraftPlatformsSchema.default([]),
452
+ mediaAssetIds: DraftMediaAssetIdsSchema.default([]),
453
+ captionOverrides: DraftCaptionOverridesObjectSchema.default({}),
454
+ tiktokSettings: TikTokDraftSettingsSchema.nullable().default(null),
359
455
  youtubeSettings: YouTubePostSettingsSchema.nullable().default(null)
360
456
  }).strict().superRefine((input, context) => {
361
457
  if (input.caption.length === 0 && input.mediaAssetIds.length === 0) {
@@ -401,6 +497,32 @@ var DraftPostInputSchema = z.object({
401
497
  });
402
498
  }
403
499
  });
500
+ var DraftPostUpdateInputSchema = z.object({
501
+ caption: z.string().max(3e3).transform((value) => value.trim()).optional(),
502
+ platforms: DraftPlatformsSchema.optional(),
503
+ mediaAssetIds: DraftMediaAssetIdsSchema.optional(),
504
+ captionOverrides: DraftCaptionOverridesObjectSchema.optional(),
505
+ tiktokSettings: TikTokDraftSettingsSchema.nullable().optional(),
506
+ youtubeSettings: YouTubePostSettingsSchema.nullable().optional()
507
+ }).strict().superRefine((input, context) => {
508
+ if (Object.values(input).every((value) => value === void 0)) {
509
+ context.addIssue({ code: "custom", message: "Provide at least one draft field to update." });
510
+ }
511
+ if (input.platforms && input.tiktokSettings && !input.platforms.includes("TIKTOK")) {
512
+ context.addIssue({
513
+ code: "custom",
514
+ path: ["tiktokSettings"],
515
+ message: "TikTok settings require the TIKTOK destination."
516
+ });
517
+ }
518
+ if (input.platforms && input.youtubeSettings && !input.platforms.includes("YOUTUBE")) {
519
+ context.addIssue({
520
+ code: "custom",
521
+ path: ["youtubeSettings"],
522
+ message: "YouTube settings require the YOUTUBE destination."
523
+ });
524
+ }
525
+ });
404
526
  var IntegrationConnectionStatusSchema = z.enum([
405
527
  "PENDING",
406
528
  "CONNECTED",
@@ -443,6 +565,65 @@ var IntegrationHealthListDataSchema = z.object({
443
565
  var IntegrationHealthListResponseSchema = successEnvelopeSchema(
444
566
  IntegrationHealthListDataSchema
445
567
  );
568
+ var ProviderDeliveryOptionsProviderSchema = z.enum([
569
+ "TIKTOK",
570
+ "LINKEDIN"
571
+ ]);
572
+ var TikTokDeliveryOptionsSchema = z.object({
573
+ provider: z.literal("TIKTOK"),
574
+ account: z.object({
575
+ username: z.string().nullable(),
576
+ displayName: z.string().nullable(),
577
+ avatarUrl: z.string().url().nullable()
578
+ }),
579
+ allowedPostModes: z.array(z.enum(["DIRECT_POST", "MEDIA_UPLOAD"])).max(2).refine(
580
+ (items) => new Set(items).size === items.length,
581
+ "TikTok post modes must be unique."
582
+ ),
583
+ visibilityOptions: z.array(z.string().trim().min(1).max(100)).max(20).refine(
584
+ (items) => new Set(items).size === items.length,
585
+ "TikTok visibility options must be unique."
586
+ ),
587
+ interactions: z.object({
588
+ comment: z.object({ available: z.boolean() }),
589
+ duet: z.object({ available: z.boolean() }),
590
+ stitch: z.object({ available: z.boolean() })
591
+ }),
592
+ maxVideoDurationMs: z.number().int().positive().max(864e5).nullable(),
593
+ health: z.object({
594
+ status: ProviderHealthStatusSchema,
595
+ code: z.string().min(1),
596
+ message: z.string().min(1)
597
+ }),
598
+ checkedAt: z.string().datetime()
599
+ });
600
+ var LinkedInDeliveryOptionsSchema = z.object({
601
+ provider: z.literal("LINKEDIN"),
602
+ account: z.object({
603
+ displayName: z.string().nullable(),
604
+ avatarUrl: z.string().url().nullable()
605
+ }),
606
+ supportedPostTypes: z.array(z.enum(["TEXT", "SINGLE_IMAGE", "MULTI_IMAGE"])).length(3),
607
+ image: z.object({
608
+ maxItems: z.literal(10),
609
+ mimeTypes: z.tuple([z.literal("image/jpeg"), z.literal("image/png")]),
610
+ maxPixelsExclusive: z.literal(36152320),
611
+ maxBytes: z.literal(26214400)
612
+ }),
613
+ health: z.object({
614
+ status: ProviderHealthStatusSchema,
615
+ code: z.string().min(1),
616
+ message: z.string().min(1)
617
+ }),
618
+ checkedAt: z.string().datetime()
619
+ });
620
+ var ProviderDeliveryOptionsSchema = z.discriminatedUnion("provider", [
621
+ TikTokDeliveryOptionsSchema,
622
+ LinkedInDeliveryOptionsSchema
623
+ ]);
624
+ var ProviderDeliveryOptionsResponseSchema = successEnvelopeSchema(
625
+ ProviderDeliveryOptionsSchema
626
+ );
446
627
  var ReadinessStatusSchema = z.enum([
447
628
  "checking",
448
629
  "pass",
@@ -667,10 +848,12 @@ export {
667
848
  CliAuthorizationRevokeDataSchema,
668
849
  CliAuthorizationRevokeResponseSchema,
669
850
  DraftPostInputSchema,
851
+ DraftPostUpdateInputSchema,
670
852
  IntegrationConnectionStatusSchema,
671
853
  IntegrationHealthListDataSchema,
672
854
  IntegrationHealthListResponseSchema,
673
855
  IntegrationHealthSchema,
856
+ LinkedInDeliveryOptionsSchema,
674
857
  MediaAssetListDataSchema,
675
858
  MediaAssetListQuerySchema,
676
859
  MediaAssetListResponseSchema,
@@ -687,6 +870,7 @@ export {
687
870
  PostListQuerySchema,
688
871
  PostListResponseSchema,
689
872
  PostMediaSchema,
873
+ PostProviderSettingsSchema,
690
874
  PostPublishExecuteInputSchema,
691
875
  PostPublishInputSchema,
692
876
  PostPublishPreviewResponseSchema,
@@ -711,11 +895,16 @@ export {
711
895
  ProjectResponseSchema,
712
896
  ProjectSchema,
713
897
  ProjectTypeSchema,
898
+ ProviderDeliveryOptionsProviderSchema,
899
+ ProviderDeliveryOptionsResponseSchema,
900
+ ProviderDeliveryOptionsSchema,
714
901
  ProviderHealthStatusSchema,
715
902
  PublishingProviderSchema,
716
903
  ReadinessActionSchema,
717
904
  ReadinessStatusSchema,
718
905
  RequestMetadataSchema,
906
+ TikTokDeliveryOptionsSchema,
907
+ TikTokDraftSettingsSchema,
719
908
  TikTokPostSettingsSchema,
720
909
  WhoAmIResponseSchema,
721
910
  YouTubePostSettingsSchema,