@postrun/react 2.0.0 → 2.1.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.cjs +7 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +53 -2
- package/dist/index.d.ts +53 -2
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -3,7 +3,7 @@ import { ReactNode, CSSProperties } from 'react';
|
|
|
3
3
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
4
4
|
import { QueryClient, QueryKey } from '@tanstack/react-query';
|
|
5
5
|
import { PostrunClient, ListProfilesQuery, DiscoverableAccountList, Connection, ConnectionKind, ConnectionStatus, ListMediaQuery, ListPostsQuery, ConnectablePlatform, MediaResource, MediaTarget, MediaKind, Metadata, ComposePostInput, PostValidation, XPostVariant, LinkedInPostVariant } from '@postrun/js';
|
|
6
|
-
export { PostValidation, ValidationIssue } from '@postrun/js';
|
|
6
|
+
export { PostValidation, PostVariant, PostVariantError, ValidationIssue } from '@postrun/js';
|
|
7
7
|
import { TwitterComponents } from 'react-tweet';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -1181,6 +1181,25 @@ declare function usePost(id: string, options?: LiveOptions): _tanstack_react_que
|
|
|
1181
1181
|
* variant set from `{ content, channels }` (per the `buildCreatePost` rules), and
|
|
1182
1182
|
* sends it — the customer never assembles variants or passes a `connection_id`.
|
|
1183
1183
|
* `connectedChannels` is the set of posting platforms this profile can reach.
|
|
1184
|
+
*
|
|
1185
|
+
* ## Reading the publish outcome (do NOT stop at "it returned")
|
|
1186
|
+
* On `publish: 'now'` the API returns the created post with a rollup `status` and
|
|
1187
|
+
* a per-variant `status` + typed `error`. A 201 does NOT mean every platform
|
|
1188
|
+
* published — one can silently fail while another succeeds. Surface the outcome
|
|
1189
|
+
* via the derived fields, never assume success from a resolved `create`:
|
|
1190
|
+
*
|
|
1191
|
+
* - **`status`** — the rollup (`published | partially_published | failed |
|
|
1192
|
+
* draft | scheduled`), `undefined` until the first `create` resolves.
|
|
1193
|
+
* - **`isPublished`** — `true` ONLY when `status === 'published'`. This is the
|
|
1194
|
+
* one "fully published" state; `partially_published` and `failed` are NOT
|
|
1195
|
+
* success. Branch on this, not on the promise resolving.
|
|
1196
|
+
* - **`failedVariants`** — the variants that failed, each with its typed
|
|
1197
|
+
* `error` (`{ code, message }`); `[]` when none. Render "X failed: <message>".
|
|
1198
|
+
*
|
|
1199
|
+
* `create` still resolves with the FULL `Post` (read everything if you need to),
|
|
1200
|
+
* and it NEVER throws on a failed/partial publish — a throw would discard the
|
|
1201
|
+
* platforms that DID publish. A transport error (network / 4xx) still surfaces
|
|
1202
|
+
* via `error` (and rejects `create`), exactly as before.
|
|
1184
1203
|
*/
|
|
1185
1204
|
declare function useCreatePost(profileId: string): {
|
|
1186
1205
|
create: _tanstack_react_query.UseMutateAsyncFunction<{
|
|
@@ -1280,6 +1299,38 @@ declare function useCreatePost(profileId: string): {
|
|
|
1280
1299
|
executed: boolean;
|
|
1281
1300
|
} | undefined;
|
|
1282
1301
|
reset: () => void;
|
|
1302
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed" | undefined;
|
|
1303
|
+
isPublished: boolean;
|
|
1304
|
+
failedVariants: {
|
|
1305
|
+
id: string;
|
|
1306
|
+
object: "post_variant";
|
|
1307
|
+
connection_id: string | null;
|
|
1308
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
1309
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
1310
|
+
body: string | null;
|
|
1311
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
1312
|
+
settings: {
|
|
1313
|
+
[key: string]: unknown;
|
|
1314
|
+
};
|
|
1315
|
+
schedule_at: string | null;
|
|
1316
|
+
result: {
|
|
1317
|
+
platform_post_id: string;
|
|
1318
|
+
permalink: string | null;
|
|
1319
|
+
published_at: string;
|
|
1320
|
+
} | null;
|
|
1321
|
+
error: {
|
|
1322
|
+
code: string;
|
|
1323
|
+
message: string;
|
|
1324
|
+
} | null;
|
|
1325
|
+
media: Array<{
|
|
1326
|
+
media_id: string;
|
|
1327
|
+
position: number;
|
|
1328
|
+
crop_box: {
|
|
1329
|
+
[key: string]: unknown;
|
|
1330
|
+
} | null;
|
|
1331
|
+
alt_text_override: string | null;
|
|
1332
|
+
}>;
|
|
1333
|
+
}[];
|
|
1283
1334
|
isReady: boolean;
|
|
1284
1335
|
connectedChannels: ("x" | "linkedin" | "facebook_page" | "instagram" | "tiktok")[];
|
|
1285
1336
|
};
|
|
@@ -1300,7 +1351,7 @@ declare function useValidatePost(profileId: string): {
|
|
|
1300
1351
|
validate: (input: Omit<ComposePostInput, "profileId">) => Promise<PostValidation>;
|
|
1301
1352
|
publishable: boolean | undefined;
|
|
1302
1353
|
issues: {
|
|
1303
|
-
code: "unauthorized" | "forbidden" | "not_found" | "conflict" | "validation_failed" | "rate_limited" | "internal_error" | "idempotency_key_invalid" | "idempotency_key_reused" | "idempotency_request_in_progress" | "account_not_available" | "connection_reauth_required" | "connection_not_pending" | "not_implemented" | "connection_discovery_failed" | "media_processing" | "not_publishable" | "invalid_connection" | "invalid_media" | "profile_scope_invalid" | "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_format_indeterminate" | "media_count_invalid" | "body_too_long" | "content_missing" | "content_conflict" | "content_incomplete" | "content_kind_mismatch" | "media_type_mismatch" | "tag_limit_exceeded" | "reel_field_on_non_reel" | "field_placement_invalid" | "media_not_ready" | "media_failed" | "media_unsupported" | "media_kind_mismatch" | "variant_unparseable" | "publishing_unavailable" | "x_duplicate_content" | "x_not_authorized" | "x_rate_limited" | "x_publish_failed" | "x_media_upload_failed" | "linkedin_duplicate_content" | "linkedin_auth_expired" | "linkedin_permission_denied" | "linkedin_media_processing" | "linkedin_media_upload_failed" | "linkedin_publish_failed" | "instagram_media_processing" | "instagram_container_expired" | "instagram_container_failed" | "instagram_rate_limited" | "instagram_not_authorized" | "instagram_publish_failed" | "facebook_reel_processing" | "facebook_reel_failed" | "facebook_rate_limited" | "facebook_not_authorized" | "facebook_publish_failed" | "tiktok_privacy_not_allowed" | "tiktok_duration_exceeds_max" | "tiktok_media_processing" | "tiktok_not_authorized" | "tiktok_rate_limited" | "tiktok_publish_failed" | "connection_platform_mismatch" | "connection_removed";
|
|
1354
|
+
code: "unauthorized" | "forbidden" | "not_found" | "conflict" | "validation_failed" | "rate_limited" | "internal_error" | "idempotency_key_invalid" | "idempotency_key_reused" | "idempotency_request_in_progress" | "account_not_available" | "connection_reauth_required" | "connection_not_pending" | "not_implemented" | "connection_discovery_failed" | "media_processing" | "not_publishable" | "invalid_connection" | "invalid_media" | "profile_scope_invalid" | "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_format_indeterminate" | "media_count_invalid" | "body_too_long" | "content_missing" | "content_conflict" | "content_incomplete" | "content_kind_mismatch" | "media_type_mismatch" | "tag_limit_exceeded" | "reel_field_on_non_reel" | "field_placement_invalid" | "media_not_ready" | "media_failed" | "media_unsupported" | "media_kind_mismatch" | "variant_unparseable" | "publishing_unavailable" | "x_duplicate_content" | "x_not_authorized" | "x_access_not_permitted" | "x_rate_limited" | "x_publish_failed" | "x_media_upload_failed" | "linkedin_duplicate_content" | "linkedin_auth_expired" | "linkedin_permission_denied" | "linkedin_media_processing" | "linkedin_media_upload_failed" | "linkedin_publish_failed" | "instagram_media_processing" | "instagram_container_expired" | "instagram_container_failed" | "instagram_rate_limited" | "instagram_not_authorized" | "instagram_publish_failed" | "facebook_reel_processing" | "facebook_reel_failed" | "facebook_rate_limited" | "facebook_not_authorized" | "facebook_publish_failed" | "tiktok_privacy_not_allowed" | "tiktok_duration_exceeds_max" | "tiktok_media_processing" | "tiktok_not_authorized" | "tiktok_rate_limited" | "tiktok_publish_failed" | "connection_platform_mismatch" | "connection_removed";
|
|
1304
1355
|
message: string;
|
|
1305
1356
|
hint?: string;
|
|
1306
1357
|
allowed?: Array<string>;
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { ReactNode, CSSProperties } from 'react';
|
|
|
3
3
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
4
4
|
import { QueryClient, QueryKey } from '@tanstack/react-query';
|
|
5
5
|
import { PostrunClient, ListProfilesQuery, DiscoverableAccountList, Connection, ConnectionKind, ConnectionStatus, ListMediaQuery, ListPostsQuery, ConnectablePlatform, MediaResource, MediaTarget, MediaKind, Metadata, ComposePostInput, PostValidation, XPostVariant, LinkedInPostVariant } from '@postrun/js';
|
|
6
|
-
export { PostValidation, ValidationIssue } from '@postrun/js';
|
|
6
|
+
export { PostValidation, PostVariant, PostVariantError, ValidationIssue } from '@postrun/js';
|
|
7
7
|
import { TwitterComponents } from 'react-tweet';
|
|
8
8
|
|
|
9
9
|
/**
|
|
@@ -1181,6 +1181,25 @@ declare function usePost(id: string, options?: LiveOptions): _tanstack_react_que
|
|
|
1181
1181
|
* variant set from `{ content, channels }` (per the `buildCreatePost` rules), and
|
|
1182
1182
|
* sends it — the customer never assembles variants or passes a `connection_id`.
|
|
1183
1183
|
* `connectedChannels` is the set of posting platforms this profile can reach.
|
|
1184
|
+
*
|
|
1185
|
+
* ## Reading the publish outcome (do NOT stop at "it returned")
|
|
1186
|
+
* On `publish: 'now'` the API returns the created post with a rollup `status` and
|
|
1187
|
+
* a per-variant `status` + typed `error`. A 201 does NOT mean every platform
|
|
1188
|
+
* published — one can silently fail while another succeeds. Surface the outcome
|
|
1189
|
+
* via the derived fields, never assume success from a resolved `create`:
|
|
1190
|
+
*
|
|
1191
|
+
* - **`status`** — the rollup (`published | partially_published | failed |
|
|
1192
|
+
* draft | scheduled`), `undefined` until the first `create` resolves.
|
|
1193
|
+
* - **`isPublished`** — `true` ONLY when `status === 'published'`. This is the
|
|
1194
|
+
* one "fully published" state; `partially_published` and `failed` are NOT
|
|
1195
|
+
* success. Branch on this, not on the promise resolving.
|
|
1196
|
+
* - **`failedVariants`** — the variants that failed, each with its typed
|
|
1197
|
+
* `error` (`{ code, message }`); `[]` when none. Render "X failed: <message>".
|
|
1198
|
+
*
|
|
1199
|
+
* `create` still resolves with the FULL `Post` (read everything if you need to),
|
|
1200
|
+
* and it NEVER throws on a failed/partial publish — a throw would discard the
|
|
1201
|
+
* platforms that DID publish. A transport error (network / 4xx) still surfaces
|
|
1202
|
+
* via `error` (and rejects `create`), exactly as before.
|
|
1184
1203
|
*/
|
|
1185
1204
|
declare function useCreatePost(profileId: string): {
|
|
1186
1205
|
create: _tanstack_react_query.UseMutateAsyncFunction<{
|
|
@@ -1280,6 +1299,38 @@ declare function useCreatePost(profileId: string): {
|
|
|
1280
1299
|
executed: boolean;
|
|
1281
1300
|
} | undefined;
|
|
1282
1301
|
reset: () => void;
|
|
1302
|
+
status: "draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed" | undefined;
|
|
1303
|
+
isPublished: boolean;
|
|
1304
|
+
failedVariants: {
|
|
1305
|
+
id: string;
|
|
1306
|
+
object: "post_variant";
|
|
1307
|
+
connection_id: string | null;
|
|
1308
|
+
platform: "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
|
|
1309
|
+
post_type: "text" | "single_image" | "multi_image" | "video" | "reel" | "carousel";
|
|
1310
|
+
body: string | null;
|
|
1311
|
+
status: "draft" | "scheduled" | "publishing" | "published" | "failed";
|
|
1312
|
+
settings: {
|
|
1313
|
+
[key: string]: unknown;
|
|
1314
|
+
};
|
|
1315
|
+
schedule_at: string | null;
|
|
1316
|
+
result: {
|
|
1317
|
+
platform_post_id: string;
|
|
1318
|
+
permalink: string | null;
|
|
1319
|
+
published_at: string;
|
|
1320
|
+
} | null;
|
|
1321
|
+
error: {
|
|
1322
|
+
code: string;
|
|
1323
|
+
message: string;
|
|
1324
|
+
} | null;
|
|
1325
|
+
media: Array<{
|
|
1326
|
+
media_id: string;
|
|
1327
|
+
position: number;
|
|
1328
|
+
crop_box: {
|
|
1329
|
+
[key: string]: unknown;
|
|
1330
|
+
} | null;
|
|
1331
|
+
alt_text_override: string | null;
|
|
1332
|
+
}>;
|
|
1333
|
+
}[];
|
|
1283
1334
|
isReady: boolean;
|
|
1284
1335
|
connectedChannels: ("x" | "linkedin" | "facebook_page" | "instagram" | "tiktok")[];
|
|
1285
1336
|
};
|
|
@@ -1300,7 +1351,7 @@ declare function useValidatePost(profileId: string): {
|
|
|
1300
1351
|
validate: (input: Omit<ComposePostInput, "profileId">) => Promise<PostValidation>;
|
|
1301
1352
|
publishable: boolean | undefined;
|
|
1302
1353
|
issues: {
|
|
1303
|
-
code: "unauthorized" | "forbidden" | "not_found" | "conflict" | "validation_failed" | "rate_limited" | "internal_error" | "idempotency_key_invalid" | "idempotency_key_reused" | "idempotency_request_in_progress" | "account_not_available" | "connection_reauth_required" | "connection_not_pending" | "not_implemented" | "connection_discovery_failed" | "media_processing" | "not_publishable" | "invalid_connection" | "invalid_media" | "profile_scope_invalid" | "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_format_indeterminate" | "media_count_invalid" | "body_too_long" | "content_missing" | "content_conflict" | "content_incomplete" | "content_kind_mismatch" | "media_type_mismatch" | "tag_limit_exceeded" | "reel_field_on_non_reel" | "field_placement_invalid" | "media_not_ready" | "media_failed" | "media_unsupported" | "media_kind_mismatch" | "variant_unparseable" | "publishing_unavailable" | "x_duplicate_content" | "x_not_authorized" | "x_rate_limited" | "x_publish_failed" | "x_media_upload_failed" | "linkedin_duplicate_content" | "linkedin_auth_expired" | "linkedin_permission_denied" | "linkedin_media_processing" | "linkedin_media_upload_failed" | "linkedin_publish_failed" | "instagram_media_processing" | "instagram_container_expired" | "instagram_container_failed" | "instagram_rate_limited" | "instagram_not_authorized" | "instagram_publish_failed" | "facebook_reel_processing" | "facebook_reel_failed" | "facebook_rate_limited" | "facebook_not_authorized" | "facebook_publish_failed" | "tiktok_privacy_not_allowed" | "tiktok_duration_exceeds_max" | "tiktok_media_processing" | "tiktok_not_authorized" | "tiktok_rate_limited" | "tiktok_publish_failed" | "connection_platform_mismatch" | "connection_removed";
|
|
1354
|
+
code: "unauthorized" | "forbidden" | "not_found" | "conflict" | "validation_failed" | "rate_limited" | "internal_error" | "idempotency_key_invalid" | "idempotency_key_reused" | "idempotency_request_in_progress" | "account_not_available" | "connection_reauth_required" | "connection_not_pending" | "not_implemented" | "connection_discovery_failed" | "media_processing" | "not_publishable" | "invalid_connection" | "invalid_media" | "profile_scope_invalid" | "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_format_indeterminate" | "media_count_invalid" | "body_too_long" | "content_missing" | "content_conflict" | "content_incomplete" | "content_kind_mismatch" | "media_type_mismatch" | "tag_limit_exceeded" | "reel_field_on_non_reel" | "field_placement_invalid" | "media_not_ready" | "media_failed" | "media_unsupported" | "media_kind_mismatch" | "variant_unparseable" | "publishing_unavailable" | "x_duplicate_content" | "x_not_authorized" | "x_access_not_permitted" | "x_rate_limited" | "x_publish_failed" | "x_media_upload_failed" | "linkedin_duplicate_content" | "linkedin_auth_expired" | "linkedin_permission_denied" | "linkedin_media_processing" | "linkedin_media_upload_failed" | "linkedin_publish_failed" | "instagram_media_processing" | "instagram_container_expired" | "instagram_container_failed" | "instagram_rate_limited" | "instagram_not_authorized" | "instagram_publish_failed" | "facebook_reel_processing" | "facebook_reel_failed" | "facebook_rate_limited" | "facebook_not_authorized" | "facebook_publish_failed" | "tiktok_privacy_not_allowed" | "tiktok_duration_exceeds_max" | "tiktok_media_processing" | "tiktok_not_authorized" | "tiktok_rate_limited" | "tiktok_publish_failed" | "connection_platform_mismatch" | "connection_removed";
|
|
1304
1355
|
message: string;
|
|
1305
1356
|
hint?: string;
|
|
1306
1357
|
allowed?: Array<string>;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createContext, memo, useMemo, useState, useEffect, Fragment as Fragment$1, useRef, createElement, useContext, useCallback } from 'react';
|
|
3
3
|
import { useInfiniteQuery, useQuery, useMutation, QueryClient } from '@tanstack/react-query';
|
|
4
|
-
import { createPostrunClient, profilesList, profilesGet, profilesCreate, profilesUpdate, profilesDelete, connectionsConnect, connectionsListByProfile, connectionsGet, connectionsListAccounts, connectionsSelect, connectionsDelete, mediaGet, mediaList, mediaUpdate, mediaDelete, postsList, postsGet, postsCreate, buildCreatePost, isPostPlatform, postsValidate, postsUpdate, postsDelete, mediaCreate, PostrunError } from '@postrun/js';
|
|
4
|
+
import { createPostrunClient, profilesList, profilesGet, profilesCreate, profilesUpdate, profilesDelete, connectionsConnect, connectionsListByProfile, connectionsGet, connectionsListAccounts, connectionsSelect, connectionsDelete, mediaGet, mediaList, mediaUpdate, mediaDelete, postsList, postsGet, postsCreate, buildCreatePost, isPostPlatform, failedVariants, isPublished, postsValidate, postsUpdate, postsDelete, mediaCreate, PostrunError } from '@postrun/js';
|
|
5
5
|
import Nango, { AuthError } from '@nangohq/frontend';
|
|
6
6
|
import pWaitFor, { TimeoutError } from 'p-wait-for';
|
|
7
7
|
import pLimit from 'p-limit';
|
|
@@ -878,12 +878,18 @@ function useCreatePost(profileId) {
|
|
|
878
878
|
},
|
|
879
879
|
queryClient
|
|
880
880
|
);
|
|
881
|
+
const post = mutation.data;
|
|
881
882
|
return {
|
|
882
883
|
create: mutation.mutateAsync,
|
|
883
884
|
isPending: mutation.isPending,
|
|
884
885
|
error: mutation.error,
|
|
885
|
-
data:
|
|
886
|
+
data: post,
|
|
886
887
|
reset: mutation.reset,
|
|
888
|
+
// Derived publish outcome (see the JSDoc above) — `undefined`/`false`/`[]`
|
|
889
|
+
// until the first create resolves; computed from the returned post only.
|
|
890
|
+
status: post?.status,
|
|
891
|
+
isPublished: post ? isPublished(post) : false,
|
|
892
|
+
failedVariants: post ? failedVariants(post) : [],
|
|
887
893
|
// The profile's connections must load before `create` can resolve a channel;
|
|
888
894
|
// gate on this so a call during loading isn't mislabeled "not connected".
|
|
889
895
|
isReady: connections.isSuccess,
|