@happyvertical/smrt-social 0.30.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/AGENTS.md +18 -0
- package/CLAUDE.md +1 -0
- package/LICENSE +7 -0
- package/README.md +94 -0
- package/dist/__smrt-register__.d.ts +2 -0
- package/dist/__smrt-register__.d.ts.map +1 -0
- package/dist/collections/index.d.ts +5 -0
- package/dist/collections/index.d.ts.map +1 -0
- package/dist/collections/oauth-state-collection.d.ts +9 -0
- package/dist/collections/oauth-state-collection.d.ts.map +1 -0
- package/dist/collections/social-account-collection.d.ts +9 -0
- package/dist/collections/social-account-collection.d.ts.map +1 -0
- package/dist/collections/social-post-analytics-snapshot-collection.d.ts +18 -0
- package/dist/collections/social-post-analytics-snapshot-collection.d.ts.map +1 -0
- package/dist/collections/social-post-collection.d.ts +32 -0
- package/dist/collections/social-post-collection.d.ts.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +824 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.json +3363 -0
- package/dist/oauth-state.d.ts +127 -0
- package/dist/oauth-state.d.ts.map +1 -0
- package/dist/server.d.ts +18 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +106 -0
- package/dist/server.js.map +1 -0
- package/dist/smrt-knowledge.json +1398 -0
- package/dist/social-account.d.ts +270 -0
- package/dist/social-account.d.ts.map +1 -0
- package/dist/social-post-analytics-snapshot.d.ts +40 -0
- package/dist/social-post-analytics-snapshot.d.ts.map +1 -0
- package/dist/social-post.d.ts +258 -0
- package/dist/social-post.d.ts.map +1 -0
- package/dist/svelte/components/SocialAccountSettings.svelte +243 -0
- package/dist/svelte/components/SocialAccountSettings.svelte.d.ts +15 -0
- package/dist/svelte/components/SocialAccountSettings.svelte.d.ts.map +1 -0
- package/dist/svelte/i18n.d.ts +9 -0
- package/dist/svelte/i18n.d.ts.map +1 -0
- package/dist/svelte/i18n.js +15 -0
- package/dist/svelte/index.d.ts +6 -0
- package/dist/svelte/index.d.ts.map +1 -0
- package/dist/svelte/index.js +2 -0
- package/dist/svelte/types.d.ts +16 -0
- package/dist/svelte/types.d.ts.map +1 -0
- package/dist/svelte/types.js +1 -0
- package/package.json +88 -0
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { SmrtObjectOptions, SmrtObject } from '@happyvertical/smrt-core';
|
|
2
|
+
import { SocialPlatformType } from './social-account.js';
|
|
3
|
+
/**
|
|
4
|
+
* OAuth state creation options
|
|
5
|
+
*/
|
|
6
|
+
export interface OAuthStateOptions extends SmrtObjectOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Platform being connected
|
|
9
|
+
*/
|
|
10
|
+
platform?: SocialPlatformType;
|
|
11
|
+
/**
|
|
12
|
+
* CSRF state token
|
|
13
|
+
*/
|
|
14
|
+
state?: string;
|
|
15
|
+
/**
|
|
16
|
+
* PKCE code verifier (for platforms that require it)
|
|
17
|
+
*/
|
|
18
|
+
codeVerifier?: string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Redirect URI used in the OAuth request
|
|
21
|
+
*/
|
|
22
|
+
redirectUri?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Requested OAuth scopes
|
|
25
|
+
*/
|
|
26
|
+
scopes?: string[];
|
|
27
|
+
/**
|
|
28
|
+
* When this state expires
|
|
29
|
+
*/
|
|
30
|
+
expiresAt?: Date;
|
|
31
|
+
/**
|
|
32
|
+
* Tenant ID for multi-tenant isolation
|
|
33
|
+
*/
|
|
34
|
+
tenantId?: string | null;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Temporary OAuth state for social account connection
|
|
38
|
+
*
|
|
39
|
+
* OAuthState stores temporary data during the OAuth flow to:
|
|
40
|
+
* - Verify callback requests match initiated requests (CSRF protection)
|
|
41
|
+
* - Store PKCE code verifier for code exchange
|
|
42
|
+
* - Track redirect URI and scopes for verification
|
|
43
|
+
*
|
|
44
|
+
* These records should be cleaned up after successful connection
|
|
45
|
+
* or after expiration.
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* import { OAuthState } from '@happyvertical/smrt-social';
|
|
50
|
+
*
|
|
51
|
+
* // Create state when initiating OAuth
|
|
52
|
+
* const state = new OAuthState({
|
|
53
|
+
* platform: 'youtube',
|
|
54
|
+
* state: crypto.randomUUID(),
|
|
55
|
+
* codeVerifier: generatePKCEVerifier(),
|
|
56
|
+
* redirectUri: 'https://app.example.com/oauth/callback',
|
|
57
|
+
* scopes: ['youtube.upload', 'youtube.readonly'],
|
|
58
|
+
* expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes
|
|
59
|
+
* });
|
|
60
|
+
* await state.save();
|
|
61
|
+
*
|
|
62
|
+
* // After successful callback, delete the state
|
|
63
|
+
* await state.delete();
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export declare class OAuthState extends SmrtObject {
|
|
67
|
+
/**
|
|
68
|
+
* Tenant ID for multi-tenant isolation
|
|
69
|
+
*/
|
|
70
|
+
tenantId: string | null;
|
|
71
|
+
/**
|
|
72
|
+
* Platform being connected
|
|
73
|
+
*/
|
|
74
|
+
platform: SocialPlatformType;
|
|
75
|
+
/**
|
|
76
|
+
* CSRF state token
|
|
77
|
+
* This is sent to the OAuth provider and verified on callback
|
|
78
|
+
*/
|
|
79
|
+
state: string;
|
|
80
|
+
/**
|
|
81
|
+
* PKCE code verifier
|
|
82
|
+
* Required for platforms using PKCE (YouTube, etc.)
|
|
83
|
+
*/
|
|
84
|
+
codeVerifier: string | null;
|
|
85
|
+
/**
|
|
86
|
+
* Redirect URI used in the OAuth request
|
|
87
|
+
* Must match on callback for verification
|
|
88
|
+
*/
|
|
89
|
+
redirectUri: string;
|
|
90
|
+
/**
|
|
91
|
+
* Requested OAuth scopes
|
|
92
|
+
*/
|
|
93
|
+
scopes: string[];
|
|
94
|
+
/**
|
|
95
|
+
* When this state expires
|
|
96
|
+
* States should be short-lived (10 minutes typical)
|
|
97
|
+
*/
|
|
98
|
+
expiresAt: Date;
|
|
99
|
+
constructor(options?: OAuthStateOptions);
|
|
100
|
+
/**
|
|
101
|
+
* Check if the state has expired
|
|
102
|
+
*/
|
|
103
|
+
get isExpired(): boolean;
|
|
104
|
+
/**
|
|
105
|
+
* Check if the state is still valid
|
|
106
|
+
*/
|
|
107
|
+
get isValid(): boolean;
|
|
108
|
+
/**
|
|
109
|
+
* Verify a callback state matches this record
|
|
110
|
+
*/
|
|
111
|
+
verifyState(callbackState: string): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Generate a new random state token
|
|
114
|
+
*/
|
|
115
|
+
static generateState(): string;
|
|
116
|
+
/**
|
|
117
|
+
* Generate a PKCE code verifier
|
|
118
|
+
* Returns a 43-128 character random string
|
|
119
|
+
*/
|
|
120
|
+
static generateCodeVerifier(): string;
|
|
121
|
+
/**
|
|
122
|
+
* Generate PKCE code challenge from verifier (S256 method)
|
|
123
|
+
* Note: This requires async crypto operations
|
|
124
|
+
*/
|
|
125
|
+
static generateCodeChallenge(verifier: string): Promise<string>;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=oauth-state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth-state.d.ts","sourceRoot":"","sources":["../src/oauth-state.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,UAAU,EAAQ,MAAM,0BAA0B,CAAC;AAE5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D;;OAEG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAE9B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAElB;;OAEG;IACH,SAAS,CAAC,EAAE,IAAI,CAAC;IAEjB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBASa,UAAW,SAAQ,UAAU;IACxC;;OAEG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IACH,QAAQ,EAAE,kBAAkB,CAAa;IAEzC;;;OAGG;IACH,KAAK,EAAE,MAAM,CAAM;IAEnB;;;OAGG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEnC;;;OAGG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAM;IAEtB;;;OAGG;IACH,SAAS,EAAE,IAAI,CAAyC;gBAE5C,OAAO,GAAE,iBAAsB;IAc3C;;OAEG;IACH,IAAI,SAAS,IAAI,OAAO,CAEvB;IAED;;OAEG;IACH,IAAI,OAAO,IAAI,OAAO,CAErB;IAED;;OAEG;IACH,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO;IAI3C;;OAEG;IACH,MAAM,CAAC,aAAa,IAAI,MAAM;IAI9B;;;OAGG;IACH,MAAM,CAAC,oBAAoB,IAAI,MAAM;IAQrC;;;OAGG;WACU,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAOtE"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { LinkBehavior, PublishMode, SocialPlatformType } from './social-account.js';
|
|
2
|
+
export type SocialAccountSetupMethod = 'oauth' | 'manual';
|
|
3
|
+
export interface SocialPlatformSetup {
|
|
4
|
+
platform: SocialPlatformType;
|
|
5
|
+
label: string;
|
|
6
|
+
setupMethod: SocialAccountSetupMethod;
|
|
7
|
+
postTypes: Array<'text' | 'link' | 'image' | 'video'>;
|
|
8
|
+
defaultLinkBehavior: LinkBehavior;
|
|
9
|
+
defaultPublishMode: PublishMode;
|
|
10
|
+
supportedPublishModes: PublishMode[];
|
|
11
|
+
requiredSecretFields: string[];
|
|
12
|
+
}
|
|
13
|
+
export declare const SOCIAL_PLATFORM_SETUPS: SocialPlatformSetup[];
|
|
14
|
+
export declare function getSocialPlatformSetup(platform: SocialPlatformType): SocialPlatformSetup;
|
|
15
|
+
export declare function getDefaultSocialAccountName(platform: SocialPlatformType, username?: string | null): string;
|
|
16
|
+
export declare function normalizeManualCredentials(platform: SocialPlatformType, values: Record<string, unknown>): Record<string, string>;
|
|
17
|
+
export declare function validateManualCredentials(platform: SocialPlatformType, values: Record<string, unknown>): string[];
|
|
18
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,WAAW,EACX,kBAAkB,EACnB,MAAM,qBAAqB,CAAC;AAE7B,MAAM,MAAM,wBAAwB,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE1D,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,kBAAkB,CAAC;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,wBAAwB,CAAC;IACtC,SAAS,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,CAAC;IACtD,mBAAmB,EAAE,YAAY,CAAC;IAClC,kBAAkB,EAAE,WAAW,CAAC;IAChC,qBAAqB,EAAE,WAAW,EAAE,CAAC;IACrC,oBAAoB,EAAE,MAAM,EAAE,CAAC;CAChC;AAED,eAAO,MAAM,sBAAsB,EAAE,mBAAmB,EA6DvD,CAAC;AAMF,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,kBAAkB,GAC3B,mBAAmB,CAMrB;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,kBAAkB,EAC5B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,GACvB,MAAM,CAGR;AAED,wBAAgB,0BAA0B,CACxC,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,kBAAkB,EAC5B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,EAAE,CAYV"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const SOCIAL_PLATFORM_SETUPS = [
|
|
2
|
+
{
|
|
3
|
+
platform: "youtube",
|
|
4
|
+
label: "YouTube",
|
|
5
|
+
setupMethod: "oauth",
|
|
6
|
+
postTypes: ["video"],
|
|
7
|
+
defaultLinkBehavior: "description",
|
|
8
|
+
defaultPublishMode: "private_or_scheduled",
|
|
9
|
+
supportedPublishModes: ["dry_run", "private_or_scheduled", "public"],
|
|
10
|
+
requiredSecretFields: ["clientId", "clientSecret", "accessToken"]
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
platform: "facebook",
|
|
14
|
+
label: "Facebook Page",
|
|
15
|
+
setupMethod: "oauth",
|
|
16
|
+
postTypes: ["text", "link", "image", "video"],
|
|
17
|
+
defaultLinkBehavior: "attachment",
|
|
18
|
+
defaultPublishMode: "private_or_scheduled",
|
|
19
|
+
supportedPublishModes: [
|
|
20
|
+
"dry_run",
|
|
21
|
+
"stage_remote",
|
|
22
|
+
"private_or_scheduled",
|
|
23
|
+
"public"
|
|
24
|
+
],
|
|
25
|
+
requiredSecretFields: ["accessToken", "pageId"]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
platform: "threads",
|
|
29
|
+
label: "Threads",
|
|
30
|
+
setupMethod: "oauth",
|
|
31
|
+
postTypes: ["text", "link", "image", "video"],
|
|
32
|
+
defaultLinkBehavior: "attachment",
|
|
33
|
+
defaultPublishMode: "stage_remote",
|
|
34
|
+
supportedPublishModes: ["dry_run", "stage_remote", "public"],
|
|
35
|
+
requiredSecretFields: ["accessToken", "userId"]
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
platform: "x",
|
|
39
|
+
label: "X",
|
|
40
|
+
setupMethod: "oauth",
|
|
41
|
+
postTypes: ["text", "link", "image", "video"],
|
|
42
|
+
defaultLinkBehavior: "inline",
|
|
43
|
+
defaultPublishMode: "dry_run",
|
|
44
|
+
supportedPublishModes: ["dry_run", "stage_remote", "public"],
|
|
45
|
+
requiredSecretFields: [
|
|
46
|
+
"apiKey",
|
|
47
|
+
"apiSecret",
|
|
48
|
+
"accessToken",
|
|
49
|
+
"accessSecret"
|
|
50
|
+
]
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
platform: "bluesky",
|
|
54
|
+
label: "Bluesky",
|
|
55
|
+
setupMethod: "manual",
|
|
56
|
+
postTypes: ["text", "link", "image"],
|
|
57
|
+
defaultLinkBehavior: "attachment",
|
|
58
|
+
defaultPublishMode: "dry_run",
|
|
59
|
+
supportedPublishModes: ["dry_run", "stage_remote", "public"],
|
|
60
|
+
requiredSecretFields: ["identifier", "password"]
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
const SOCIAL_PLATFORM_SETUP_BY_PLATFORM = new Map(
|
|
64
|
+
SOCIAL_PLATFORM_SETUPS.map((setup) => [setup.platform, setup])
|
|
65
|
+
);
|
|
66
|
+
function getSocialPlatformSetup(platform) {
|
|
67
|
+
const setup = SOCIAL_PLATFORM_SETUP_BY_PLATFORM.get(platform);
|
|
68
|
+
if (!setup) {
|
|
69
|
+
throw new Error(`Unsupported social platform: ${platform}`);
|
|
70
|
+
}
|
|
71
|
+
return setup;
|
|
72
|
+
}
|
|
73
|
+
function getDefaultSocialAccountName(platform, username) {
|
|
74
|
+
const setup = getSocialPlatformSetup(platform);
|
|
75
|
+
return username ? `${setup.label} ${username}` : setup.label;
|
|
76
|
+
}
|
|
77
|
+
function normalizeManualCredentials(platform, values) {
|
|
78
|
+
const setup = getSocialPlatformSetup(platform);
|
|
79
|
+
const credentials = {};
|
|
80
|
+
for (const field of setup.requiredSecretFields) {
|
|
81
|
+
const value = values[field];
|
|
82
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
83
|
+
credentials[field] = value.trim();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return credentials;
|
|
87
|
+
}
|
|
88
|
+
function validateManualCredentials(platform, values) {
|
|
89
|
+
const setup = getSocialPlatformSetup(platform);
|
|
90
|
+
const missing = [];
|
|
91
|
+
for (const field of setup.requiredSecretFields) {
|
|
92
|
+
const value = values[field];
|
|
93
|
+
if (typeof value !== "string" || value.trim() === "") {
|
|
94
|
+
missing.push(field);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return missing;
|
|
98
|
+
}
|
|
99
|
+
export {
|
|
100
|
+
SOCIAL_PLATFORM_SETUPS,
|
|
101
|
+
getDefaultSocialAccountName,
|
|
102
|
+
getSocialPlatformSetup,
|
|
103
|
+
normalizeManualCredentials,
|
|
104
|
+
validateManualCredentials
|
|
105
|
+
};
|
|
106
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sources":["../src/server.ts"],"sourcesContent":["import type {\n LinkBehavior,\n PublishMode,\n SocialPlatformType,\n} from './social-account.js';\n\nexport type SocialAccountSetupMethod = 'oauth' | 'manual';\n\nexport interface SocialPlatformSetup {\n platform: SocialPlatformType;\n label: string;\n setupMethod: SocialAccountSetupMethod;\n postTypes: Array<'text' | 'link' | 'image' | 'video'>;\n defaultLinkBehavior: LinkBehavior;\n defaultPublishMode: PublishMode;\n supportedPublishModes: PublishMode[];\n requiredSecretFields: string[];\n}\n\nexport const SOCIAL_PLATFORM_SETUPS: SocialPlatformSetup[] = [\n {\n platform: 'youtube',\n label: 'YouTube',\n setupMethod: 'oauth',\n postTypes: ['video'],\n defaultLinkBehavior: 'description',\n defaultPublishMode: 'private_or_scheduled',\n supportedPublishModes: ['dry_run', 'private_or_scheduled', 'public'],\n requiredSecretFields: ['clientId', 'clientSecret', 'accessToken'],\n },\n {\n platform: 'facebook',\n label: 'Facebook Page',\n setupMethod: 'oauth',\n postTypes: ['text', 'link', 'image', 'video'],\n defaultLinkBehavior: 'attachment',\n defaultPublishMode: 'private_or_scheduled',\n supportedPublishModes: [\n 'dry_run',\n 'stage_remote',\n 'private_or_scheduled',\n 'public',\n ],\n requiredSecretFields: ['accessToken', 'pageId'],\n },\n {\n platform: 'threads',\n label: 'Threads',\n setupMethod: 'oauth',\n postTypes: ['text', 'link', 'image', 'video'],\n defaultLinkBehavior: 'attachment',\n defaultPublishMode: 'stage_remote',\n supportedPublishModes: ['dry_run', 'stage_remote', 'public'],\n requiredSecretFields: ['accessToken', 'userId'],\n },\n {\n platform: 'x',\n label: 'X',\n setupMethod: 'oauth',\n postTypes: ['text', 'link', 'image', 'video'],\n defaultLinkBehavior: 'inline',\n defaultPublishMode: 'dry_run',\n supportedPublishModes: ['dry_run', 'stage_remote', 'public'],\n requiredSecretFields: [\n 'apiKey',\n 'apiSecret',\n 'accessToken',\n 'accessSecret',\n ],\n },\n {\n platform: 'bluesky',\n label: 'Bluesky',\n setupMethod: 'manual',\n postTypes: ['text', 'link', 'image'],\n defaultLinkBehavior: 'attachment',\n defaultPublishMode: 'dry_run',\n supportedPublishModes: ['dry_run', 'stage_remote', 'public'],\n requiredSecretFields: ['identifier', 'password'],\n },\n];\n\nconst SOCIAL_PLATFORM_SETUP_BY_PLATFORM = new Map(\n SOCIAL_PLATFORM_SETUPS.map((setup) => [setup.platform, setup]),\n);\n\nexport function getSocialPlatformSetup(\n platform: SocialPlatformType,\n): SocialPlatformSetup {\n const setup = SOCIAL_PLATFORM_SETUP_BY_PLATFORM.get(platform);\n if (!setup) {\n throw new Error(`Unsupported social platform: ${platform}`);\n }\n return setup;\n}\n\nexport function getDefaultSocialAccountName(\n platform: SocialPlatformType,\n username?: string | null,\n): string {\n const setup = getSocialPlatformSetup(platform);\n return username ? `${setup.label} ${username}` : setup.label;\n}\n\nexport function normalizeManualCredentials(\n platform: SocialPlatformType,\n values: Record<string, unknown>,\n): Record<string, string> {\n const setup = getSocialPlatformSetup(platform);\n const credentials: Record<string, string> = {};\n\n for (const field of setup.requiredSecretFields) {\n const value = values[field];\n if (typeof value === 'string' && value.trim() !== '') {\n credentials[field] = value.trim();\n }\n }\n\n return credentials;\n}\n\nexport function validateManualCredentials(\n platform: SocialPlatformType,\n values: Record<string, unknown>,\n): string[] {\n const setup = getSocialPlatformSetup(platform);\n const missing: string[] = [];\n\n for (const field of setup.requiredSecretFields) {\n const value = values[field];\n if (typeof value !== 'string' || value.trim() === '') {\n missing.push(field);\n }\n }\n\n return missing;\n}\n"],"names":[],"mappings":"AAmBO,MAAM,yBAAgD;AAAA,EAC3D;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW,CAAC,OAAO;AAAA,IACnB,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,uBAAuB,CAAC,WAAW,wBAAwB,QAAQ;AAAA,IACnE,sBAAsB,CAAC,YAAY,gBAAgB,aAAa;AAAA,EAAA;AAAA,EAElE;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW,CAAC,QAAQ,QAAQ,SAAS,OAAO;AAAA,IAC5C,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,uBAAuB;AAAA,MACrB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,IAEF,sBAAsB,CAAC,eAAe,QAAQ;AAAA,EAAA;AAAA,EAEhD;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW,CAAC,QAAQ,QAAQ,SAAS,OAAO;AAAA,IAC5C,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,uBAAuB,CAAC,WAAW,gBAAgB,QAAQ;AAAA,IAC3D,sBAAsB,CAAC,eAAe,QAAQ;AAAA,EAAA;AAAA,EAEhD;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW,CAAC,QAAQ,QAAQ,SAAS,OAAO;AAAA,IAC5C,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,uBAAuB,CAAC,WAAW,gBAAgB,QAAQ;AAAA,IAC3D,sBAAsB;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IAAA;AAAA,EACF;AAAA,EAEF;AAAA,IACE,UAAU;AAAA,IACV,OAAO;AAAA,IACP,aAAa;AAAA,IACb,WAAW,CAAC,QAAQ,QAAQ,OAAO;AAAA,IACnC,qBAAqB;AAAA,IACrB,oBAAoB;AAAA,IACpB,uBAAuB,CAAC,WAAW,gBAAgB,QAAQ;AAAA,IAC3D,sBAAsB,CAAC,cAAc,UAAU;AAAA,EAAA;AAEnD;AAEA,MAAM,oCAAoC,IAAI;AAAA,EAC5C,uBAAuB,IAAI,CAAC,UAAU,CAAC,MAAM,UAAU,KAAK,CAAC;AAC/D;AAEO,SAAS,uBACd,UACqB;AACrB,QAAM,QAAQ,kCAAkC,IAAI,QAAQ;AAC5D,MAAI,CAAC,OAAO;AACV,UAAM,IAAI,MAAM,gCAAgC,QAAQ,EAAE;AAAA,EAC5D;AACA,SAAO;AACT;AAEO,SAAS,4BACd,UACA,UACQ;AACR,QAAM,QAAQ,uBAAuB,QAAQ;AAC7C,SAAO,WAAW,GAAG,MAAM,KAAK,IAAI,QAAQ,KAAK,MAAM;AACzD;AAEO,SAAS,2BACd,UACA,QACwB;AACxB,QAAM,QAAQ,uBAAuB,QAAQ;AAC7C,QAAM,cAAsC,CAAA;AAE5C,aAAW,SAAS,MAAM,sBAAsB;AAC9C,UAAM,QAAQ,OAAO,KAAK;AAC1B,QAAI,OAAO,UAAU,YAAY,MAAM,KAAA,MAAW,IAAI;AACpD,kBAAY,KAAK,IAAI,MAAM,KAAA;AAAA,IAC7B;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,0BACd,UACA,QACU;AACV,QAAM,QAAQ,uBAAuB,QAAQ;AAC7C,QAAM,UAAoB,CAAA;AAE1B,aAAW,SAAS,MAAM,sBAAsB;AAC9C,UAAM,QAAQ,OAAO,KAAK;AAC1B,QAAI,OAAO,UAAU,YAAY,MAAM,KAAA,MAAW,IAAI;AACpD,cAAQ,KAAK,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SAAO;AACT;"}
|