@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.
Files changed (47) hide show
  1. package/AGENTS.md +18 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +94 -0
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/collections/index.d.ts +5 -0
  8. package/dist/collections/index.d.ts.map +1 -0
  9. package/dist/collections/oauth-state-collection.d.ts +9 -0
  10. package/dist/collections/oauth-state-collection.d.ts.map +1 -0
  11. package/dist/collections/social-account-collection.d.ts +9 -0
  12. package/dist/collections/social-account-collection.d.ts.map +1 -0
  13. package/dist/collections/social-post-analytics-snapshot-collection.d.ts +18 -0
  14. package/dist/collections/social-post-analytics-snapshot-collection.d.ts.map +1 -0
  15. package/dist/collections/social-post-collection.d.ts +32 -0
  16. package/dist/collections/social-post-collection.d.ts.map +1 -0
  17. package/dist/index.d.ts +6 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +824 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/manifest.json +3363 -0
  22. package/dist/oauth-state.d.ts +127 -0
  23. package/dist/oauth-state.d.ts.map +1 -0
  24. package/dist/server.d.ts +18 -0
  25. package/dist/server.d.ts.map +1 -0
  26. package/dist/server.js +106 -0
  27. package/dist/server.js.map +1 -0
  28. package/dist/smrt-knowledge.json +1398 -0
  29. package/dist/social-account.d.ts +270 -0
  30. package/dist/social-account.d.ts.map +1 -0
  31. package/dist/social-post-analytics-snapshot.d.ts +40 -0
  32. package/dist/social-post-analytics-snapshot.d.ts.map +1 -0
  33. package/dist/social-post.d.ts +258 -0
  34. package/dist/social-post.d.ts.map +1 -0
  35. package/dist/svelte/components/SocialAccountSettings.svelte +243 -0
  36. package/dist/svelte/components/SocialAccountSettings.svelte.d.ts +15 -0
  37. package/dist/svelte/components/SocialAccountSettings.svelte.d.ts.map +1 -0
  38. package/dist/svelte/i18n.d.ts +9 -0
  39. package/dist/svelte/i18n.d.ts.map +1 -0
  40. package/dist/svelte/i18n.js +15 -0
  41. package/dist/svelte/index.d.ts +6 -0
  42. package/dist/svelte/index.d.ts.map +1 -0
  43. package/dist/svelte/index.js +2 -0
  44. package/dist/svelte/types.d.ts +16 -0
  45. package/dist/svelte/types.d.ts.map +1 -0
  46. package/dist/svelte/types.js +1 -0
  47. 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"}
@@ -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;"}