← Public packages
@kentcdodds/linkedin
Headless helpers for LinkedIn identity, requests, and guarded posting using the saved linkedin OAuth integration.
src/create-post-input.ts
93 lines · 2.5 KB · TypeScriptimport {
ValidationError,
any,
boolean,
object,
optional,
parse,
string,
} from 'remix/data-schema'
import { formatSchemaValidationError } from './schema-input-errors.ts'
import type { CreatePostInput, JsonRecord, LinkedInVisibility } from './types.ts'
const KNOWN_KEYS = [
'commentary',
'text',
'message',
'body',
'content',
'author',
'visibility',
'distribution',
'isReshareDisabledByAuthor',
'dryRun',
'confirm',
] as const
const HINT =
`Pass commentary (aliases: text, message, body) plus optional author/visibility/content/distribution. ` +
`Unknown top-level keys are rejected (no silent drop). ` +
`For structured LinkedIn content, use the \`content\` object — do not invent reply/parent aliases here.`
const CreatePostInputSchema = object(
{
commentary: optional(string()),
text: optional(string()),
message: optional(string()),
body: optional(string()),
content: optional(any()), // LinkedIn API content bag (controlled extension)
author: optional(string()),
visibility: optional(string()),
distribution: optional(any()),
isReshareDisabledByAuthor: optional(boolean()),
dryRun: optional(boolean()),
confirm: optional(boolean()),
},
{ unknownKeys: 'error' },
).transform((raw): CreatePostInput => {
const commentary =
[raw.commentary, raw.text, raw.message, raw.body]
.find((v) => typeof v === 'string' && v.trim().length > 0)
?.trim()
const content =
raw.content && typeof raw.content === 'object' && !Array.isArray(raw.content)
? (raw.content as JsonRecord)
: undefined
const distribution =
raw.distribution && typeof raw.distribution === 'object' && !Array.isArray(raw.distribution)
? (raw.distribution as JsonRecord)
: undefined
return {
commentary,
text: commentary,
author: raw.author,
visibility: raw.visibility as LinkedInVisibility | undefined,
content,
distribution,
isReshareDisabledByAuthor: raw.isReshareDisabledByAuthor,
dryRun: raw.dryRun,
confirm: raw.confirm,
}
})
export function parseCreatePostInput(input: unknown): CreatePostInput {
try {
const normalized = parse(CreatePostInputSchema, input ?? {})
if (!normalized.commentary?.trim()) {
throw new Error(
'create-post requires commentary (aliases: text, message, body).',
)
}
return normalized
} catch (error) {
if (error instanceof ValidationError) {
throw formatSchemaValidationError(error, {
surface: 'create-post',
knownKeys: KNOWN_KEYS,
hint: HINT,
input,
})
}
throw error
}
}