@happyvertical/smrt-social 0.40.69 → 0.40.70

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 CHANGED
@@ -16,3 +16,9 @@ Social media account management with OAuth and post scheduling. Supports YouTube
16
16
  - **Platform enum hardcoded**: youtube/threads/x/bluesky — extending requires code changes
17
17
  - **OAuthState TTL**: 10 minutes, app must clean up expired states
18
18
  - **Optional tenancy** on all models
19
+ - **Relationship targets**: `SocialPost.socialAccountId` and
20
+ `SocialPostAnalyticsSnapshot.socialPostId` are same-package `@foreignKey`
21
+ columns; `SocialPost.videoContentId` is a `@crossPackageRef` to
22
+ `@happyvertical/smrt-video:VideoContent` (no value import back into this
23
+ package). They previously used `@foreignKey(() => X)`, whose target resolved
24
+ to `''`, so none of them carried a relationship edge (#2379).
package/dist/index.js CHANGED
@@ -3,9 +3,8 @@ import { ObjectRegistry, SmrtCollection, SmrtObject, crossPackageRef, field, for
3
3
  import { TenantScoped, getCurrentTenant, tenantId, withTenant } from "@happyvertical/smrt-tenancy";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { SecretService } from "@happyvertical/smrt-secrets";
6
- import { VideoContent } from "@happyvertical/smrt-video";
7
6
  //#region src/__smrt-register__.ts
8
- ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-social\",\"packageVersion\":\"0.40.69\",\"objects\":{\"@happyvertical/smrt-social:OAuthState\":{\"name\":\"oauthstate\",\"className\":\"OAuthState\",\"qualifiedName\":\"@happyvertical/smrt-social:OAuthState\",\"collection\":\"oauthstates\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/oauth-state.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"platform\":{\"type\":\"text\",\"required\":false,\"default\":\"youtube\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"codeVerifier\":{\"type\":\"text\",\"required\":false},\"redirectUri\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"scopes\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"expiresAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"verifyState\":{\"name\":\"verifyState\",\"async\":false,\"parameters\":[{\"name\":\"callbackState\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"generateState\":{\"name\":\"generateState\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":true,\"isPublic\":true},\"generateCodeVerifier\":{\"name\":\"generateCodeVerifier\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":true,\"isPublic\":true},\"generateCodeChallenge\":{\"name\":\"generateCodeChallenge\",\"async\":true,\"parameters\":[{\"name\":\"verifier\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"delete\"]},\"mcp\":false,\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"OAuthState\",\"collectionExportName\":\"OAuthStateCollection\",\"schema\":{\"tableName\":\"oauth_states\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oauth_states\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"platform\\\" TEXT DEFAULT 'youtube',\\n \\\"state\\\" TEXT DEFAULT '',\\n \\\"code_verifier\\\" TEXT,\\n \\\"redirect_uri\\\" TEXT DEFAULT '',\\n \\\"scopes\\\" JSON DEFAULT '[]',\\n \\\"expires_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"platform\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"youtube\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"code_verifier\":{\"type\":\"TEXT\",\"notNull\":false},\"redirect_uri\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"scopes\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"oauth_states_id_idx\",\"columns\":[\"id\"]},{\"name\":\"oauth_states_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"oauth_states_meta_type_idx\",\"columns\":[\"_meta_type\"]}],\"version\":\"709e111f\"}},\"@happyvertical/smrt-social:SocialAccount\":{\"name\":\"socialaccount\",\"className\":\"SocialAccount\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialAccount\",\"collection\":\"socialaccounts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/social-account.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"platform\":{\"type\":\"text\",\"required\":false,\"default\":\"youtube\"},\"platformUserId\":{\"type\":\"text\",\"required\":false},\"platformUsername\":{\"type\":\"text\",\"required\":false},\"platformUrl\":{\"type\":\"text\",\"required\":false},\"accessToken\":{\"type\":\"text\",\"required\":false},\"refreshToken\":{\"type\":\"text\",\"required\":false},\"credentialSecretId\":{\"type\":\"text\",\"required\":false},\"accessTokenSecretName\":{\"type\":\"text\",\"required\":false},\"refreshTokenSecretName\":{\"type\":\"text\",\"required\":false},\"tokenExpiresAt\":{\"type\":\"datetime\",\"required\":false},\"isActive\":{\"type\":\"boolean\",\"required\":false,\"default\":true},\"defaultHashtags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"scopes\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"missingPermissions\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"linkBehavior\":{\"type\":\"text\",\"required\":false,\"default\":\"description\"},\"publishMode\":{\"type\":\"text\",\"required\":false,\"default\":\"dry_run\"},\"publicPublishingAllowed\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"connected\"},\"errorMessage\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string | null | undefined>\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"setCredentials\":{\"name\":\"setCredentials\",\"async\":true,\"parameters\":[{\"name\":\"credentials\",\"type\":\"Record<string>\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getCredentials\":{\"name\":\"getCredentials\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Record<string> | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"SocialAccount\",\"collectionExportName\":\"SocialAccountCollection\",\"schema\":{\"tableName\":\"social_accounts\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_accounts\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"platform\\\" TEXT DEFAULT 'youtube',\\n \\\"platform_user_id\\\" TEXT,\\n \\\"platform_username\\\" TEXT,\\n \\\"platform_url\\\" TEXT,\\n \\\"access_token\\\" TEXT,\\n \\\"refresh_token\\\" TEXT,\\n \\\"credential_secret_id\\\" TEXT,\\n \\\"access_token_secret_name\\\" TEXT,\\n \\\"refresh_token_secret_name\\\" TEXT,\\n \\\"token_expires_at\\\" TIMESTAMP,\\n \\\"is_active\\\" BOOLEAN DEFAULT TRUE,\\n \\\"default_hashtags\\\" JSON DEFAULT '[]',\\n \\\"scopes\\\" JSON DEFAULT '[]',\\n \\\"missing_permissions\\\" JSON DEFAULT '[]',\\n \\\"link_behavior\\\" TEXT DEFAULT 'description',\\n \\\"publish_mode\\\" TEXT DEFAULT 'dry_run',\\n \\\"public_publishing_allowed\\\" BOOLEAN DEFAULT FALSE,\\n \\\"status\\\" TEXT DEFAULT 'connected',\\n \\\"error_message\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"platform\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"youtube\"},\"platform_user_id\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_username\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_url\":{\"type\":\"TEXT\",\"notNull\":false},\"access_token\":{\"type\":\"TEXT\",\"notNull\":false},\"refresh_token\":{\"type\":\"TEXT\",\"notNull\":false},\"credential_secret_id\":{\"type\":\"TEXT\",\"notNull\":false},\"access_token_secret_name\":{\"type\":\"TEXT\",\"notNull\":false},\"refresh_token_secret_name\":{\"type\":\"TEXT\",\"notNull\":false},\"token_expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"is_active\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true},\"default_hashtags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"scopes\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"missing_permissions\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"link_behavior\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"description\"},\"publish_mode\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"dry_run\"},\"public_publishing_allowed\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"connected\"},\"error_message\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"social_accounts_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_accounts_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"social_accounts_meta_type_idx\",\"columns\":[\"_meta_type\"]}],\"version\":\"0c175da6\"}},\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshot\":{\"name\":\"socialpostanalyticssnapshot\",\"className\":\"SocialPostAnalyticsSnapshot\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshot\",\"collection\":\"socialpostanalyticssnapshots\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/social-post-analytics-snapshot.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"socialPostId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"() => SocialPost\"},\"platform\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"analytics\":{\"type\":\"json\",\"required\":false},\"raw\":{\"type\":\"json\",\"required\":false,\"_meta\":{\"nullable\":true}},\"capturedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"SocialPostAnalyticsSnapshot\",\"collectionExportName\":\"SocialPostAnalyticsSnapshotCollection\",\"validationRules\":[{\"field\":\"platform\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"social_post_analytics_snapshots\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_post_analytics_snapshots\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"social_post_id\\\" UUID,\\n \\\"platform\\\" TEXT,\\n \\\"analytics\\\" JSON,\\n \\\"raw\\\" JSON,\\n \\\"captured_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"social_post_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false},\"platform\":{\"type\":\"TEXT\",\"notNull\":false},\"analytics\":{\"type\":\"JSON\",\"notNull\":false},\"raw\":{\"type\":\"JSON\",\"notNull\":false},\"captured_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"social_post_analytics_snapshots_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_post_analytics_snapshots_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"social_post_analytics_snapshots_meta_type_idx\",\"columns\":[\"_meta_type\"]}],\"version\":\"50fd9e85\"}},\"@happyvertical/smrt-social:SocialPost\":{\"name\":\"socialpost\",\"className\":\"SocialPost\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPost\",\"collection\":\"socialposts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/social-post.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"socialAccountId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"() => SocialAccount\"},\"videoContentId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"() => VideoContent\"},\"contentId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-content:Content\"},\"postType\":{\"type\":\"text\",\"required\":false,\"default\":\"text\"},\"mediaUrl\":{\"type\":\"text\",\"required\":false},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"hashtags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"linkUrl\":{\"type\":\"text\",\"required\":false},\"platformPostId\":{\"type\":\"text\",\"required\":false},\"platformUrl\":{\"type\":\"text\",\"required\":false},\"scheduledAt\":{\"type\":\"datetime\",\"required\":false},\"publishedAt\":{\"type\":\"datetime\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"draft\"},\"errorMessage\":{\"type\":\"text\",\"required\":false},\"analytics\":{\"type\":\"json\",\"required\":false},\"analyticsLastSyncedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"SocialPost\",\"collectionExportName\":\"SocialPostCollection\",\"schema\":{\"tableName\":\"social_posts\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_posts\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"social_account_id\\\" UUID,\\n \\\"video_content_id\\\" UUID,\\n \\\"content_id\\\" UUID,\\n \\\"post_type\\\" TEXT DEFAULT 'text',\\n \\\"media_url\\\" TEXT,\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"hashtags\\\" JSON DEFAULT '[]',\\n \\\"link_url\\\" TEXT,\\n \\\"platform_post_id\\\" TEXT,\\n \\\"platform_url\\\" TEXT,\\n \\\"scheduled_at\\\" TIMESTAMP,\\n \\\"published_at\\\" TIMESTAMP,\\n \\\"status\\\" TEXT DEFAULT 'draft',\\n \\\"error_message\\\" TEXT,\\n \\\"analytics\\\" JSON,\\n \\\"analytics_last_synced_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"social_account_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false},\"video_content_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false},\"content_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"post_type\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"text\"},\"media_url\":{\"type\":\"TEXT\",\"notNull\":false},\"title\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"hashtags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"link_url\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_post_id\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_url\":{\"type\":\"TEXT\",\"notNull\":false},\"scheduled_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"published_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"draft\"},\"error_message\":{\"type\":\"TEXT\",\"notNull\":false},\"analytics\":{\"type\":\"JSON\",\"notNull\":false},\"analytics_last_synced_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"social_posts_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_posts_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"social_posts_meta_type_idx\",\"columns\":[\"_meta_type\"]}],\"version\":\"0ec041f6\"}},\"@happyvertical/smrt-social:OAuthStateCollection\":{\"name\":\"oauthstatecollection\",\"className\":\"OAuthStateCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:OAuthStateCollection\",\"collection\":\"oauthstates\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/oauth-state-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"findByState\":{\"name\":\"findByState\",\"async\":true,\"parameters\":[{\"name\":\"state\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<OAuthState | null>\",\"isStatic\":false,\"isPublic\":true},\"findExpired\":{\"name\":\"findExpired\",\"async\":true,\"parameters\":[{\"name\":\"now\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<OAuthState[]>\",\"isStatic\":false,\"isPublic\":true},\"deleteExpired\":{\"name\":\"deleteExpired\",\"async\":true,\"parameters\":[{\"name\":\"now\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"OAuthState\",\"exportName\":\"OAuthStateCollection\",\"collectionExportName\":\"OAuthStateCollectionCollection\",\"schema\":{\"tableName\":\"oauth_state_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oauth_state_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"oauth_state_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"oauth_state_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"bb1b91f9\"}},\"@happyvertical/smrt-social:SocialAccountCollection\":{\"name\":\"socialaccountcollection\",\"className\":\"SocialAccountCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialAccountCollection\",\"collection\":\"socialaccounts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/social-account-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"findActive\":{\"name\":\"findActive\",\"async\":true,\"parameters\":[{\"name\":\"platform\",\"type\":\"SocialPlatformType\",\"optional\":true}],\"returnType\":\"Promise<SocialAccount[]>\",\"isStatic\":false,\"isPublic\":true},\"findReady\":{\"name\":\"findReady\",\"async\":true,\"parameters\":[{\"name\":\"platform\",\"type\":\"SocialPlatformType\",\"optional\":true}],\"returnType\":\"Promise<SocialAccount[]>\",\"isStatic\":false,\"isPublic\":true},\"findNeedsAttention\":{\"name\":\"findNeedsAttention\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<SocialAccount[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"SocialAccount\",\"exportName\":\"SocialAccountCollection\",\"collectionExportName\":\"SocialAccountCollectionCollection\",\"schema\":{\"tableName\":\"social_account_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_account_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"social_account_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_account_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"eeae07d4\"}},\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshotCollection\":{\"name\":\"socialpostanalyticssnapshotcollection\",\"className\":\"SocialPostAnalyticsSnapshotCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshotCollection\",\"collection\":\"socialpostanalyticssnapshots\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/social-post-analytics-snapshot-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"recordSnapshot\":{\"name\":\"recordSnapshot\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<SocialPostAnalyticsSnapshot>\",\"isStatic\":false,\"isPublic\":true},\"findForPost\":{\"name\":\"findForPost\",\"async\":true,\"parameters\":[{\"name\":\"socialPostId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<SocialPostAnalyticsSnapshot[]>\",\"isStatic\":false,\"isPublic\":true},\"findLatestForPost\":{\"name\":\"findLatestForPost\",\"async\":true,\"parameters\":[{\"name\":\"socialPostId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<SocialPostAnalyticsSnapshot | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"SocialPostAnalyticsSnapshot\",\"exportName\":\"SocialPostAnalyticsSnapshotCollection\",\"collectionExportName\":\"SocialPostAnalyticsSnapshotCollectionCollection\",\"schema\":{\"tableName\":\"social_post_analytics_snapshot_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_post_analytics_snapshot_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"social_post_analytics_snapshot_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_post_analytics_snapshot_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"c98f7921\"}},\"@happyvertical/smrt-social:SocialPostCollection\":{\"name\":\"socialpostcollection\",\"className\":\"SocialPostCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPostCollection\",\"collection\":\"socialposts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/social-post-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"createDraft\":{\"name\":\"createDraft\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"CreateSocialPostDraftOptions\",\"optional\":false}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true},\"findByStatus\":{\"name\":\"findByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"PostStatus\",\"optional\":false}],\"returnType\":\"Promise<SocialPost[]>\",\"isStatic\":false,\"isPublic\":true},\"findForAccount\":{\"name\":\"findForAccount\",\"async\":true,\"parameters\":[{\"name\":\"socialAccountId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<SocialPost[]>\",\"isStatic\":false,\"isPublic\":true},\"findDueForPublish\":{\"name\":\"findDueForPublish\",\"async\":true,\"parameters\":[{\"name\":\"now\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<SocialPost[]>\",\"isStatic\":false,\"isPublic\":true},\"recordPublishSuccess\":{\"name\":\"recordPublishSuccess\",\"async\":true,\"parameters\":[{\"name\":\"post\",\"type\":\"SocialPost\",\"optional\":false},{\"name\":\"data\",\"type\":\"PublishSuccessData\",\"optional\":false}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true},\"recordPublishFailure\":{\"name\":\"recordPublishFailure\",\"async\":true,\"parameters\":[{\"name\":\"post\",\"type\":\"SocialPost\",\"optional\":false},{\"name\":\"error\",\"type\":\"Error | string\",\"optional\":false}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true},\"updateLatestAnalytics\":{\"name\":\"updateLatestAnalytics\",\"async\":true,\"parameters\":[{\"name\":\"post\",\"type\":\"SocialPost\",\"optional\":false},{\"name\":\"analytics\",\"type\":\"PostAnalytics\",\"optional\":false},{\"name\":\"syncedAt\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"SocialPost\",\"exportName\":\"SocialPostCollection\",\"collectionExportName\":\"SocialPostCollectionCollection\",\"schema\":{\"tableName\":\"social_post_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_post_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"social_post_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_post_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"1baa42c4\"}}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-content\",\"@happyvertical/smrt-core\",\"@happyvertical/smrt-secrets\",\"@happyvertical/smrt-tenancy\",\"@happyvertical/smrt-video\"]}"));
7
+ ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-social\",\"packageVersion\":\"0.40.70\",\"objects\":{\"@happyvertical/smrt-social:OAuthState\":{\"name\":\"oauthstate\",\"className\":\"OAuthState\",\"qualifiedName\":\"@happyvertical/smrt-social:OAuthState\",\"collection\":\"oauthstates\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/oauth-state.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"platform\":{\"type\":\"text\",\"required\":false,\"default\":\"youtube\"},\"state\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"codeVerifier\":{\"type\":\"text\",\"required\":false},\"redirectUri\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"scopes\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"expiresAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"verifyState\":{\"name\":\"verifyState\",\"async\":false,\"parameters\":[{\"name\":\"callbackState\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"generateState\":{\"name\":\"generateState\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":true,\"isPublic\":true},\"generateCodeVerifier\":{\"name\":\"generateCodeVerifier\",\"async\":false,\"parameters\":[],\"returnType\":\"string\",\"isStatic\":true,\"isPublic\":true},\"generateCodeChallenge\":{\"name\":\"generateCodeChallenge\",\"async\":true,\"parameters\":[{\"name\":\"verifier\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<string>\",\"isStatic\":true,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"delete\"]},\"mcp\":false,\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"OAuthState\",\"collectionExportName\":\"OAuthStateCollection\",\"schema\":{\"tableName\":\"oauth_states\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oauth_states\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"platform\\\" TEXT DEFAULT 'youtube',\\n \\\"state\\\" TEXT DEFAULT '',\\n \\\"code_verifier\\\" TEXT,\\n \\\"redirect_uri\\\" TEXT DEFAULT '',\\n \\\"scopes\\\" JSON DEFAULT '[]',\\n \\\"expires_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"platform\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"youtube\"},\"state\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"code_verifier\":{\"type\":\"TEXT\",\"notNull\":false},\"redirect_uri\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"scopes\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"oauth_states_id_idx\",\"columns\":[\"id\"]},{\"name\":\"oauth_states_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"oauth_states_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"oauth_states_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"709e111f\"}},\"@happyvertical/smrt-social:SocialAccount\":{\"name\":\"socialaccount\",\"className\":\"SocialAccount\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialAccount\",\"collection\":\"socialaccounts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/social-account.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"name\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"platform\":{\"type\":\"text\",\"required\":false,\"default\":\"youtube\"},\"platformUserId\":{\"type\":\"text\",\"required\":false},\"platformUsername\":{\"type\":\"text\",\"required\":false},\"platformUrl\":{\"type\":\"text\",\"required\":false},\"accessToken\":{\"type\":\"text\",\"required\":false},\"refreshToken\":{\"type\":\"text\",\"required\":false},\"credentialSecretId\":{\"type\":\"text\",\"required\":false},\"accessTokenSecretName\":{\"type\":\"text\",\"required\":false},\"refreshTokenSecretName\":{\"type\":\"text\",\"required\":false},\"tokenExpiresAt\":{\"type\":\"datetime\",\"required\":false},\"isActive\":{\"type\":\"boolean\",\"required\":false,\"default\":true},\"defaultHashtags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"scopes\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"missingPermissions\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"linkBehavior\":{\"type\":\"text\",\"required\":false,\"default\":\"description\"},\"publishMode\":{\"type\":\"text\",\"required\":false,\"default\":\"dry_run\"},\"publicPublishingAllowed\":{\"type\":\"boolean\",\"required\":false,\"default\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"connected\"},\"errorMessage\":{\"type\":\"text\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string | null | undefined>\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"setCredentials\":{\"name\":\"setCredentials\",\"async\":true,\"parameters\":[{\"name\":\"credentials\",\"type\":\"Record<string>\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getCredentials\":{\"name\":\"getCredentials\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Record<string> | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"SocialAccount\",\"collectionExportName\":\"SocialAccountCollection\",\"schema\":{\"tableName\":\"social_accounts\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_accounts\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"name\\\" TEXT DEFAULT '',\\n \\\"platform\\\" TEXT DEFAULT 'youtube',\\n \\\"platform_user_id\\\" TEXT,\\n \\\"platform_username\\\" TEXT,\\n \\\"platform_url\\\" TEXT,\\n \\\"access_token\\\" TEXT,\\n \\\"refresh_token\\\" TEXT,\\n \\\"credential_secret_id\\\" TEXT,\\n \\\"access_token_secret_name\\\" TEXT,\\n \\\"refresh_token_secret_name\\\" TEXT,\\n \\\"token_expires_at\\\" TIMESTAMP,\\n \\\"is_active\\\" BOOLEAN DEFAULT TRUE,\\n \\\"default_hashtags\\\" JSON DEFAULT '[]',\\n \\\"scopes\\\" JSON DEFAULT '[]',\\n \\\"missing_permissions\\\" JSON DEFAULT '[]',\\n \\\"link_behavior\\\" TEXT DEFAULT 'description',\\n \\\"publish_mode\\\" TEXT DEFAULT 'dry_run',\\n \\\"public_publishing_allowed\\\" BOOLEAN DEFAULT FALSE,\\n \\\"status\\\" TEXT DEFAULT 'connected',\\n \\\"error_message\\\" TEXT\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"name\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"platform\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"youtube\"},\"platform_user_id\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_username\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_url\":{\"type\":\"TEXT\",\"notNull\":false},\"access_token\":{\"type\":\"TEXT\",\"notNull\":false},\"refresh_token\":{\"type\":\"TEXT\",\"notNull\":false},\"credential_secret_id\":{\"type\":\"TEXT\",\"notNull\":false},\"access_token_secret_name\":{\"type\":\"TEXT\",\"notNull\":false},\"refresh_token_secret_name\":{\"type\":\"TEXT\",\"notNull\":false},\"token_expires_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"is_active\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":true},\"default_hashtags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"scopes\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"missing_permissions\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"link_behavior\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"description\"},\"publish_mode\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"dry_run\"},\"public_publishing_allowed\":{\"type\":\"BOOLEAN\",\"notNull\":false,\"default\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"connected\"},\"error_message\":{\"type\":\"TEXT\",\"notNull\":false}},\"indexes\":[{\"name\":\"social_accounts_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_accounts_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"social_accounts_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_accounts_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"0c175da6\"}},\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshot\":{\"name\":\"socialpostanalyticssnapshot\",\"className\":\"SocialPostAnalyticsSnapshot\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshot\",\"collection\":\"socialpostanalyticssnapshots\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/social-post-analytics-snapshot.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"socialPostId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"SocialPost\"},\"platform\":{\"type\":\"text\",\"required\":true,\"_meta\":{\"required\":true}},\"analytics\":{\"type\":\"json\",\"required\":false},\"raw\":{\"type\":\"json\",\"required\":false,\"_meta\":{\"nullable\":true}},\"capturedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"SocialPostAnalyticsSnapshot\",\"collectionExportName\":\"SocialPostAnalyticsSnapshotCollection\",\"validationRules\":[{\"field\":\"platform\",\"rule\":\"required\",\"fieldType\":\"text\"}],\"schema\":{\"tableName\":\"social_post_analytics_snapshots\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_post_analytics_snapshots\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"social_post_id\\\" UUID,\\n \\\"platform\\\" TEXT,\\n \\\"analytics\\\" JSON,\\n \\\"raw\\\" JSON,\\n \\\"captured_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"social_post_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false},\"platform\":{\"type\":\"TEXT\",\"notNull\":false},\"analytics\":{\"type\":\"JSON\",\"notNull\":false},\"raw\":{\"type\":\"JSON\",\"notNull\":false},\"captured_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"social_post_analytics_snapshots_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_post_analytics_snapshots_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"social_post_analytics_snapshots_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_post_analytics_snapshots_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"50fd9e85\"}},\"@happyvertical/smrt-social:SocialPost\":{\"name\":\"socialpost\",\"className\":\"SocialPost\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPost\",\"collection\":\"socialposts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/social-post.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{\"created_at\":{\"type\":\"datetime\",\"required\":false},\"updated_at\":{\"type\":\"datetime\",\"required\":false},\"tenantId\":{\"type\":\"text\",\"required\":false,\"_meta\":{\"sqlType\":\"UUID\",\"nullable\":true,\"__tenancy\":{\"isTenantIdField\":true,\"autoFilter\":true,\"required\":false,\"autoPopulate\":true,\"nullable\":true,\"mode\":\"optional\",\"field\":\"tenantId\",\"allowSuperAdminBypass\":false}}},\"socialAccountId\":{\"type\":\"foreignKey\",\"required\":false,\"related\":\"SocialAccount\"},\"videoContentId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-video:VideoContent\"},\"contentId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-content:Content\"},\"postType\":{\"type\":\"text\",\"required\":false,\"default\":\"text\"},\"mediaUrl\":{\"type\":\"text\",\"required\":false},\"title\":{\"type\":\"text\",\"required\":false},\"description\":{\"type\":\"text\",\"required\":false,\"default\":\"\"},\"hashtags\":{\"type\":\"json\",\"required\":false,\"default\":[]},\"linkUrl\":{\"type\":\"text\",\"required\":false},\"platformPostId\":{\"type\":\"text\",\"required\":false},\"platformUrl\":{\"type\":\"text\",\"required\":false},\"scheduledAt\":{\"type\":\"datetime\",\"required\":false},\"publishedAt\":{\"type\":\"datetime\",\"required\":false},\"status\":{\"type\":\"text\",\"required\":false,\"default\":\"draft\"},\"errorMessage\":{\"type\":\"text\",\"required\":false},\"analytics\":{\"type\":\"json\",\"required\":false},\"analyticsLastSyncedAt\":{\"type\":\"datetime\",\"required\":false}},\"methods\":{\"getAiUsageSnapshot\":{\"name\":\"getAiUsageSnapshot\",\"async\":false,\"parameters\":[],\"returnType\":\"AiUsageSnapshot | undefined\",\"isStatic\":false,\"isPublic\":true},\"resetAiUsage\":{\"name\":\"resetAiUsage\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"listAiUsage\":{\"name\":\"listAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageListOptions\",\"optional\":true}],\"returnType\":\"Promise<SmrtAiUsageRecord[]>\",\"isStatic\":false,\"isPublic\":true},\"summarizeAiUsage\":{\"name\":\"summarizeAiUsage\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiUsageSummaryOptions\",\"optional\":true}],\"returnType\":\"Promise<Record<string, AiUsageStats>>\",\"isStatic\":false,\"isPublic\":true},\"destroy\":{\"name\":\"destroy\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"markAsPersisted\":{\"name\":\"markAsPersisted\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"requireInsertOnSave\":{\"name\":\"requireInsertOnSave\",\"async\":false,\"parameters\":[],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"initialize\":{\"name\":\"initialize\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"loadDataFromDb\":{\"name\":\"loadDataFromDb\",\"async\":true,\"parameters\":[{\"name\":\"data\",\"type\":\"Record<string>\",\"optional\":false}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getFields\":{\"name\":\"getFields\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"toJSON\":{\"name\":\"toJSON\",\"async\":false,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"toPlainObject\":{\"name\":\"toPlainObject\",\"async\":false,\"parameters\":[],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"toPublicJSON\":{\"name\":\"toPublicJSON\",\"async\":false,\"parameters\":[{\"name\":\"options\",\"type\":\"PublicJsonOptions\",\"optional\":true}],\"returnType\":\"Record<string>\",\"isStatic\":false,\"isPublic\":true},\"getId\":{\"name\":\"getId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"getSavedId\":{\"name\":\"getSavedId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"isSaved\":{\"name\":\"isSaved\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"save\":{\"name\":\"save\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"classifyConstraintError\":{\"name\":\"classifyConstraintError\",\"async\":false,\"parameters\":[{\"name\":\"message\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"'unique' | 'not_null' | null\",\"isStatic\":true,\"isPublic\":true},\"loadFromId\":{\"name\":\"loadFromId\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"loadFromSlug\":{\"name\":\"loadFromSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"is\":{\"name\":\"is\",\"async\":true,\"parameters\":[{\"name\":\"criteria\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"do\":{\"name\":\"do\",\"async\":true,\"parameters\":[{\"name\":\"instructions\",\"type\":\"string\",\"optional\":false},{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"describe\":{\"name\":\"describe\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"AiOperationOptions\",\"optional\":true}],\"returnType\":\"any\",\"isStatic\":false,\"isPublic\":true},\"delete\":{\"name\":\"delete\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"isRelatedLoaded\":{\"name\":\"isRelatedLoaded\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"boolean\",\"isStatic\":false,\"isPublic\":true},\"_setLoadedRelationship\":{\"name\":\"_setLoadedRelationship\",\"async\":false,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"value\",\"type\":\"any\",\"optional\":false}],\"returnType\":\"void\",\"isStatic\":false,\"isPublic\":true},\"loadRelated\":{\"name\":\"loadRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"loadRelatedMany\":{\"name\":\"loadRelatedMany\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any[]>\",\"isStatic\":false,\"isPublic\":true},\"getRelated\":{\"name\":\"getRelated\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"opts\",\"type\":\"LoadRelatedOptions\",\"optional\":true}],\"returnType\":\"Promise<any>\",\"isStatic\":false,\"isPublic\":true},\"getAvailableTools\":{\"name\":\"getAvailableTools\",\"async\":false,\"parameters\":[],\"returnType\":\"AITool[]\",\"isStatic\":false,\"isPublic\":true},\"executeToolCall\":{\"name\":\"executeToolCall\",\"async\":true,\"parameters\":[{\"name\":\"toolCall\",\"type\":\"ToolCall\",\"optional\":false}],\"returnType\":\"Promise<ToolCallResult>\",\"isStatic\":false,\"isPublic\":true},\"remember\":{\"name\":\"remember\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"recall\":{\"name\":\"recall\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise\",\"isStatic\":false,\"isPublic\":true},\"recallAll\":{\"name\":\"recallAll\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":true}],\"returnType\":\"Promise<Map<string>>\",\"isStatic\":false,\"isPublic\":true},\"forget\":{\"name\":\"forget\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"forgetScope\":{\"name\":\"forgetScope\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true},\"generateEmbeddings\":{\"name\":\"generateEmbeddings\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"GenerateEmbeddingsOptions\",\"optional\":true}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getEmbedding\":{\"name\":\"getEmbedding\",\"async\":true,\"parameters\":[{\"name\":\"fieldName\",\"type\":\"string\",\"optional\":false},{\"name\":\"model\",\"type\":\"string\",\"optional\":true}],\"returnType\":\"Promise<number[] | null>\",\"isStatic\":false,\"isPublic\":true},\"hasStaleEmbeddings\":{\"name\":\"hasStaleEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<boolean>\",\"isStatic\":false,\"isPublic\":true},\"clearEmbeddings\":{\"name\":\"clearEmbeddings\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"}},\"extends\":\"SmrtObject\",\"exportName\":\"SocialPost\",\"collectionExportName\":\"SocialPostCollection\",\"schema\":{\"tableName\":\"social_posts\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_posts\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"_meta_type\\\" TEXT NOT NULL,\\n \\\"_meta_data\\\" JSON,\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"tenant_id\\\" UUID,\\n \\\"social_account_id\\\" UUID,\\n \\\"video_content_id\\\" UUID,\\n \\\"content_id\\\" UUID,\\n \\\"post_type\\\" TEXT DEFAULT 'text',\\n \\\"media_url\\\" TEXT,\\n \\\"title\\\" TEXT,\\n \\\"description\\\" TEXT DEFAULT '',\\n \\\"hashtags\\\" JSON DEFAULT '[]',\\n \\\"link_url\\\" TEXT,\\n \\\"platform_post_id\\\" TEXT,\\n \\\"platform_url\\\" TEXT,\\n \\\"scheduled_at\\\" TIMESTAMP,\\n \\\"published_at\\\" TIMESTAMP,\\n \\\"status\\\" TEXT DEFAULT 'draft',\\n \\\"error_message\\\" TEXT,\\n \\\"analytics\\\" JSON,\\n \\\"analytics_last_synced_at\\\" TIMESTAMP\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"_meta_type\":{\"type\":\"TEXT\",\"notNull\":true},\"_meta_data\":{\"type\":\"JSON\",\"notNull\":false},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"tenant_id\":{\"type\":\"UUID\",\"referenceKind\":\"tenantId\",\"notNull\":false},\"social_account_id\":{\"type\":\"UUID\",\"referenceKind\":\"foreignKey\",\"notNull\":false},\"video_content_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"content_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"notNull\":false},\"post_type\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"text\"},\"media_url\":{\"type\":\"TEXT\",\"notNull\":false},\"title\":{\"type\":\"TEXT\",\"notNull\":false},\"description\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"\"},\"hashtags\":{\"type\":\"JSON\",\"notNull\":false,\"default\":[]},\"link_url\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_post_id\":{\"type\":\"TEXT\",\"notNull\":false},\"platform_url\":{\"type\":\"TEXT\",\"notNull\":false},\"scheduled_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"published_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false},\"status\":{\"type\":\"TEXT\",\"notNull\":false,\"default\":\"draft\"},\"error_message\":{\"type\":\"TEXT\",\"notNull\":false},\"analytics\":{\"type\":\"JSON\",\"notNull\":false},\"analytics_last_synced_at\":{\"type\":\"TIMESTAMP\",\"notNull\":false}},\"indexes\":[{\"name\":\"social_posts_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_posts_slug_context_meta_type_idx\",\"columns\":[\"slug\",\"context\",\"_meta_type\"],\"unique\":true},{\"name\":\"social_posts_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_posts_tenant_id_idx\",\"columns\":[\"tenant_id\"]}],\"version\":\"ded3699f\"}},\"@happyvertical/smrt-social:OAuthStateCollection\":{\"name\":\"oauthstatecollection\",\"className\":\"OAuthStateCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:OAuthStateCollection\",\"collection\":\"oauthstates\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/oauth-state-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"findByState\":{\"name\":\"findByState\",\"async\":true,\"parameters\":[{\"name\":\"state\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<OAuthState | null>\",\"isStatic\":false,\"isPublic\":true},\"findExpired\":{\"name\":\"findExpired\",\"async\":true,\"parameters\":[{\"name\":\"now\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<OAuthState[]>\",\"isStatic\":false,\"isPublic\":true},\"deleteExpired\":{\"name\":\"deleteExpired\",\"async\":true,\"parameters\":[{\"name\":\"now\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<number>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"OAuthState\",\"exportName\":\"OAuthStateCollection\",\"collectionExportName\":\"OAuthStateCollectionCollection\",\"schema\":{\"tableName\":\"oauth_state_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"oauth_state_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"oauth_state_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"oauth_state_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"bb1b91f9\"}},\"@happyvertical/smrt-social:SocialAccountCollection\":{\"name\":\"socialaccountcollection\",\"className\":\"SocialAccountCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialAccountCollection\",\"collection\":\"socialaccounts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/social-account-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"findActive\":{\"name\":\"findActive\",\"async\":true,\"parameters\":[{\"name\":\"platform\",\"type\":\"SocialPlatformType\",\"optional\":true}],\"returnType\":\"Promise<SocialAccount[]>\",\"isStatic\":false,\"isPublic\":true},\"findReady\":{\"name\":\"findReady\",\"async\":true,\"parameters\":[{\"name\":\"platform\",\"type\":\"SocialPlatformType\",\"optional\":true}],\"returnType\":\"Promise<SocialAccount[]>\",\"isStatic\":false,\"isPublic\":true},\"findNeedsAttention\":{\"name\":\"findNeedsAttention\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<SocialAccount[]>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"SocialAccount\",\"exportName\":\"SocialAccountCollection\",\"collectionExportName\":\"SocialAccountCollectionCollection\",\"schema\":{\"tableName\":\"social_account_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_account_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"social_account_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_account_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"eeae07d4\"}},\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshotCollection\":{\"name\":\"socialpostanalyticssnapshotcollection\",\"className\":\"SocialPostAnalyticsSnapshotCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPostAnalyticsSnapshotCollection\",\"collection\":\"socialpostanalyticssnapshots\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/social-post-analytics-snapshot-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"recordSnapshot\":{\"name\":\"recordSnapshot\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"object\",\"optional\":false}],\"returnType\":\"Promise<SocialPostAnalyticsSnapshot>\",\"isStatic\":false,\"isPublic\":true},\"findForPost\":{\"name\":\"findForPost\",\"async\":true,\"parameters\":[{\"name\":\"socialPostId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<SocialPostAnalyticsSnapshot[]>\",\"isStatic\":false,\"isPublic\":true},\"findLatestForPost\":{\"name\":\"findLatestForPost\",\"async\":true,\"parameters\":[{\"name\":\"socialPostId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<SocialPostAnalyticsSnapshot | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"SocialPostAnalyticsSnapshot\",\"exportName\":\"SocialPostAnalyticsSnapshotCollection\",\"collectionExportName\":\"SocialPostAnalyticsSnapshotCollectionCollection\",\"schema\":{\"tableName\":\"social_post_analytics_snapshot_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_post_analytics_snapshot_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"social_post_analytics_snapshot_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_post_analytics_snapshot_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"c98f7921\"}},\"@happyvertical/smrt-social:SocialPostCollection\":{\"name\":\"socialpostcollection\",\"className\":\"SocialPostCollection\",\"qualifiedName\":\"@happyvertical/smrt-social:SocialPostCollection\",\"collection\":\"socialposts\",\"filePath\":\"/home/runner/_work/smrt/smrt/packages/social/src/collections/social-post-collection.ts\",\"packageName\":\"@happyvertical/smrt-social\",\"fields\":{},\"methods\":{\"createDraft\":{\"name\":\"createDraft\",\"async\":true,\"parameters\":[{\"name\":\"options\",\"type\":\"CreateSocialPostDraftOptions\",\"optional\":false}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true},\"findByStatus\":{\"name\":\"findByStatus\",\"async\":true,\"parameters\":[{\"name\":\"status\",\"type\":\"PostStatus\",\"optional\":false}],\"returnType\":\"Promise<SocialPost[]>\",\"isStatic\":false,\"isPublic\":true},\"findForAccount\":{\"name\":\"findForAccount\",\"async\":true,\"parameters\":[{\"name\":\"socialAccountId\",\"type\":\"string\",\"optional\":false}],\"returnType\":\"Promise<SocialPost[]>\",\"isStatic\":false,\"isPublic\":true},\"findDueForPublish\":{\"name\":\"findDueForPublish\",\"async\":true,\"parameters\":[{\"name\":\"now\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<SocialPost[]>\",\"isStatic\":false,\"isPublic\":true},\"recordPublishSuccess\":{\"name\":\"recordPublishSuccess\",\"async\":true,\"parameters\":[{\"name\":\"post\",\"type\":\"SocialPost\",\"optional\":false},{\"name\":\"data\",\"type\":\"PublishSuccessData\",\"optional\":false}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true},\"recordPublishFailure\":{\"name\":\"recordPublishFailure\",\"async\":true,\"parameters\":[{\"name\":\"post\",\"type\":\"SocialPost\",\"optional\":false},{\"name\":\"error\",\"type\":\"Error | string\",\"optional\":false}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true},\"updateLatestAnalytics\":{\"name\":\"updateLatestAnalytics\",\"async\":true,\"parameters\":[{\"name\":\"post\",\"type\":\"SocialPost\",\"optional\":false},{\"name\":\"analytics\",\"type\":\"PostAnalytics\",\"optional\":false},{\"name\":\"syncedAt\",\"type\":\"Date\",\"optional\":true}],\"returnType\":\"Promise<SocialPost>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"SocialPost\",\"exportName\":\"SocialPostCollection\",\"collectionExportName\":\"SocialPostCollectionCollection\",\"schema\":{\"tableName\":\"social_post_collections\",\"ddl\":\"CREATE TABLE IF NOT EXISTS \\\"social_post_collections\\\" (\\n \\\"id\\\" UUID PRIMARY KEY NOT NULL,\\n \\\"slug\\\" TEXT NOT NULL,\\n \\\"context\\\" TEXT NOT NULL DEFAULT '',\\n \\\"created_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp,\\n \\\"updated_at\\\" TIMESTAMP NOT NULL DEFAULT current_timestamp\\n);\",\"columns\":{\"id\":{\"type\":\"UUID\",\"primaryKey\":true,\"referenceKind\":\"id\",\"notNull\":true},\"slug\":{\"type\":\"TEXT\",\"notNull\":true},\"context\":{\"type\":\"TEXT\",\"notNull\":true,\"default\":\"\"},\"created_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"},\"updated_at\":{\"type\":\"TIMESTAMP\",\"notNull\":true,\"default\":\"current_timestamp\"}},\"indexes\":[{\"name\":\"social_post_collections_id_idx\",\"columns\":[\"id\"]},{\"name\":\"social_post_collections_slug_context_idx\",\"columns\":[\"slug\",\"context\"],\"unique\":true}],\"version\":\"1baa42c4\"}}},\"moduleType\":\"smrt\",\"smrtDependencies\":[\"@happyvertical/smrt-content\",\"@happyvertical/smrt-core\",\"@happyvertical/smrt-secrets\",\"@happyvertical/smrt-tenancy\",\"@happyvertical/smrt-video\"]}"));
9
8
  //#endregion
10
9
  //#region src/oauth-state.ts
11
10
  var __defProp$3 = Object.defineProperty;
@@ -543,8 +542,8 @@ var SocialPost = class extends SmrtObject {
543
542
  }
544
543
  };
545
544
  __decorateClass$1([tenantId({ nullable: true })], SocialPost.prototype, "tenantId", 2);
546
- __decorateClass$1([foreignKey(() => SocialAccount)], SocialPost.prototype, "socialAccountId", 2);
547
- __decorateClass$1([foreignKey(() => VideoContent)], SocialPost.prototype, "videoContentId", 2);
545
+ __decorateClass$1([foreignKey(SocialAccount)], SocialPost.prototype, "socialAccountId", 2);
546
+ __decorateClass$1([crossPackageRef("@happyvertical/smrt-video:VideoContent")], SocialPost.prototype, "videoContentId", 2);
548
547
  __decorateClass$1([crossPackageRef("@happyvertical/smrt-content:Content")], SocialPost.prototype, "contentId", 2);
549
548
  SocialPost = __decorateClass$1([TenantScoped({ mode: "optional" }), smrt({
550
549
  tableStrategy: "sti",
@@ -586,7 +585,7 @@ var SocialPostAnalyticsSnapshot = class extends SmrtObject {
586
585
  }
587
586
  };
588
587
  __decorateClass([tenantId({ nullable: true })], SocialPostAnalyticsSnapshot.prototype, "tenantId", 2);
589
- __decorateClass([foreignKey(() => SocialPost)], SocialPostAnalyticsSnapshot.prototype, "socialPostId", 2);
588
+ __decorateClass([foreignKey(SocialPost)], SocialPostAnalyticsSnapshot.prototype, "socialPostId", 2);
590
589
  __decorateClass([field({ required: true })], SocialPostAnalyticsSnapshot.prototype, "platform", 2);
591
590
  __decorateClass([field({
592
591
  type: "json",
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["tenantId","secretService","secret"],"sources":["../src/__smrt-register__.ts","../src/oauth-state.ts","../src/collections/oauth-state-collection.ts","../src/social-account.ts","../src/collections/social-account-collection.ts","../src/social-post.ts","../src/social-post-analytics-snapshot.ts","../src/collections/social-post-analytics-snapshot-collection.ts","../src/collections/social-post-collection.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// During library builds, smrtPlugin replaces this entire module with generated\n// code that embeds the scanned manifest inline (#1506/#1507) — published dists\n// never resolve this URL, so downstream bundlers cannot break registration by\n// relocating the compiled module away from dist/manifest.json. The runtime\n// lookup below is the fallback for source-mode runs without that transform.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * OAuth State Model\n *\n * Manages temporary OAuth state for connecting social accounts.\n * Used to verify callback requests and prevent CSRF attacks.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { SocialPlatformType } from './social-account.js';\n\n/**\n * OAuth state creation options\n */\nexport interface OAuthStateOptions extends SmrtObjectOptions {\n /**\n * Platform being connected\n */\n platform?: SocialPlatformType;\n\n /**\n * CSRF state token\n */\n state?: string;\n\n /**\n * PKCE code verifier (for platforms that require it)\n */\n codeVerifier?: string | null;\n\n /**\n * Redirect URI used in the OAuth request\n */\n redirectUri?: string;\n\n /**\n * Requested OAuth scopes\n */\n scopes?: string[];\n\n /**\n * When this state expires\n */\n expiresAt?: Date;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Temporary OAuth state for social account connection\n *\n * OAuthState stores temporary data during the OAuth flow to:\n * - Verify callback requests match initiated requests (CSRF protection)\n * - Store PKCE code verifier for code exchange\n * - Track redirect URI and scopes for verification\n *\n * These records should be cleaned up after successful connection\n * or after expiration.\n *\n * @example\n * ```typescript\n * import { OAuthState } from '@happyvertical/smrt-social';\n *\n * // Create state when initiating OAuth\n * const state = new OAuthState({\n * platform: 'youtube',\n * state: crypto.randomUUID(),\n * codeVerifier: generatePKCEVerifier(),\n * redirectUri: 'https://app.example.com/oauth/callback',\n * scopes: ['youtube.upload', 'youtube.readonly'],\n * expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes\n * });\n * await state.save();\n *\n * // After successful callback, delete the state\n * await state.delete();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: false,\n cli: true,\n})\nexport class OAuthState extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Platform being connected\n */\n platform: SocialPlatformType = 'youtube';\n\n /**\n * CSRF state token\n * This is sent to the OAuth provider and verified on callback\n */\n state: string = '';\n\n /**\n * PKCE code verifier\n * Required for platforms using PKCE (YouTube, etc.)\n */\n codeVerifier: string | null = null;\n\n /**\n * Redirect URI used in the OAuth request\n * Must match on callback for verification\n */\n redirectUri: string = '';\n\n /**\n * Requested OAuth scopes\n */\n scopes: string[] = [];\n\n /**\n * When this state expires\n * States should be short-lived (10 minutes typical)\n */\n expiresAt: Date = new Date(Date.now() + 10 * 60 * 1000);\n\n constructor(options: OAuthStateOptions = {}) {\n super(options);\n\n if (options.platform !== undefined) this.platform = options.platform;\n if (options.state !== undefined) this.state = options.state;\n if (options.codeVerifier !== undefined)\n this.codeVerifier = options.codeVerifier;\n if (options.redirectUri !== undefined)\n this.redirectUri = options.redirectUri;\n if (options.scopes !== undefined) this.scopes = options.scopes;\n if (options.expiresAt !== undefined) this.expiresAt = options.expiresAt;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if the state has expired\n */\n get isExpired(): boolean {\n return Date.now() >= this.expiresAt.getTime();\n }\n\n /**\n * Check if the state is still valid\n */\n get isValid(): boolean {\n return !this.isExpired && this.state.length > 0;\n }\n\n /**\n * Verify a callback state matches this record\n */\n verifyState(callbackState: string): boolean {\n return this.isValid && this.state === callbackState;\n }\n\n /**\n * Generate a new random state token\n */\n static generateState(): string {\n return crypto.randomUUID();\n }\n\n /**\n * Generate a PKCE code verifier\n * Returns a 43-128 character random string\n */\n static generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join(\n '',\n );\n }\n\n /**\n * Generate PKCE code challenge from verifier (S256 method)\n * Note: This requires async crypto operations\n */\n static async generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest('SHA-256', data);\n const base64 = btoa(String.fromCharCode(...new Uint8Array(digest)));\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { OAuthState } from '../oauth-state.js';\n\nexport class OAuthStateCollection extends SmrtCollection<OAuthState> {\n static readonly _itemClass = OAuthState;\n\n async findByState(state: string): Promise<OAuthState | null> {\n return this.get({ state });\n }\n\n async findExpired(now: Date = new Date()): Promise<OAuthState[]> {\n return this.list({\n where: { 'expiresAt <=': now },\n orderBy: 'expiresAt ASC',\n });\n }\n\n async deleteExpired(now: Date = new Date()): Promise<number> {\n const expired = await this.findExpired(now);\n await Promise.all(expired.map((state) => state.delete()));\n return expired.length;\n }\n}\n","/**\n * Social Account Model\n *\n * Manages connected social media platform accounts for publishing.\n * Stores OAuth credentials and account settings.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { SecretService } from '@happyvertical/smrt-secrets';\nimport {\n getCurrentTenant,\n TenantScoped,\n tenantId,\n withTenant,\n} from '@happyvertical/smrt-tenancy';\nimport { getSocialPlatformSetup } from './server.js';\n\n/**\n * Supported social platforms\n */\nexport type SocialPlatformType =\n | 'youtube'\n | 'threads'\n | 'x'\n | 'bluesky'\n | 'facebook';\n\n/**\n * Account connection status\n */\nexport type AccountStatus =\n | 'connected'\n | 'disconnected'\n | 'expired'\n | 'missing_permissions'\n | 'error';\n\n/**\n * Link behavior for posts with links\n */\nexport type LinkBehavior =\n | 'description'\n | 'inline'\n | 'attachment'\n | 'reply'\n | 'none';\n\n/**\n * Controls how far publish operations are allowed to go.\n */\nexport type PublishMode =\n | 'dry_run'\n | 'stage_remote'\n | 'private_or_scheduled'\n | 'public';\n\n/**\n * Social account creation options\n */\nexport interface SocialAccountOptions extends SmrtObjectOptions {\n /**\n * Human-readable name for the account\n */\n name?: string;\n\n /**\n * Social platform type\n */\n platform?: SocialPlatformType;\n\n /**\n * Platform-specific user ID\n */\n platformUserId?: string | null;\n\n /**\n * Platform username/handle\n */\n platformUsername?: string | null;\n\n /**\n * Profile URL on the platform\n */\n platformUrl?: string | null;\n\n /**\n * Deprecated raw OAuth access token\n */\n accessToken?: string | null;\n\n /**\n * Deprecated raw OAuth refresh token\n */\n refreshToken?: string | null;\n\n /**\n * Secret name containing the full platform credential payload\n */\n credentialSecretId?: string | null;\n\n /**\n * Secret name containing the OAuth access token\n */\n accessTokenSecretName?: string | null;\n\n /**\n * Secret name containing the OAuth refresh token\n */\n refreshTokenSecretName?: string | null;\n\n /**\n * Token expiration time\n */\n tokenExpiresAt?: Date | null;\n\n /**\n * Whether the account is active\n * @default true\n */\n isActive?: boolean;\n\n /**\n * Default hashtags to add to posts\n */\n defaultHashtags?: string[];\n\n /**\n * Granted OAuth scopes or platform permissions\n */\n scopes?: string[];\n\n /**\n * Required permissions that still need approval/granting\n */\n missingPermissions?: string[];\n\n /**\n * How to handle links in posts\n * @default 'description'\n */\n linkBehavior?: LinkBehavior;\n\n /**\n * Safety mode for publish operations.\n * @default 'dry_run'\n */\n publishMode?: PublishMode;\n\n /**\n * Separate latch required before public publishing can happen.\n * @default false\n */\n publicPublishingAllowed?: boolean;\n\n /**\n * Account connection status\n * @default 'connected'\n */\n status?: AccountStatus;\n\n /**\n * Error message if status is 'error'\n */\n errorMessage?: string | null;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Connected social media account for publishing\n *\n * SocialAccount represents a connected social platform account\n * with OAuth credentials and publishing settings. Accounts can\n * be used to publish content to multiple platforms.\n *\n * @example\n * ```typescript\n * import { SocialAccount } from '@happyvertical/smrt-social';\n *\n * const account = new SocialAccount({\n * name: 'Bentley News YouTube',\n * platform: 'youtube',\n * platformUserId: 'UC...',\n * platformUsername: 'Bentley News',\n * accessToken: '...encrypted...',\n * refreshToken: '...encrypted...',\n * tokenExpiresAt: new Date('2026-02-25'),\n * defaultHashtags: ['news', 'local', 'bentley'],\n * linkBehavior: 'description',\n * });\n * await account.save();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class SocialAccount extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Human-readable name for the account\n */\n name: string = '';\n\n /**\n * Social platform type\n */\n platform: SocialPlatformType = 'youtube';\n\n /**\n * Platform-specific user ID\n */\n platformUserId: string | null = null;\n\n /**\n * Platform username/handle\n */\n platformUsername: string | null = null;\n\n /**\n * Profile URL on the platform\n */\n platformUrl: string | null = null;\n\n /**\n * Deprecated raw OAuth access token.\n * Prefer credentialSecretId/accessTokenSecretName.\n */\n accessToken: string | null = null;\n\n /**\n * Deprecated raw OAuth refresh token.\n * Prefer credentialSecretId/refreshTokenSecretName.\n */\n refreshToken: string | null = null;\n\n /**\n * Secret name containing the complete platform credential payload.\n */\n credentialSecretId: string | null = null;\n\n /**\n * Secret name containing only the access token.\n */\n accessTokenSecretName: string | null = null;\n\n /**\n * Secret name containing only the refresh token.\n */\n refreshTokenSecretName: string | null = null;\n\n /**\n * Token expiration time\n */\n tokenExpiresAt: Date | null = null;\n\n /**\n * Whether the account is active\n */\n isActive: boolean = true;\n\n /**\n * Default hashtags to add to posts\n */\n defaultHashtags: string[] = [];\n\n /**\n * Granted OAuth scopes or platform permissions.\n */\n scopes: string[] = [];\n\n /**\n * Required permissions that still need app review or user grant.\n */\n missingPermissions: string[] = [];\n\n /**\n * How to handle links in posts\n * - description: Include link in post body/description\n * - reply: Post link as a reply (better for X algorithm)\n * - none: Don't include link\n */\n linkBehavior: LinkBehavior = 'description';\n\n /**\n * Safety mode for publish operations.\n */\n publishMode: PublishMode = 'dry_run';\n\n /**\n * Separate latch required before public publishing is allowed.\n */\n publicPublishingAllowed: boolean = false;\n\n /**\n * Account connection status\n */\n status: AccountStatus = 'connected';\n\n /**\n * Error message if status is 'error'\n */\n errorMessage: string | null = null;\n\n constructor(options: SocialAccountOptions = {}) {\n super(options);\n\n if (options.name !== undefined) this.name = options.name;\n if (options.platform !== undefined) this.platform = options.platform;\n if (options.platformUserId !== undefined)\n this.platformUserId = options.platformUserId;\n if (options.platformUsername !== undefined)\n this.platformUsername = options.platformUsername;\n if (options.platformUrl !== undefined)\n this.platformUrl = options.platformUrl;\n if (options.accessToken !== undefined)\n this.accessToken = options.accessToken;\n if (options.refreshToken !== undefined)\n this.refreshToken = options.refreshToken;\n if (options.credentialSecretId !== undefined)\n this.credentialSecretId = options.credentialSecretId;\n if (options.accessTokenSecretName !== undefined)\n this.accessTokenSecretName = options.accessTokenSecretName;\n if (options.refreshTokenSecretName !== undefined)\n this.refreshTokenSecretName = options.refreshTokenSecretName;\n if (options.tokenExpiresAt !== undefined)\n this.tokenExpiresAt = options.tokenExpiresAt;\n if (options.isActive !== undefined) this.isActive = options.isActive;\n if (options.defaultHashtags !== undefined)\n this.defaultHashtags = options.defaultHashtags;\n if (options.scopes !== undefined) this.scopes = options.scopes;\n if (options.missingPermissions !== undefined)\n this.missingPermissions = options.missingPermissions;\n if (options.linkBehavior !== undefined)\n this.linkBehavior = options.linkBehavior;\n if (options.publishMode !== undefined)\n this.publishMode = options.publishMode;\n if (options.publicPublishingAllowed !== undefined)\n this.publicPublishingAllowed = options.publicPublishingAllowed;\n if (options.status !== undefined) this.status = options.status;\n if (options.errorMessage !== undefined)\n this.errorMessage = options.errorMessage;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n\n if (options.platform !== undefined) {\n const setup = getSocialPlatformSetup(this.platform);\n if (options.linkBehavior === undefined) {\n this.linkBehavior = setup.defaultLinkBehavior;\n }\n if (options.publishMode === undefined) {\n this.publishMode = setup.defaultPublishMode;\n }\n }\n }\n\n /**\n * Social accounts need a slug identity that is scoped by tenant and platform.\n * A newsroom may connect `@localnews` on X, YouTube, Threads, and Facebook;\n * the generic name-derived slug would make those accounts overwrite each\n * other through SMRT's slug/context upsert identity.\n */\n async getSlug(): Promise<string | null | undefined> {\n if (!this.slug) {\n const identity =\n this.platformUserId || this.platformUsername || this.name || this.id;\n if (!identity) {\n return this.slug;\n }\n\n const source = [\n this.tenantId ? `tenant-${this.tenantId}` : 'no-tenant',\n this.platform,\n identity,\n ]\n .filter(Boolean)\n .join('-');\n\n this.slug = source\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '');\n }\n\n return this.slug;\n }\n\n /**\n * Check if the token is expired or will expire soon\n */\n get isTokenExpired(): boolean {\n if (!this.tokenExpiresAt) return false;\n // Expire 5 minutes early to allow for refresh\n const expiryBuffer = 5 * 60 * 1000;\n return Date.now() >= this.tokenExpiresAt.getTime() - expiryBuffer;\n }\n\n /**\n * Check if the account needs attention (expired or error)\n */\n get needsAttention(): boolean {\n return (\n this.status !== 'connected' ||\n this.isTokenExpired ||\n this.missingPermissions.length > 0 ||\n (this.publishMode === 'public' && !this.publicPublishingAllowed)\n );\n }\n\n /**\n * Check if the account is ready for publishing\n */\n get isReady(): boolean {\n return (\n this.isActive &&\n this.status === 'connected' &&\n this.hasCredentials &&\n this.missingPermissions.length === 0 &&\n !this.isTokenExpired &&\n (this.publishMode !== 'public' || this.publicPublishingAllowed)\n );\n }\n\n /**\n * Effective publish mode after applying the public-publishing latch.\n */\n get effectivePublishMode(): PublishMode {\n if (this.publishMode === 'public' && !this.publicPublishingAllowed) {\n return 'dry_run';\n }\n return this.publishMode;\n }\n\n /**\n * Check whether any usable credential reference exists.\n */\n get hasCredentials(): boolean {\n return Boolean(\n this.credentialSecretId || this.accessTokenSecretName || this.accessToken,\n );\n }\n\n /**\n * Store all platform credentials in smrt-secrets as a single JSON payload.\n */\n async setCredentials(\n credentials: Record<string, unknown>,\n options: {\n description?: string;\n category?: string;\n } = {},\n ): Promise<void> {\n if (!this.id) {\n this.id = randomUUID();\n }\n\n const secretName = this.credentialSecretId ?? `social-account-${this.id}`;\n const tenantId = this.requireCredentialTenantId(\n 'store social account credentials',\n );\n const secretService = await SecretService.create({ db: this.db });\n\n await secretService.storeForTenant(\n tenantId,\n secretName,\n JSON.stringify(credentials),\n {\n description: options.description ?? `Credentials for ${this.name}`,\n category: options.category ?? 'social',\n },\n );\n\n this.credentialSecretId = secretName;\n\n await this.withCredentialTenantContext(async () => {\n await this.save();\n });\n }\n\n /**\n * Retrieve platform credentials from smrt-secrets, falling back to deprecated fields.\n */\n async getCredentials(): Promise<Record<string, unknown> | null> {\n if (!this.credentialSecretId) {\n if (this.accessTokenSecretName || this.refreshTokenSecretName) {\n const tenantId = this.requireCredentialTenantId(\n 'retrieve social account credentials',\n );\n const secretService = await SecretService.create({ db: this.db });\n const credentials: Record<string, unknown> = {};\n\n if (this.accessTokenSecretName) {\n const secret = await secretService.retrieveForTenant(\n tenantId,\n this.accessTokenSecretName,\n );\n credentials.accessToken = secret.value;\n }\n\n if (this.refreshTokenSecretName) {\n const secret = await secretService.retrieveForTenant(\n tenantId,\n this.refreshTokenSecretName,\n );\n credentials.refreshToken = secret.value;\n }\n\n return credentials;\n }\n\n if (!this.accessToken && !this.refreshToken) return null;\n return {\n accessToken: this.accessToken,\n refreshToken: this.refreshToken,\n };\n }\n\n const credentialSecretId = this.credentialSecretId;\n const tenantId = this.requireCredentialTenantId(\n 'retrieve social account credentials',\n );\n const secretService = await SecretService.create({ db: this.db });\n const secret = await secretService.retrieveForTenant(\n tenantId,\n credentialSecretId,\n );\n return JSON.parse(secret.value);\n }\n\n private async withCredentialTenantContext<T>(\n fn: () => Promise<T>,\n ): Promise<T> {\n const tenantId = this.getCredentialTenantId();\n const currentTenantId = getCurrentTenant()?.tenantId;\n\n if (!tenantId || currentTenantId === tenantId) {\n return fn();\n }\n\n return withTenant({ tenantId }, fn);\n }\n\n private getCredentialTenantId(): string | null {\n if (this.tenantId) {\n return this.tenantId;\n }\n\n return getCurrentTenant()?.tenantId ?? null;\n }\n\n private requireCredentialTenantId(action: string): string {\n const tenantId = this.getCredentialTenantId();\n if (!tenantId) {\n throw new Error(`Tenant context required to ${action}.`);\n }\n return tenantId;\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { SocialAccount, type SocialPlatformType } from '../social-account.js';\n\nexport class SocialAccountCollection extends SmrtCollection<SocialAccount> {\n static readonly _itemClass = SocialAccount;\n\n async findActive(platform?: SocialPlatformType): Promise<SocialAccount[]> {\n const accounts = await this.list({\n where: {\n isActive: true,\n ...(platform ? { platform } : {}),\n },\n orderBy: 'name ASC',\n });\n\n return accounts;\n }\n\n async findReady(platform?: SocialPlatformType): Promise<SocialAccount[]> {\n const accounts = await this.findActive(platform);\n return accounts.filter((account) => account.isReady);\n }\n\n async findNeedsAttention(): Promise<SocialAccount[]> {\n const accounts = await this.list({\n where: { isActive: true },\n orderBy: 'name ASC',\n });\n return accounts.filter((account) => account.needsAttention);\n }\n}\n","/**\n * Social Post Model\n *\n * Manages posts published or scheduled to social media platforms.\n * Tracks publishing status and engagement analytics.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { VideoContent } from '@happyvertical/smrt-video';\nimport { SocialAccount } from './social-account.js';\n\n/**\n * Post status\n */\nexport type PostStatus =\n | 'draft'\n | 'pending_approval'\n | 'approved'\n | 'scheduled'\n | 'publishing'\n | 'dry_run'\n | 'staged'\n | 'published'\n | 'failed'\n | 'cancelled';\n\n/**\n * Social post type\n */\nexport type SocialPostType = 'text' | 'link' | 'image' | 'video';\n\n/**\n * Post analytics\n */\nexport interface PostAnalytics {\n /**\n * View/impression count\n */\n views?: number;\n\n /**\n * Impression count when the platform distinguishes it from views\n */\n impressions?: number;\n\n /**\n * Like/favorite count\n */\n likes?: number;\n\n /**\n * Comment count\n */\n comments?: number;\n\n /**\n * Share/repost count\n */\n shares?: number;\n\n /**\n * Link click count\n */\n clicks?: number;\n\n /**\n * Raw platform analytics payload\n */\n raw?: unknown;\n\n /**\n * When analytics were last updated\n */\n lastUpdated?: Date;\n}\n\n/**\n * Social post creation options\n */\nexport interface SocialPostOptions extends SmrtObjectOptions {\n /**\n * Social account to publish to\n */\n socialAccountId?: string | null;\n\n /**\n * Video content to publish\n */\n videoContentId?: string | null;\n\n /**\n * Generic content ID (for non-video content)\n */\n contentId?: string | null;\n\n /**\n * High-level post type\n */\n postType?: SocialPostType;\n\n /**\n * Public media URL for platforms that cannot upload buffers\n */\n mediaUrl?: string | null;\n\n /**\n * Post title (for platforms that support it)\n */\n title?: string | null;\n\n /**\n * Post description/caption\n */\n description?: string;\n\n /**\n * Hashtags to include\n */\n hashtags?: string[];\n\n /**\n * Link URL to include\n */\n linkUrl?: string | null;\n\n /**\n * Platform-specific post ID (after publishing)\n */\n platformPostId?: string | null;\n\n /**\n * Public post URL (after publishing)\n */\n platformUrl?: string | null;\n\n /**\n * Scheduled publish time\n */\n scheduledAt?: Date | null;\n\n /**\n * Actual publish time\n */\n publishedAt?: Date | null;\n\n /**\n * Post status\n * @default 'draft'\n */\n status?: PostStatus;\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage?: string | null;\n\n /**\n * Engagement analytics\n */\n analytics?: PostAnalytics;\n\n /**\n * When analytics were last synced\n */\n analyticsLastSyncedAt?: Date | null;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Social media post for multi-platform publishing\n *\n * SocialPost represents a post published or scheduled to a social\n * platform. It tracks publishing status and engagement analytics,\n * and can reference VideoContent for video posts.\n *\n * @example\n * ```typescript\n * import { SocialPost } from '@happyvertical/smrt-social';\n *\n * const post = new SocialPost({\n * socialAccountId: 'account-123',\n * videoContentId: 'video-456',\n * title: 'Breaking News from Bentley',\n * description: 'Latest updates from the town council meeting.',\n * hashtags: ['news', 'local', 'bentley'],\n * linkUrl: 'https://example.com/article',\n * scheduledAt: new Date('2026-01-26T18:00:00Z'),\n * });\n * await post.save();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class SocialPost extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Social account to publish to\n */\n @foreignKey(() => SocialAccount)\n socialAccountId: string | null = null;\n\n /**\n * Video content to publish\n */\n @foreignKey(() => VideoContent)\n videoContentId: string | null = null;\n\n /**\n * Generic content ID (for non-video content)\n */\n @crossPackageRef('@happyvertical/smrt-content:Content')\n contentId: string | null = null;\n\n /**\n * High-level post type\n */\n postType: SocialPostType = 'text';\n\n /**\n * Public media URL for platforms that require URL media publishing\n */\n mediaUrl: string | null = null;\n\n /**\n * Post title (for platforms that support it)\n */\n title: string | null = null;\n\n /**\n * Post description/caption\n */\n description: string = '';\n\n /**\n * Hashtags to include\n */\n hashtags: string[] = [];\n\n /**\n * Link URL to include in the post\n */\n linkUrl: string | null = null;\n\n /**\n * Platform-specific post ID (set after publishing)\n */\n platformPostId: string | null = null;\n\n /**\n * Public post URL (set after publishing)\n */\n platformUrl: string | null = null;\n\n /**\n * Scheduled publish time\n * If set, post will be scheduled instead of published immediately\n */\n scheduledAt: Date | null = null;\n\n /**\n * Actual publish time\n */\n publishedAt: Date | null = null;\n\n /**\n * Post status\n * - draft: Not yet submitted for publishing\n * - pending_approval: Awaiting editorial approval\n * - approved: Approved and ready to publish\n * - scheduled: Queued for future publishing\n * - publishing: Currently being published\n * - dry_run: Payload was validated without remote write\n * - staged: Non-public platform object/container was created\n * - published: Successfully published\n * - failed: Publishing failed\n * - cancelled: Publishing was cancelled\n */\n status: PostStatus = 'draft';\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage: string | null = null;\n\n /**\n * Engagement analytics\n */\n analytics: PostAnalytics = {};\n\n /**\n * When analytics were last synced\n */\n analyticsLastSyncedAt: Date | null = null;\n\n constructor(options: SocialPostOptions = {}) {\n super(options);\n\n if (options.socialAccountId !== undefined)\n this.socialAccountId = options.socialAccountId;\n if (options.videoContentId !== undefined)\n this.videoContentId = options.videoContentId;\n if (options.contentId !== undefined) this.contentId = options.contentId;\n if (options.postType !== undefined) this.postType = options.postType;\n if (options.mediaUrl !== undefined) this.mediaUrl = options.mediaUrl;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.hashtags !== undefined) this.hashtags = options.hashtags;\n if (options.linkUrl !== undefined) this.linkUrl = options.linkUrl;\n if (options.platformPostId !== undefined)\n this.platformPostId = options.platformPostId;\n if (options.platformUrl !== undefined)\n this.platformUrl = options.platformUrl;\n if (options.scheduledAt !== undefined)\n this.scheduledAt = options.scheduledAt;\n if (options.publishedAt !== undefined)\n this.publishedAt = options.publishedAt;\n if (options.status !== undefined) this.status = options.status;\n if (options.errorMessage !== undefined)\n this.errorMessage = options.errorMessage;\n if (options.analytics !== undefined) this.analytics = options.analytics;\n if (options.analyticsLastSyncedAt !== undefined)\n this.analyticsLastSyncedAt = options.analyticsLastSyncedAt;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if the post is scheduled for future publishing\n */\n get isScheduled(): boolean {\n return this.status === 'scheduled' && this.scheduledAt !== null;\n }\n\n /**\n * Check if the post has been published\n */\n get isPublished(): boolean {\n return this.status === 'published';\n }\n\n /**\n * Check if the post can be edited (draft or failed)\n */\n get isEditable(): boolean {\n return (\n this.status === 'draft' ||\n this.status === 'pending_approval' ||\n this.status === 'failed'\n );\n }\n\n /**\n * Check if the post is due for publishing now.\n */\n get isDueForPublish(): boolean {\n if (this.status !== 'approved' && this.status !== 'scheduled') {\n return false;\n }\n return !this.scheduledAt || this.scheduledAt.getTime() <= Date.now();\n }\n\n /**\n * Get formatted hashtag string\n */\n get hashtagString(): string {\n return this.hashtags\n .map((tag) => (tag.startsWith('#') ? tag : `#${tag}`))\n .join(' ');\n }\n\n /**\n * Get the full post text with hashtags\n */\n get fullText(): string {\n const parts = [this.description];\n if (this.hashtags.length > 0) {\n parts.push(this.hashtagString);\n }\n return parts.join('\\n\\n');\n }\n}\n","/**\n * Social Post Analytics Snapshot Model\n *\n * Stores timestamped normalized and raw platform analytics payloads.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { SocialPlatformType } from './social-account.js';\nimport { type PostAnalytics, SocialPost } from './social-post.js';\n\nexport type RawAnalyticsPayload = Record<string, unknown> | unknown[] | null;\n\nexport interface SocialPostAnalyticsSnapshotOptions extends SmrtObjectOptions {\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n\n /**\n * Social post being measured\n */\n socialPostId?: string | null;\n\n /**\n * Platform that produced this snapshot\n */\n platform?: SocialPlatformType | null;\n\n /**\n * Normalized platform analytics.\n */\n analytics?: PostAnalytics;\n\n /**\n * Raw platform payload\n */\n raw?: RawAnalyticsPayload;\n\n /**\n * When the platform data was captured\n */\n capturedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class SocialPostAnalyticsSnapshot extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey(() => SocialPost)\n socialPostId: string | null = null;\n\n @field({ required: true })\n platform: SocialPlatformType | null = null;\n\n analytics: PostAnalytics = {};\n\n @field({ type: 'json', nullable: true })\n raw: RawAnalyticsPayload = null;\n\n capturedAt: Date = new Date();\n\n constructor(options: SocialPostAnalyticsSnapshotOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.socialPostId !== undefined)\n this.socialPostId = options.socialPostId;\n if (options.platform !== undefined) this.platform = options.platform;\n if (options.analytics !== undefined) this.analytics = options.analytics;\n if (options.raw !== undefined) this.raw = options.raw;\n if (options.capturedAt !== undefined) this.capturedAt = options.capturedAt;\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport type { SocialPlatformType } from '../social-account.js';\nimport type { PostAnalytics } from '../social-post.js';\nimport {\n type RawAnalyticsPayload,\n SocialPostAnalyticsSnapshot,\n} from '../social-post-analytics-snapshot.js';\n\nfunction isRawAnalyticsPayload(value: unknown): value is RawAnalyticsPayload {\n return (\n value === null ||\n Array.isArray(value) ||\n (typeof value === 'object' && value !== null)\n );\n}\n\nexport class SocialPostAnalyticsSnapshotCollection extends SmrtCollection<SocialPostAnalyticsSnapshot> {\n static readonly _itemClass = SocialPostAnalyticsSnapshot;\n\n async recordSnapshot(options: {\n socialPostId: string;\n platform: SocialPlatformType;\n metrics: PostAnalytics;\n raw?: RawAnalyticsPayload;\n capturedAt?: Date;\n tenantId?: string | null;\n }): Promise<SocialPostAnalyticsSnapshot> {\n const snapshot = await this.create({\n socialPostId: options.socialPostId,\n platform: options.platform,\n analytics: options.metrics,\n raw:\n options.raw ??\n (isRawAnalyticsPayload(options.metrics.raw)\n ? options.metrics.raw\n : null),\n capturedAt: options.capturedAt ?? new Date(),\n tenantId: options.tenantId,\n });\n return snapshot;\n }\n\n async findForPost(\n socialPostId: string,\n ): Promise<SocialPostAnalyticsSnapshot[]> {\n return this.list({\n where: { socialPostId },\n orderBy: 'capturedAt DESC',\n });\n }\n\n async findLatestForPost(\n socialPostId: string,\n ): Promise<SocialPostAnalyticsSnapshot | null> {\n const snapshots = await this.findForPost(socialPostId);\n return snapshots[0] ?? null;\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n type PostAnalytics,\n type PostStatus,\n SocialPost,\n type SocialPostType,\n} from '../social-post.js';\n\nexport interface CreateSocialPostDraftOptions {\n socialAccountId: string;\n contentId?: string | null;\n videoContentId?: string | null;\n postType?: SocialPostType;\n title?: string | null;\n description?: string;\n hashtags?: string[];\n linkUrl?: string | null;\n mediaUrl?: string | null;\n scheduledAt?: Date | null;\n tenantId?: string | null;\n}\n\nexport interface PublishSuccessData {\n platformPostId: string;\n platformUrl: string;\n publishedAt?: Date;\n status?: PostStatus;\n}\n\nexport class SocialPostCollection extends SmrtCollection<SocialPost> {\n static readonly _itemClass = SocialPost;\n\n async createDraft(\n options: CreateSocialPostDraftOptions,\n ): Promise<SocialPost> {\n return this.create({\n ...options,\n postType:\n options.postType ??\n (options.videoContentId || options.mediaUrl\n ? 'video'\n : options.linkUrl\n ? 'link'\n : 'text'),\n status: options.scheduledAt ? 'scheduled' : 'draft',\n });\n }\n\n async findByStatus(status: PostStatus): Promise<SocialPost[]> {\n return this.list({ where: { status }, orderBy: 'scheduledAt ASC' });\n }\n\n async findForAccount(socialAccountId: string): Promise<SocialPost[]> {\n return this.list({\n where: { socialAccountId },\n orderBy: 'created_at DESC',\n });\n }\n\n async findDueForPublish(now: Date = new Date()): Promise<SocialPost[]> {\n const [approved, scheduled] = await Promise.all([\n this.list({\n where: { status: 'approved' },\n orderBy: 'scheduledAt ASC',\n }),\n this.list({\n where: { status: 'scheduled', 'scheduledAt <=': now },\n orderBy: 'scheduledAt ASC',\n }),\n ]);\n\n return [\n ...approved.filter((post) => post.isDueForPublish),\n ...scheduled,\n ].sort(\n (a, b) =>\n (a.scheduledAt?.getTime() ?? 0) - (b.scheduledAt?.getTime() ?? 0),\n );\n }\n\n async recordPublishSuccess(\n post: SocialPost,\n data: PublishSuccessData,\n ): Promise<SocialPost> {\n const status = data.status ?? 'published';\n post.platformPostId = data.platformPostId;\n post.platformUrl = data.platformUrl;\n if (status === 'published') {\n post.publishedAt = data.publishedAt ?? post.publishedAt ?? new Date();\n }\n post.status = status;\n post.errorMessage = null;\n await post.save();\n return post;\n }\n\n async recordPublishFailure(\n post: SocialPost,\n error: Error | string,\n ): Promise<SocialPost> {\n post.status = 'failed';\n post.errorMessage = formatPublishError(error);\n await post.save();\n return post;\n }\n\n async updateLatestAnalytics(\n post: SocialPost,\n analytics: PostAnalytics,\n syncedAt: Date = new Date(),\n ): Promise<SocialPost> {\n post.analytics = {\n ...analytics,\n lastUpdated: analytics.lastUpdated ?? syncedAt,\n };\n post.analyticsLastSyncedAt = syncedAt;\n await post.save();\n return post;\n }\n}\n\nfunction formatPublishError(error: Error | string): string {\n if (typeof error === 'string') {\n return error;\n }\n\n const details = [error.message];\n const code = (error as Error & { code?: unknown }).code;\n if (code !== undefined) {\n details.push(`code=${String(code)}`);\n }\n if (error.stack) {\n details.push(error.stack);\n }\n return details.join('\\n');\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["tenantId","secretService","secret"],"sources":["../src/__smrt-register__.ts","../src/oauth-state.ts","../src/collections/oauth-state-collection.ts","../src/social-account.ts","../src/collections/social-account-collection.ts","../src/social-post.ts","../src/social-post-analytics-snapshot.ts","../src/collections/social-post-analytics-snapshot-collection.ts","../src/collections/social-post-collection.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// During library builds, smrtPlugin replaces this entire module with generated\n// code that embeds the scanned manifest inline (#1506/#1507) — published dists\n// never resolve this URL, so downstream bundlers cannot break registration by\n// relocating the compiled module away from dist/manifest.json. The runtime\n// lookup below is the fallback for source-mode runs without that transform.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * OAuth State Model\n *\n * Manages temporary OAuth state for connecting social accounts.\n * Used to verify callback requests and prevent CSRF attacks.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { SocialPlatformType } from './social-account.js';\n\n/**\n * OAuth state creation options\n */\nexport interface OAuthStateOptions extends SmrtObjectOptions {\n /**\n * Platform being connected\n */\n platform?: SocialPlatformType;\n\n /**\n * CSRF state token\n */\n state?: string;\n\n /**\n * PKCE code verifier (for platforms that require it)\n */\n codeVerifier?: string | null;\n\n /**\n * Redirect URI used in the OAuth request\n */\n redirectUri?: string;\n\n /**\n * Requested OAuth scopes\n */\n scopes?: string[];\n\n /**\n * When this state expires\n */\n expiresAt?: Date;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Temporary OAuth state for social account connection\n *\n * OAuthState stores temporary data during the OAuth flow to:\n * - Verify callback requests match initiated requests (CSRF protection)\n * - Store PKCE code verifier for code exchange\n * - Track redirect URI and scopes for verification\n *\n * These records should be cleaned up after successful connection\n * or after expiration.\n *\n * @example\n * ```typescript\n * import { OAuthState } from '@happyvertical/smrt-social';\n *\n * // Create state when initiating OAuth\n * const state = new OAuthState({\n * platform: 'youtube',\n * state: crypto.randomUUID(),\n * codeVerifier: generatePKCEVerifier(),\n * redirectUri: 'https://app.example.com/oauth/callback',\n * scopes: ['youtube.upload', 'youtube.readonly'],\n * expiresAt: new Date(Date.now() + 10 * 60 * 1000), // 10 minutes\n * });\n * await state.save();\n *\n * // After successful callback, delete the state\n * await state.delete();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: false,\n cli: true,\n})\nexport class OAuthState extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Platform being connected\n */\n platform: SocialPlatformType = 'youtube';\n\n /**\n * CSRF state token\n * This is sent to the OAuth provider and verified on callback\n */\n state: string = '';\n\n /**\n * PKCE code verifier\n * Required for platforms using PKCE (YouTube, etc.)\n */\n codeVerifier: string | null = null;\n\n /**\n * Redirect URI used in the OAuth request\n * Must match on callback for verification\n */\n redirectUri: string = '';\n\n /**\n * Requested OAuth scopes\n */\n scopes: string[] = [];\n\n /**\n * When this state expires\n * States should be short-lived (10 minutes typical)\n */\n expiresAt: Date = new Date(Date.now() + 10 * 60 * 1000);\n\n constructor(options: OAuthStateOptions = {}) {\n super(options);\n\n if (options.platform !== undefined) this.platform = options.platform;\n if (options.state !== undefined) this.state = options.state;\n if (options.codeVerifier !== undefined)\n this.codeVerifier = options.codeVerifier;\n if (options.redirectUri !== undefined)\n this.redirectUri = options.redirectUri;\n if (options.scopes !== undefined) this.scopes = options.scopes;\n if (options.expiresAt !== undefined) this.expiresAt = options.expiresAt;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if the state has expired\n */\n get isExpired(): boolean {\n return Date.now() >= this.expiresAt.getTime();\n }\n\n /**\n * Check if the state is still valid\n */\n get isValid(): boolean {\n return !this.isExpired && this.state.length > 0;\n }\n\n /**\n * Verify a callback state matches this record\n */\n verifyState(callbackState: string): boolean {\n return this.isValid && this.state === callbackState;\n }\n\n /**\n * Generate a new random state token\n */\n static generateState(): string {\n return crypto.randomUUID();\n }\n\n /**\n * Generate a PKCE code verifier\n * Returns a 43-128 character random string\n */\n static generateCodeVerifier(): string {\n const array = new Uint8Array(32);\n crypto.getRandomValues(array);\n return Array.from(array, (byte) => byte.toString(16).padStart(2, '0')).join(\n '',\n );\n }\n\n /**\n * Generate PKCE code challenge from verifier (S256 method)\n * Note: This requires async crypto operations\n */\n static async generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const digest = await crypto.subtle.digest('SHA-256', data);\n const base64 = btoa(String.fromCharCode(...new Uint8Array(digest)));\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=/g, '');\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { OAuthState } from '../oauth-state.js';\n\nexport class OAuthStateCollection extends SmrtCollection<OAuthState> {\n static readonly _itemClass = OAuthState;\n\n async findByState(state: string): Promise<OAuthState | null> {\n return this.get({ state });\n }\n\n async findExpired(now: Date = new Date()): Promise<OAuthState[]> {\n return this.list({\n where: { 'expiresAt <=': now },\n orderBy: 'expiresAt ASC',\n });\n }\n\n async deleteExpired(now: Date = new Date()): Promise<number> {\n const expired = await this.findExpired(now);\n await Promise.all(expired.map((state) => state.delete()));\n return expired.length;\n }\n}\n","/**\n * Social Account Model\n *\n * Manages connected social media platform accounts for publishing.\n * Stores OAuth credentials and account settings.\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { SecretService } from '@happyvertical/smrt-secrets';\nimport {\n getCurrentTenant,\n TenantScoped,\n tenantId,\n withTenant,\n} from '@happyvertical/smrt-tenancy';\nimport { getSocialPlatformSetup } from './server.js';\n\n/**\n * Supported social platforms\n */\nexport type SocialPlatformType =\n | 'youtube'\n | 'threads'\n | 'x'\n | 'bluesky'\n | 'facebook';\n\n/**\n * Account connection status\n */\nexport type AccountStatus =\n | 'connected'\n | 'disconnected'\n | 'expired'\n | 'missing_permissions'\n | 'error';\n\n/**\n * Link behavior for posts with links\n */\nexport type LinkBehavior =\n | 'description'\n | 'inline'\n | 'attachment'\n | 'reply'\n | 'none';\n\n/**\n * Controls how far publish operations are allowed to go.\n */\nexport type PublishMode =\n | 'dry_run'\n | 'stage_remote'\n | 'private_or_scheduled'\n | 'public';\n\n/**\n * Social account creation options\n */\nexport interface SocialAccountOptions extends SmrtObjectOptions {\n /**\n * Human-readable name for the account\n */\n name?: string;\n\n /**\n * Social platform type\n */\n platform?: SocialPlatformType;\n\n /**\n * Platform-specific user ID\n */\n platformUserId?: string | null;\n\n /**\n * Platform username/handle\n */\n platformUsername?: string | null;\n\n /**\n * Profile URL on the platform\n */\n platformUrl?: string | null;\n\n /**\n * Deprecated raw OAuth access token\n */\n accessToken?: string | null;\n\n /**\n * Deprecated raw OAuth refresh token\n */\n refreshToken?: string | null;\n\n /**\n * Secret name containing the full platform credential payload\n */\n credentialSecretId?: string | null;\n\n /**\n * Secret name containing the OAuth access token\n */\n accessTokenSecretName?: string | null;\n\n /**\n * Secret name containing the OAuth refresh token\n */\n refreshTokenSecretName?: string | null;\n\n /**\n * Token expiration time\n */\n tokenExpiresAt?: Date | null;\n\n /**\n * Whether the account is active\n * @default true\n */\n isActive?: boolean;\n\n /**\n * Default hashtags to add to posts\n */\n defaultHashtags?: string[];\n\n /**\n * Granted OAuth scopes or platform permissions\n */\n scopes?: string[];\n\n /**\n * Required permissions that still need approval/granting\n */\n missingPermissions?: string[];\n\n /**\n * How to handle links in posts\n * @default 'description'\n */\n linkBehavior?: LinkBehavior;\n\n /**\n * Safety mode for publish operations.\n * @default 'dry_run'\n */\n publishMode?: PublishMode;\n\n /**\n * Separate latch required before public publishing can happen.\n * @default false\n */\n publicPublishingAllowed?: boolean;\n\n /**\n * Account connection status\n * @default 'connected'\n */\n status?: AccountStatus;\n\n /**\n * Error message if status is 'error'\n */\n errorMessage?: string | null;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Connected social media account for publishing\n *\n * SocialAccount represents a connected social platform account\n * with OAuth credentials and publishing settings. Accounts can\n * be used to publish content to multiple platforms.\n *\n * @example\n * ```typescript\n * import { SocialAccount } from '@happyvertical/smrt-social';\n *\n * const account = new SocialAccount({\n * name: 'Bentley News YouTube',\n * platform: 'youtube',\n * platformUserId: 'UC...',\n * platformUsername: 'Bentley News',\n * accessToken: '...encrypted...',\n * refreshToken: '...encrypted...',\n * tokenExpiresAt: new Date('2026-02-25'),\n * defaultHashtags: ['news', 'local', 'bentley'],\n * linkBehavior: 'description',\n * });\n * await account.save();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class SocialAccount extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Human-readable name for the account\n */\n name: string = '';\n\n /**\n * Social platform type\n */\n platform: SocialPlatformType = 'youtube';\n\n /**\n * Platform-specific user ID\n */\n platformUserId: string | null = null;\n\n /**\n * Platform username/handle\n */\n platformUsername: string | null = null;\n\n /**\n * Profile URL on the platform\n */\n platformUrl: string | null = null;\n\n /**\n * Deprecated raw OAuth access token.\n * Prefer credentialSecretId/accessTokenSecretName.\n */\n accessToken: string | null = null;\n\n /**\n * Deprecated raw OAuth refresh token.\n * Prefer credentialSecretId/refreshTokenSecretName.\n */\n refreshToken: string | null = null;\n\n /**\n * Secret name containing the complete platform credential payload.\n */\n credentialSecretId: string | null = null;\n\n /**\n * Secret name containing only the access token.\n */\n accessTokenSecretName: string | null = null;\n\n /**\n * Secret name containing only the refresh token.\n */\n refreshTokenSecretName: string | null = null;\n\n /**\n * Token expiration time\n */\n tokenExpiresAt: Date | null = null;\n\n /**\n * Whether the account is active\n */\n isActive: boolean = true;\n\n /**\n * Default hashtags to add to posts\n */\n defaultHashtags: string[] = [];\n\n /**\n * Granted OAuth scopes or platform permissions.\n */\n scopes: string[] = [];\n\n /**\n * Required permissions that still need app review or user grant.\n */\n missingPermissions: string[] = [];\n\n /**\n * How to handle links in posts\n * - description: Include link in post body/description\n * - reply: Post link as a reply (better for X algorithm)\n * - none: Don't include link\n */\n linkBehavior: LinkBehavior = 'description';\n\n /**\n * Safety mode for publish operations.\n */\n publishMode: PublishMode = 'dry_run';\n\n /**\n * Separate latch required before public publishing is allowed.\n */\n publicPublishingAllowed: boolean = false;\n\n /**\n * Account connection status\n */\n status: AccountStatus = 'connected';\n\n /**\n * Error message if status is 'error'\n */\n errorMessage: string | null = null;\n\n constructor(options: SocialAccountOptions = {}) {\n super(options);\n\n if (options.name !== undefined) this.name = options.name;\n if (options.platform !== undefined) this.platform = options.platform;\n if (options.platformUserId !== undefined)\n this.platformUserId = options.platformUserId;\n if (options.platformUsername !== undefined)\n this.platformUsername = options.platformUsername;\n if (options.platformUrl !== undefined)\n this.platformUrl = options.platformUrl;\n if (options.accessToken !== undefined)\n this.accessToken = options.accessToken;\n if (options.refreshToken !== undefined)\n this.refreshToken = options.refreshToken;\n if (options.credentialSecretId !== undefined)\n this.credentialSecretId = options.credentialSecretId;\n if (options.accessTokenSecretName !== undefined)\n this.accessTokenSecretName = options.accessTokenSecretName;\n if (options.refreshTokenSecretName !== undefined)\n this.refreshTokenSecretName = options.refreshTokenSecretName;\n if (options.tokenExpiresAt !== undefined)\n this.tokenExpiresAt = options.tokenExpiresAt;\n if (options.isActive !== undefined) this.isActive = options.isActive;\n if (options.defaultHashtags !== undefined)\n this.defaultHashtags = options.defaultHashtags;\n if (options.scopes !== undefined) this.scopes = options.scopes;\n if (options.missingPermissions !== undefined)\n this.missingPermissions = options.missingPermissions;\n if (options.linkBehavior !== undefined)\n this.linkBehavior = options.linkBehavior;\n if (options.publishMode !== undefined)\n this.publishMode = options.publishMode;\n if (options.publicPublishingAllowed !== undefined)\n this.publicPublishingAllowed = options.publicPublishingAllowed;\n if (options.status !== undefined) this.status = options.status;\n if (options.errorMessage !== undefined)\n this.errorMessage = options.errorMessage;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n\n if (options.platform !== undefined) {\n const setup = getSocialPlatformSetup(this.platform);\n if (options.linkBehavior === undefined) {\n this.linkBehavior = setup.defaultLinkBehavior;\n }\n if (options.publishMode === undefined) {\n this.publishMode = setup.defaultPublishMode;\n }\n }\n }\n\n /**\n * Social accounts need a slug identity that is scoped by tenant and platform.\n * A newsroom may connect `@localnews` on X, YouTube, Threads, and Facebook;\n * the generic name-derived slug would make those accounts overwrite each\n * other through SMRT's slug/context upsert identity.\n */\n async getSlug(): Promise<string | null | undefined> {\n if (!this.slug) {\n const identity =\n this.platformUserId || this.platformUsername || this.name || this.id;\n if (!identity) {\n return this.slug;\n }\n\n const source = [\n this.tenantId ? `tenant-${this.tenantId}` : 'no-tenant',\n this.platform,\n identity,\n ]\n .filter(Boolean)\n .join('-');\n\n this.slug = source\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/(^-|-$)/g, '');\n }\n\n return this.slug;\n }\n\n /**\n * Check if the token is expired or will expire soon\n */\n get isTokenExpired(): boolean {\n if (!this.tokenExpiresAt) return false;\n // Expire 5 minutes early to allow for refresh\n const expiryBuffer = 5 * 60 * 1000;\n return Date.now() >= this.tokenExpiresAt.getTime() - expiryBuffer;\n }\n\n /**\n * Check if the account needs attention (expired or error)\n */\n get needsAttention(): boolean {\n return (\n this.status !== 'connected' ||\n this.isTokenExpired ||\n this.missingPermissions.length > 0 ||\n (this.publishMode === 'public' && !this.publicPublishingAllowed)\n );\n }\n\n /**\n * Check if the account is ready for publishing\n */\n get isReady(): boolean {\n return (\n this.isActive &&\n this.status === 'connected' &&\n this.hasCredentials &&\n this.missingPermissions.length === 0 &&\n !this.isTokenExpired &&\n (this.publishMode !== 'public' || this.publicPublishingAllowed)\n );\n }\n\n /**\n * Effective publish mode after applying the public-publishing latch.\n */\n get effectivePublishMode(): PublishMode {\n if (this.publishMode === 'public' && !this.publicPublishingAllowed) {\n return 'dry_run';\n }\n return this.publishMode;\n }\n\n /**\n * Check whether any usable credential reference exists.\n */\n get hasCredentials(): boolean {\n return Boolean(\n this.credentialSecretId || this.accessTokenSecretName || this.accessToken,\n );\n }\n\n /**\n * Store all platform credentials in smrt-secrets as a single JSON payload.\n */\n async setCredentials(\n credentials: Record<string, unknown>,\n options: {\n description?: string;\n category?: string;\n } = {},\n ): Promise<void> {\n if (!this.id) {\n this.id = randomUUID();\n }\n\n const secretName = this.credentialSecretId ?? `social-account-${this.id}`;\n const tenantId = this.requireCredentialTenantId(\n 'store social account credentials',\n );\n const secretService = await SecretService.create({ db: this.db });\n\n await secretService.storeForTenant(\n tenantId,\n secretName,\n JSON.stringify(credentials),\n {\n description: options.description ?? `Credentials for ${this.name}`,\n category: options.category ?? 'social',\n },\n );\n\n this.credentialSecretId = secretName;\n\n await this.withCredentialTenantContext(async () => {\n await this.save();\n });\n }\n\n /**\n * Retrieve platform credentials from smrt-secrets, falling back to deprecated fields.\n */\n async getCredentials(): Promise<Record<string, unknown> | null> {\n if (!this.credentialSecretId) {\n if (this.accessTokenSecretName || this.refreshTokenSecretName) {\n const tenantId = this.requireCredentialTenantId(\n 'retrieve social account credentials',\n );\n const secretService = await SecretService.create({ db: this.db });\n const credentials: Record<string, unknown> = {};\n\n if (this.accessTokenSecretName) {\n const secret = await secretService.retrieveForTenant(\n tenantId,\n this.accessTokenSecretName,\n );\n credentials.accessToken = secret.value;\n }\n\n if (this.refreshTokenSecretName) {\n const secret = await secretService.retrieveForTenant(\n tenantId,\n this.refreshTokenSecretName,\n );\n credentials.refreshToken = secret.value;\n }\n\n return credentials;\n }\n\n if (!this.accessToken && !this.refreshToken) return null;\n return {\n accessToken: this.accessToken,\n refreshToken: this.refreshToken,\n };\n }\n\n const credentialSecretId = this.credentialSecretId;\n const tenantId = this.requireCredentialTenantId(\n 'retrieve social account credentials',\n );\n const secretService = await SecretService.create({ db: this.db });\n const secret = await secretService.retrieveForTenant(\n tenantId,\n credentialSecretId,\n );\n return JSON.parse(secret.value);\n }\n\n private async withCredentialTenantContext<T>(\n fn: () => Promise<T>,\n ): Promise<T> {\n const tenantId = this.getCredentialTenantId();\n const currentTenantId = getCurrentTenant()?.tenantId;\n\n if (!tenantId || currentTenantId === tenantId) {\n return fn();\n }\n\n return withTenant({ tenantId }, fn);\n }\n\n private getCredentialTenantId(): string | null {\n if (this.tenantId) {\n return this.tenantId;\n }\n\n return getCurrentTenant()?.tenantId ?? null;\n }\n\n private requireCredentialTenantId(action: string): string {\n const tenantId = this.getCredentialTenantId();\n if (!tenantId) {\n throw new Error(`Tenant context required to ${action}.`);\n }\n return tenantId;\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport { SocialAccount, type SocialPlatformType } from '../social-account.js';\n\nexport class SocialAccountCollection extends SmrtCollection<SocialAccount> {\n static readonly _itemClass = SocialAccount;\n\n async findActive(platform?: SocialPlatformType): Promise<SocialAccount[]> {\n const accounts = await this.list({\n where: {\n isActive: true,\n ...(platform ? { platform } : {}),\n },\n orderBy: 'name ASC',\n });\n\n return accounts;\n }\n\n async findReady(platform?: SocialPlatformType): Promise<SocialAccount[]> {\n const accounts = await this.findActive(platform);\n return accounts.filter((account) => account.isReady);\n }\n\n async findNeedsAttention(): Promise<SocialAccount[]> {\n const accounts = await this.list({\n where: { isActive: true },\n orderBy: 'name ASC',\n });\n return accounts.filter((account) => account.needsAttention);\n }\n}\n","/**\n * Social Post Model\n *\n * Manages posts published or scheduled to social media platforms.\n * Tracks publishing status and engagement analytics.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { SocialAccount } from './social-account.js';\n\n/**\n * Post status\n */\nexport type PostStatus =\n | 'draft'\n | 'pending_approval'\n | 'approved'\n | 'scheduled'\n | 'publishing'\n | 'dry_run'\n | 'staged'\n | 'published'\n | 'failed'\n | 'cancelled';\n\n/**\n * Social post type\n */\nexport type SocialPostType = 'text' | 'link' | 'image' | 'video';\n\n/**\n * Post analytics\n */\nexport interface PostAnalytics {\n /**\n * View/impression count\n */\n views?: number;\n\n /**\n * Impression count when the platform distinguishes it from views\n */\n impressions?: number;\n\n /**\n * Like/favorite count\n */\n likes?: number;\n\n /**\n * Comment count\n */\n comments?: number;\n\n /**\n * Share/repost count\n */\n shares?: number;\n\n /**\n * Link click count\n */\n clicks?: number;\n\n /**\n * Raw platform analytics payload\n */\n raw?: unknown;\n\n /**\n * When analytics were last updated\n */\n lastUpdated?: Date;\n}\n\n/**\n * Social post creation options\n */\nexport interface SocialPostOptions extends SmrtObjectOptions {\n /**\n * Social account to publish to\n */\n socialAccountId?: string | null;\n\n /**\n * Video content to publish\n */\n videoContentId?: string | null;\n\n /**\n * Generic content ID (for non-video content)\n */\n contentId?: string | null;\n\n /**\n * High-level post type\n */\n postType?: SocialPostType;\n\n /**\n * Public media URL for platforms that cannot upload buffers\n */\n mediaUrl?: string | null;\n\n /**\n * Post title (for platforms that support it)\n */\n title?: string | null;\n\n /**\n * Post description/caption\n */\n description?: string;\n\n /**\n * Hashtags to include\n */\n hashtags?: string[];\n\n /**\n * Link URL to include\n */\n linkUrl?: string | null;\n\n /**\n * Platform-specific post ID (after publishing)\n */\n platformPostId?: string | null;\n\n /**\n * Public post URL (after publishing)\n */\n platformUrl?: string | null;\n\n /**\n * Scheduled publish time\n */\n scheduledAt?: Date | null;\n\n /**\n * Actual publish time\n */\n publishedAt?: Date | null;\n\n /**\n * Post status\n * @default 'draft'\n */\n status?: PostStatus;\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage?: string | null;\n\n /**\n * Engagement analytics\n */\n analytics?: PostAnalytics;\n\n /**\n * When analytics were last synced\n */\n analyticsLastSyncedAt?: Date | null;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Social media post for multi-platform publishing\n *\n * SocialPost represents a post published or scheduled to a social\n * platform. It tracks publishing status and engagement analytics,\n * and can reference VideoContent for video posts.\n *\n * @example\n * ```typescript\n * import { SocialPost } from '@happyvertical/smrt-social';\n *\n * const post = new SocialPost({\n * socialAccountId: 'account-123',\n * videoContentId: 'video-456',\n * title: 'Breaking News from Bentley',\n * description: 'Latest updates from the town council meeting.',\n * hashtags: ['news', 'local', 'bentley'],\n * linkUrl: 'https://example.com/article',\n * scheduledAt: new Date('2026-01-26T18:00:00Z'),\n * });\n * await post.save();\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class SocialPost extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Social account to publish to\n */\n @foreignKey(SocialAccount)\n socialAccountId: string | null = null;\n\n /**\n * Video content to publish\n *\n * Cross-package target (`@happyvertical/smrt-video`), so it is a\n * `@crossPackageRef` rather than a `@foreignKey`: no DDL FK constraint and\n * no value import back into this package.\n */\n @crossPackageRef('@happyvertical/smrt-video:VideoContent')\n videoContentId: string | null = null;\n\n /**\n * Generic content ID (for non-video content)\n */\n @crossPackageRef('@happyvertical/smrt-content:Content')\n contentId: string | null = null;\n\n /**\n * High-level post type\n */\n postType: SocialPostType = 'text';\n\n /**\n * Public media URL for platforms that require URL media publishing\n */\n mediaUrl: string | null = null;\n\n /**\n * Post title (for platforms that support it)\n */\n title: string | null = null;\n\n /**\n * Post description/caption\n */\n description: string = '';\n\n /**\n * Hashtags to include\n */\n hashtags: string[] = [];\n\n /**\n * Link URL to include in the post\n */\n linkUrl: string | null = null;\n\n /**\n * Platform-specific post ID (set after publishing)\n */\n platformPostId: string | null = null;\n\n /**\n * Public post URL (set after publishing)\n */\n platformUrl: string | null = null;\n\n /**\n * Scheduled publish time\n * If set, post will be scheduled instead of published immediately\n */\n scheduledAt: Date | null = null;\n\n /**\n * Actual publish time\n */\n publishedAt: Date | null = null;\n\n /**\n * Post status\n * - draft: Not yet submitted for publishing\n * - pending_approval: Awaiting editorial approval\n * - approved: Approved and ready to publish\n * - scheduled: Queued for future publishing\n * - publishing: Currently being published\n * - dry_run: Payload was validated without remote write\n * - staged: Non-public platform object/container was created\n * - published: Successfully published\n * - failed: Publishing failed\n * - cancelled: Publishing was cancelled\n */\n status: PostStatus = 'draft';\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage: string | null = null;\n\n /**\n * Engagement analytics\n */\n analytics: PostAnalytics = {};\n\n /**\n * When analytics were last synced\n */\n analyticsLastSyncedAt: Date | null = null;\n\n constructor(options: SocialPostOptions = {}) {\n super(options);\n\n if (options.socialAccountId !== undefined)\n this.socialAccountId = options.socialAccountId;\n if (options.videoContentId !== undefined)\n this.videoContentId = options.videoContentId;\n if (options.contentId !== undefined) this.contentId = options.contentId;\n if (options.postType !== undefined) this.postType = options.postType;\n if (options.mediaUrl !== undefined) this.mediaUrl = options.mediaUrl;\n if (options.title !== undefined) this.title = options.title;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.hashtags !== undefined) this.hashtags = options.hashtags;\n if (options.linkUrl !== undefined) this.linkUrl = options.linkUrl;\n if (options.platformPostId !== undefined)\n this.platformPostId = options.platformPostId;\n if (options.platformUrl !== undefined)\n this.platformUrl = options.platformUrl;\n if (options.scheduledAt !== undefined)\n this.scheduledAt = options.scheduledAt;\n if (options.publishedAt !== undefined)\n this.publishedAt = options.publishedAt;\n if (options.status !== undefined) this.status = options.status;\n if (options.errorMessage !== undefined)\n this.errorMessage = options.errorMessage;\n if (options.analytics !== undefined) this.analytics = options.analytics;\n if (options.analyticsLastSyncedAt !== undefined)\n this.analyticsLastSyncedAt = options.analyticsLastSyncedAt;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if the post is scheduled for future publishing\n */\n get isScheduled(): boolean {\n return this.status === 'scheduled' && this.scheduledAt !== null;\n }\n\n /**\n * Check if the post has been published\n */\n get isPublished(): boolean {\n return this.status === 'published';\n }\n\n /**\n * Check if the post can be edited (draft or failed)\n */\n get isEditable(): boolean {\n return (\n this.status === 'draft' ||\n this.status === 'pending_approval' ||\n this.status === 'failed'\n );\n }\n\n /**\n * Check if the post is due for publishing now.\n */\n get isDueForPublish(): boolean {\n if (this.status !== 'approved' && this.status !== 'scheduled') {\n return false;\n }\n return !this.scheduledAt || this.scheduledAt.getTime() <= Date.now();\n }\n\n /**\n * Get formatted hashtag string\n */\n get hashtagString(): string {\n return this.hashtags\n .map((tag) => (tag.startsWith('#') ? tag : `#${tag}`))\n .join(' ');\n }\n\n /**\n * Get the full post text with hashtags\n */\n get fullText(): string {\n const parts = [this.description];\n if (this.hashtags.length > 0) {\n parts.push(this.hashtagString);\n }\n return parts.join('\\n\\n');\n }\n}\n","/**\n * Social Post Analytics Snapshot Model\n *\n * Stores timestamped normalized and raw platform analytics payloads.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { field, foreignKey, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport type { SocialPlatformType } from './social-account.js';\nimport { type PostAnalytics, SocialPost } from './social-post.js';\n\nexport type RawAnalyticsPayload = Record<string, unknown> | unknown[] | null;\n\nexport interface SocialPostAnalyticsSnapshotOptions extends SmrtObjectOptions {\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n\n /**\n * Social post being measured\n */\n socialPostId?: string | null;\n\n /**\n * Platform that produced this snapshot\n */\n platform?: SocialPlatformType | null;\n\n /**\n * Normalized platform analytics.\n */\n analytics?: PostAnalytics;\n\n /**\n * Raw platform payload\n */\n raw?: RawAnalyticsPayload;\n\n /**\n * When the platform data was captured\n */\n capturedAt?: Date;\n}\n\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class SocialPostAnalyticsSnapshot extends SmrtObject {\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n @foreignKey(SocialPost)\n socialPostId: string | null = null;\n\n @field({ required: true })\n platform: SocialPlatformType | null = null;\n\n analytics: PostAnalytics = {};\n\n @field({ type: 'json', nullable: true })\n raw: RawAnalyticsPayload = null;\n\n capturedAt: Date = new Date();\n\n constructor(options: SocialPostAnalyticsSnapshotOptions = {}) {\n super(options);\n\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n if (options.socialPostId !== undefined)\n this.socialPostId = options.socialPostId;\n if (options.platform !== undefined) this.platform = options.platform;\n if (options.analytics !== undefined) this.analytics = options.analytics;\n if (options.raw !== undefined) this.raw = options.raw;\n if (options.capturedAt !== undefined) this.capturedAt = options.capturedAt;\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport type { SocialPlatformType } from '../social-account.js';\nimport type { PostAnalytics } from '../social-post.js';\nimport {\n type RawAnalyticsPayload,\n SocialPostAnalyticsSnapshot,\n} from '../social-post-analytics-snapshot.js';\n\nfunction isRawAnalyticsPayload(value: unknown): value is RawAnalyticsPayload {\n return (\n value === null ||\n Array.isArray(value) ||\n (typeof value === 'object' && value !== null)\n );\n}\n\nexport class SocialPostAnalyticsSnapshotCollection extends SmrtCollection<SocialPostAnalyticsSnapshot> {\n static readonly _itemClass = SocialPostAnalyticsSnapshot;\n\n async recordSnapshot(options: {\n socialPostId: string;\n platform: SocialPlatformType;\n metrics: PostAnalytics;\n raw?: RawAnalyticsPayload;\n capturedAt?: Date;\n tenantId?: string | null;\n }): Promise<SocialPostAnalyticsSnapshot> {\n const snapshot = await this.create({\n socialPostId: options.socialPostId,\n platform: options.platform,\n analytics: options.metrics,\n raw:\n options.raw ??\n (isRawAnalyticsPayload(options.metrics.raw)\n ? options.metrics.raw\n : null),\n capturedAt: options.capturedAt ?? new Date(),\n tenantId: options.tenantId,\n });\n return snapshot;\n }\n\n async findForPost(\n socialPostId: string,\n ): Promise<SocialPostAnalyticsSnapshot[]> {\n return this.list({\n where: { socialPostId },\n orderBy: 'capturedAt DESC',\n });\n }\n\n async findLatestForPost(\n socialPostId: string,\n ): Promise<SocialPostAnalyticsSnapshot | null> {\n const snapshots = await this.findForPost(socialPostId);\n return snapshots[0] ?? null;\n }\n}\n","import { SmrtCollection } from '@happyvertical/smrt-core';\nimport {\n type PostAnalytics,\n type PostStatus,\n SocialPost,\n type SocialPostType,\n} from '../social-post.js';\n\nexport interface CreateSocialPostDraftOptions {\n socialAccountId: string;\n contentId?: string | null;\n videoContentId?: string | null;\n postType?: SocialPostType;\n title?: string | null;\n description?: string;\n hashtags?: string[];\n linkUrl?: string | null;\n mediaUrl?: string | null;\n scheduledAt?: Date | null;\n tenantId?: string | null;\n}\n\nexport interface PublishSuccessData {\n platformPostId: string;\n platformUrl: string;\n publishedAt?: Date;\n status?: PostStatus;\n}\n\nexport class SocialPostCollection extends SmrtCollection<SocialPost> {\n static readonly _itemClass = SocialPost;\n\n async createDraft(\n options: CreateSocialPostDraftOptions,\n ): Promise<SocialPost> {\n return this.create({\n ...options,\n postType:\n options.postType ??\n (options.videoContentId || options.mediaUrl\n ? 'video'\n : options.linkUrl\n ? 'link'\n : 'text'),\n status: options.scheduledAt ? 'scheduled' : 'draft',\n });\n }\n\n async findByStatus(status: PostStatus): Promise<SocialPost[]> {\n return this.list({ where: { status }, orderBy: 'scheduledAt ASC' });\n }\n\n async findForAccount(socialAccountId: string): Promise<SocialPost[]> {\n return this.list({\n where: { socialAccountId },\n orderBy: 'created_at DESC',\n });\n }\n\n async findDueForPublish(now: Date = new Date()): Promise<SocialPost[]> {\n const [approved, scheduled] = await Promise.all([\n this.list({\n where: { status: 'approved' },\n orderBy: 'scheduledAt ASC',\n }),\n this.list({\n where: { status: 'scheduled', 'scheduledAt <=': now },\n orderBy: 'scheduledAt ASC',\n }),\n ]);\n\n return [\n ...approved.filter((post) => post.isDueForPublish),\n ...scheduled,\n ].sort(\n (a, b) =>\n (a.scheduledAt?.getTime() ?? 0) - (b.scheduledAt?.getTime() ?? 0),\n );\n }\n\n async recordPublishSuccess(\n post: SocialPost,\n data: PublishSuccessData,\n ): Promise<SocialPost> {\n const status = data.status ?? 'published';\n post.platformPostId = data.platformPostId;\n post.platformUrl = data.platformUrl;\n if (status === 'published') {\n post.publishedAt = data.publishedAt ?? post.publishedAt ?? new Date();\n }\n post.status = status;\n post.errorMessage = null;\n await post.save();\n return post;\n }\n\n async recordPublishFailure(\n post: SocialPost,\n error: Error | string,\n ): Promise<SocialPost> {\n post.status = 'failed';\n post.errorMessage = formatPublishError(error);\n await post.save();\n return post;\n }\n\n async updateLatestAnalytics(\n post: SocialPost,\n analytics: PostAnalytics,\n syncedAt: Date = new Date(),\n ): Promise<SocialPost> {\n post.analytics = {\n ...analytics,\n lastUpdated: analytics.lastUpdated ?? syncedAt,\n };\n post.analyticsLastSyncedAt = syncedAt;\n await post.save();\n return post;\n }\n}\n\nfunction formatPublishError(error: Error | string): string {\n if (typeof error === 'string') {\n return error;\n }\n\n const details = [error.message];\n const code = (error as Error & { code?: unknown }).code;\n if (code !== undefined) {\n details.push(`code=${String(code)}`);\n }\n if (error.stack) {\n details.push(error.stack);\n }\n return details.join('\\n');\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@
2
2
  "version": "1.0.0",
3
3
  "timestamp": 0,
4
4
  "packageName": "@happyvertical/smrt-social",
5
- "packageVersion": "0.40.69",
5
+ "packageVersion": "0.40.70",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-social:OAuthState": {
8
8
  "name": "oauthstate",
@@ -713,6 +713,12 @@
713
713
  "columns": [
714
714
  "_meta_type"
715
715
  ]
716
+ },
717
+ {
718
+ "name": "oauth_states_tenant_id_idx",
719
+ "columns": [
720
+ "tenant_id"
721
+ ]
716
722
  }
717
723
  ],
718
724
  "version": "709e111f"
@@ -1540,6 +1546,12 @@
1540
1546
  "columns": [
1541
1547
  "_meta_type"
1542
1548
  ]
1549
+ },
1550
+ {
1551
+ "name": "social_accounts_tenant_id_idx",
1552
+ "columns": [
1553
+ "tenant_id"
1554
+ ]
1543
1555
  }
1544
1556
  ],
1545
1557
  "version": "0c175da6"
@@ -1582,7 +1594,7 @@
1582
1594
  "socialPostId": {
1583
1595
  "type": "foreignKey",
1584
1596
  "required": false,
1585
- "related": "() => SocialPost"
1597
+ "related": "SocialPost"
1586
1598
  },
1587
1599
  "platform": {
1588
1600
  "type": "text",
@@ -2214,6 +2226,12 @@
2214
2226
  "columns": [
2215
2227
  "_meta_type"
2216
2228
  ]
2229
+ },
2230
+ {
2231
+ "name": "social_post_analytics_snapshots_tenant_id_idx",
2232
+ "columns": [
2233
+ "tenant_id"
2234
+ ]
2217
2235
  }
2218
2236
  ],
2219
2237
  "version": "50fd9e85"
@@ -2256,12 +2274,12 @@
2256
2274
  "socialAccountId": {
2257
2275
  "type": "foreignKey",
2258
2276
  "required": false,
2259
- "related": "() => SocialAccount"
2277
+ "related": "SocialAccount"
2260
2278
  },
2261
2279
  "videoContentId": {
2262
- "type": "foreignKey",
2280
+ "type": "crossPackageRef",
2263
2281
  "required": false,
2264
- "related": "() => VideoContent"
2282
+ "related": "@happyvertical/smrt-video:VideoContent"
2265
2283
  },
2266
2284
  "contentId": {
2267
2285
  "type": "crossPackageRef",
@@ -2894,7 +2912,7 @@
2894
2912
  },
2895
2913
  "video_content_id": {
2896
2914
  "type": "UUID",
2897
- "referenceKind": "foreignKey",
2915
+ "referenceKind": "crossPackageRef",
2898
2916
  "notNull": false
2899
2917
  },
2900
2918
  "content_id": {
@@ -2984,9 +3002,15 @@
2984
3002
  "columns": [
2985
3003
  "_meta_type"
2986
3004
  ]
3005
+ },
3006
+ {
3007
+ "name": "social_posts_tenant_id_idx",
3008
+ "columns": [
3009
+ "tenant_id"
3010
+ ]
2987
3011
  }
2988
3012
  ],
2989
- "version": "0ec041f6"
3013
+ "version": "ded3699f"
2990
3014
  }
2991
3015
  },
2992
3016
  "@happyvertical/smrt-social:OAuthStateCollection": {
@@ -3,13 +3,13 @@
3
3
  "sensitiveFieldsExcluded": true,
4
4
  "generatedAt": "1970-01-01T00:00:00.000Z",
5
5
  "packageName": "@happyvertical/smrt-social",
6
- "packageVersion": "0.40.69",
6
+ "packageVersion": "0.40.70",
7
7
  "sourceManifestPath": "dist/manifest.json",
8
8
  "agentDocPath": "AGENTS.md",
9
9
  "sourceHashes": {
10
- "manifest": "e35a406201fc5ce71b62b29f66f7d46ea9f3b6490951c5ad203555a2745dcb78",
11
- "packageJson": "da3cb04ab830eee3744f15e1a259187a2ad3bd95a86023f47931292bc294887c",
12
- "agents": "e52e321d32201085477380f355cbb533f5d931e2701cd4d2ceeda0d7c8720957"
10
+ "manifest": "085067b0d3aaf644d98cd175c44d7df106027416e30dc8c0db14a130b735a301",
11
+ "packageJson": "4541939b5495e670dab326c5b834db499024ff8f48224d493f4145c07c7e42f6",
12
+ "agents": "f31b84b31431fcb43ab480fafd9684d91f0e55a935e95aa31fd19ea1f31b0ad4"
13
13
  },
14
14
  "exports": [
15
15
  ".",
@@ -1148,7 +1148,7 @@
1148
1148
  "name": "socialPostId",
1149
1149
  "type": "foreignKey",
1150
1150
  "required": false,
1151
- "related": "() => SocialPost",
1151
+ "related": "SocialPost",
1152
1152
  "columnType": "UUID"
1153
1153
  },
1154
1154
  {
@@ -1181,7 +1181,7 @@
1181
1181
  "name": "socialPostId",
1182
1182
  "type": "foreignKey",
1183
1183
  "required": false,
1184
- "related": "() => SocialPost",
1184
+ "related": "SocialPost",
1185
1185
  "columnType": "UUID"
1186
1186
  }
1187
1187
  ],
@@ -1613,14 +1613,14 @@
1613
1613
  "name": "socialAccountId",
1614
1614
  "type": "foreignKey",
1615
1615
  "required": false,
1616
- "related": "() => SocialAccount",
1616
+ "related": "SocialAccount",
1617
1617
  "columnType": "UUID"
1618
1618
  },
1619
1619
  {
1620
1620
  "name": "videoContentId",
1621
- "type": "foreignKey",
1621
+ "type": "crossPackageRef",
1622
1622
  "required": false,
1623
- "related": "() => VideoContent",
1623
+ "related": "@happyvertical/smrt-video:VideoContent",
1624
1624
  "columnType": "UUID"
1625
1625
  },
1626
1626
  {
@@ -1724,14 +1724,14 @@
1724
1724
  "name": "socialAccountId",
1725
1725
  "type": "foreignKey",
1726
1726
  "required": false,
1727
- "related": "() => SocialAccount",
1727
+ "related": "SocialAccount",
1728
1728
  "columnType": "UUID"
1729
1729
  },
1730
1730
  {
1731
1731
  "name": "videoContentId",
1732
- "type": "foreignKey",
1732
+ "type": "crossPackageRef",
1733
1733
  "required": false,
1734
- "related": "() => VideoContent",
1734
+ "related": "@happyvertical/smrt-video:VideoContent",
1735
1735
  "columnType": "UUID"
1736
1736
  },
1737
1737
  {
@@ -2679,12 +2679,12 @@
2679
2679
  ],
2680
2680
  "prompts": [],
2681
2681
  "relationshipsV2": {
2682
- "foreignKeyFields": 3,
2683
- "crossPackageRefFields": 1,
2682
+ "foreignKeyFields": 2,
2683
+ "crossPackageRefFields": 2,
2684
2684
  "junctionCollections": 0,
2685
2685
  "hierarchicalObjects": 0,
2686
2686
  "polymorphicAssociations": 0,
2687
2687
  "uuidColumns": 16
2688
2688
  },
2689
- "agentDoc": "# @happyvertical/smrt-social\n\nSocial media account management with OAuth and post scheduling. Supports YouTube, Threads, X (Twitter), Bluesky.\n\n## Models\n\n- **SocialAccount** (STI): `platform`, `accessToken`/`refreshToken`, `tokenExpiresAt`, `status` (connected/expired/error), `linkBehavior` (description/reply/none). `isTokenExpired` checks with 5-min buffer. `isReady` gate checks active + connected + token present + not expired.\n- **SocialPost**: `scheduledAt`, `publishedAt`, `status` (draft/scheduled/publishing/published/failed), `analytics` JSON (views/likes/comments/shares/clicks).\n- **OAuthState** (STI): CSRF token + PKCE `codeVerifier` with 10-min TTL.\n\n## Gotchas\n\n- **Tokens not encrypted**: OAuth tokens stored as plaintext — TODO for smrt-secrets integration\n- **No auto-publishing**: `scheduledAt` is metadata only — app must implement job runner to trigger publishing\n- **Analytics manual**: `analytics` field must be updated by platform sync, not auto-populated\n- **Platform enum hardcoded**: youtube/threads/x/bluesky — extending requires code changes\n- **OAuthState TTL**: 10 minutes, app must clean up expired states\n- **Optional tenancy** on all models\n"
2689
+ "agentDoc": "# @happyvertical/smrt-social\n\nSocial media account management with OAuth and post scheduling. Supports YouTube, Threads, X (Twitter), Bluesky.\n\n## Models\n\n- **SocialAccount** (STI): `platform`, `accessToken`/`refreshToken`, `tokenExpiresAt`, `status` (connected/expired/error), `linkBehavior` (description/reply/none). `isTokenExpired` checks with 5-min buffer. `isReady` gate checks active + connected + token present + not expired.\n- **SocialPost**: `scheduledAt`, `publishedAt`, `status` (draft/scheduled/publishing/published/failed), `analytics` JSON (views/likes/comments/shares/clicks).\n- **OAuthState** (STI): CSRF token + PKCE `codeVerifier` with 10-min TTL.\n\n## Gotchas\n\n- **Tokens not encrypted**: OAuth tokens stored as plaintext — TODO for smrt-secrets integration\n- **No auto-publishing**: `scheduledAt` is metadata only — app must implement job runner to trigger publishing\n- **Analytics manual**: `analytics` field must be updated by platform sync, not auto-populated\n- **Platform enum hardcoded**: youtube/threads/x/bluesky — extending requires code changes\n- **OAuthState TTL**: 10 minutes, app must clean up expired states\n- **Optional tenancy** on all models\n- **Relationship targets**: `SocialPost.socialAccountId` and\n `SocialPostAnalyticsSnapshot.socialPostId` are same-package `@foreignKey`\n columns; `SocialPost.videoContentId` is a `@crossPackageRef` to\n `@happyvertical/smrt-video:VideoContent` (no value import back into this\n package). They previously used `@foreignKey(() => X)`, whose target resolved\n to `''`, so none of them carried a relationship edge (#2379).\n"
2690
2690
  }
@@ -156,6 +156,10 @@ export declare class SocialPost extends SmrtObject {
156
156
  socialAccountId: string | null;
157
157
  /**
158
158
  * Video content to publish
159
+ *
160
+ * Cross-package target (`@happyvertical/smrt-video`), so it is a
161
+ * `@crossPackageRef` rather than a `@foreignKey`: no DDL FK constraint and
162
+ * no value import back into this package.
159
163
  */
160
164
  videoContentId: string | null;
161
165
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"social-post.d.ts","sourceRoot":"","sources":["../src/social-post.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAGL,UAAU,EAEX,MAAM,0BAA0B,CAAC;AAKlC;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB,OAAO,GACP,kBAAkB,GAClB,UAAU,GACV,WAAW,GACX,YAAY,GACZ,SAAS,GACT,QAAQ,GACR,WAAW,GACX,QAAQ,GACR,WAAW,CAAC;AAEhB;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;AAEjE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,GAAG,CAAC,EAAE,OAAO,CAAC;IAEd;;OAEG;IACH,WAAW,CAAC,EAAE,IAAI,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAkB,SAAQ,iBAAiB;IAC1D;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEhC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;IAE1B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEzB;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAEtB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IAEpB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAExB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE5B;;OAEG;IACH,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAE1B;;;OAGG;IACH,MAAM,CAAC,EAAE,UAAU,CAAC;IAEpB;;OAEG;IACH,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE7B;;OAEG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAE1B;;OAEG;IACH,qBAAqB,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAEpC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,qBAWa,UAAW,SAAQ,UAAU;IACxC;;OAEG;IAEH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IAEH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEtC;;OAEG;IAEH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAErC;;OAEG;IAEH,SAAS,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEhC;;OAEG;IACH,QAAQ,EAAE,cAAc,CAAU;IAElC;;OAEG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE/B;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE5B;;OAEG;IACH,WAAW,EAAE,MAAM,CAAM;IAEzB;;OAEG;IACH,QAAQ,EAAE,MAAM,EAAE,CAAM;IAExB;;OAEG;IACH,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAE9B;;OAEG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAQ;IAErC;;OAEG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAQ;IAElC;;;OAGG;IACH,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC;;OAEG;IACH,WAAW,EAAE,IAAI,GAAG,IAAI,CAAQ;IAEhC;;;;;;;;;;;;OAYG;IACH,MAAM,EAAE,UAAU,CAAW;IAE7B;;OAEG;IACH,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEnC;;OAEG;IACH,SAAS,EAAE,aAAa,CAAM;IAE9B;;OAEG;IACH,qBAAqB,EAAE,IAAI,GAAG,IAAI,CAAQ;gBAE9B,OAAO,GAAE,iBAAsB;IAgC3C;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACH,IAAI,WAAW,IAAI,OAAO,CAEzB;IAED;;OAEG;IACH,IAAI,UAAU,IAAI,OAAO,CAMxB;IAED;;OAEG;IACH,IAAI,eAAe,IAAI,OAAO,CAK7B;IAED;;OAEG;IACH,IAAI,aAAa,IAAI,MAAM,CAI1B;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,MAAM,CAMrB;CACF"}
1
+ {"version":3,"file":"social-post.d.ts","sourceRoot":"","sources":["../src/social-post.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-social",
3
- "version": "0.40.69",
3
+ "version": "0.40.70",
4
4
  "type": "module",
5
5
  "smrtRawPrimitives": "strict",
6
6
  "description": "Social media account management for multi-platform publishing in the SMRT ecosystem",
@@ -40,13 +40,13 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "@happyvertical/utils": "^0.88.0",
43
- "@happyvertical/smrt-config": "0.40.69",
44
- "@happyvertical/smrt-content": "0.40.69",
45
- "@happyvertical/smrt-core": "0.40.69",
46
- "@happyvertical/smrt-secrets": "0.40.69",
47
- "@happyvertical/smrt-tenancy": "0.40.69",
48
- "@happyvertical/smrt-ui": "0.40.69",
49
- "@happyvertical/smrt-video": "0.40.69"
43
+ "@happyvertical/smrt-config": "0.40.70",
44
+ "@happyvertical/smrt-secrets": "0.40.70",
45
+ "@happyvertical/smrt-tenancy": "0.40.70",
46
+ "@happyvertical/smrt-ui": "0.40.70",
47
+ "@happyvertical/smrt-video": "0.40.70",
48
+ "@happyvertical/smrt-content": "0.40.70",
49
+ "@happyvertical/smrt-core": "0.40.70"
50
50
  },
51
51
  "devDependencies": {
52
52
  "@happyvertical/logger": "^0.88.0",
@@ -58,7 +58,7 @@
58
58
  "typescript": "5.9.3",
59
59
  "vite": "8.1.4",
60
60
  "vitest": "4.1.10",
61
- "@happyvertical/smrt-vitest": "0.40.69"
61
+ "@happyvertical/smrt-vitest": "0.40.70"
62
62
  },
63
63
  "keywords": [
64
64
  "social",