@happyvertical/smrt-social 0.54.2 → 0.54.4
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 +1 -1
- package/README.md +6 -2
- package/dist/collections/oauth-state-collection.d.ts +10 -0
- package/dist/collections/oauth-state-collection.d.ts.map +1 -1
- package/dist/index.js +63 -2
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +60 -6
- package/dist/oauth-state.d.ts +27 -0
- package/dist/oauth-state.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +61 -9
- package/package.json +12 -12
package/AGENTS.md
CHANGED
|
@@ -6,7 +6,7 @@ Social media account management with OAuth and post scheduling. Supports YouTube
|
|
|
6
6
|
|
|
7
7
|
- **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.
|
|
8
8
|
- **SocialPost**: `scheduledAt`, `publishedAt`, `status` (draft/scheduled/publishing/published/failed), `analytics` JSON (views/likes/comments/shares/clicks). `createdByUserId` (nullable `@crossPackageRef` to `smrt-users:User`, uuid on PostgreSQL) records the poster; pass it to `createDraft()` so a failed publish can be reported to that person. Agent/schedule posts leave it null; `recordPublishSuccess`/`Failure` never change it. Adding the column is additive: consumers run `db:migrate`.
|
|
9
|
-
- **OAuthState** (STI): CSRF token + PKCE `codeVerifier` with 10-min TTL.
|
|
9
|
+
- **OAuthState** (STI): CSRF token + PKCE `codeVerifier` with 10-min TTL. `createdByUserId` (nullable `@crossPackageRef` to `smrt-users:User`) binds the flow to its initiator and `returnTo` stores an opaque host path; a host with one fixed callback for every tenant must reject a different user and validate `returnTo` as same-origin. `OAuthStateCollection.consume(state)` is the single-use arbiter (revision-guarded delete; `false` when another caller already consumed it). Both columns are additive: consumers run `db:migrate`.
|
|
10
10
|
|
|
11
11
|
## Gotchas
|
|
12
12
|
|
package/README.md
CHANGED
|
@@ -47,9 +47,12 @@ const state = new OAuthState({
|
|
|
47
47
|
codeVerifier: OAuthState.generateCodeVerifier(),
|
|
48
48
|
redirectUri: 'https://app.example.com/oauth/callback',
|
|
49
49
|
scopes: ['youtube.upload', 'youtube.readonly'],
|
|
50
|
+
createdByUserId: currentUser.id, // reject a different user on callback
|
|
51
|
+
returnTo: '/settings/social', // host-validated same-origin path
|
|
50
52
|
});
|
|
51
53
|
await state.save();
|
|
52
|
-
// On callback: state.verifyState(callbackState),
|
|
54
|
+
// On callback: state.verifyState(callbackState), check the user, then
|
|
55
|
+
// `await states.consume(state)` (false = already used) before exchanging the code
|
|
53
56
|
```
|
|
54
57
|
|
|
55
58
|
## API
|
|
@@ -60,7 +63,7 @@ await state.save();
|
|
|
60
63
|
|--------|------------|
|
|
61
64
|
| `SocialAccount` | Connected platform account with OAuth credentials and publishing settings |
|
|
62
65
|
| `SocialPost` | Scheduled or published post with analytics tracking; `createdByUserId` records the poster |
|
|
63
|
-
| `OAuthState` | Temporary OAuth flow state with CSRF protection and PKCE support |
|
|
66
|
+
| `OAuthState` | Temporary OAuth flow state with CSRF protection and PKCE support; `createdByUserId` and `returnTo` bind it to its initiator and return page |
|
|
64
67
|
|
|
65
68
|
### Types
|
|
66
69
|
|
|
@@ -84,6 +87,7 @@ await state.save();
|
|
|
84
87
|
- `OAuthState.isValid` -- not expired and state token present
|
|
85
88
|
- `OAuthState.verifyState(callback)` -- CSRF verification for OAuth callbacks
|
|
86
89
|
- `OAuthState.generateCodeChallenge(verifier)` -- PKCE S256 challenge generation
|
|
90
|
+
- `OAuthStateCollection.consume(state)` -- single-use consumption; `false` when another caller consumed it first
|
|
87
91
|
|
|
88
92
|
## Dependencies
|
|
89
93
|
|
|
@@ -3,6 +3,16 @@ import { OAuthState } from '../oauth-state.js';
|
|
|
3
3
|
export declare class OAuthStateCollection extends SmrtCollection<OAuthState> {
|
|
4
4
|
static readonly _itemClass: typeof OAuthState;
|
|
5
5
|
findByState(state: string): Promise<OAuthState | null>;
|
|
6
|
+
/**
|
|
7
|
+
* Consume a loaded state exactly once.
|
|
8
|
+
*
|
|
9
|
+
* Deletes the record with a revision-guarded delete, so when two callbacks
|
|
10
|
+
* race on the same state only one delete removes the row. Returns `true`
|
|
11
|
+
* for that caller and `false` for every caller whose row was already gone
|
|
12
|
+
* or changed; any other failure propagates. Call it before acting on the
|
|
13
|
+
* state (exchanging the code), and stop when it returns `false`.
|
|
14
|
+
*/
|
|
15
|
+
consume(state: OAuthState): Promise<boolean>;
|
|
6
16
|
findExpired(now?: Date): Promise<OAuthState[]>;
|
|
7
17
|
deleteExpired(now?: Date): Promise<number>;
|
|
8
18
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth-state-collection.d.ts","sourceRoot":"","sources":["../../src/collections/oauth-state-collection.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"oauth-state-collection.d.ts","sourceRoot":"","sources":["../../src/collections/oauth-state-collection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAE/C,qBAAa,oBAAqB,SAAQ,cAAc,CAAC,UAAU,CAAC;IAClE,MAAM,CAAC,QAAQ,CAAC,UAAU,oBAAc;IAElC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAI5D;;;;;;;;OAQG;IACG,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC;IAgB5C,WAAW,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAO1D,aAAa,CAAC,GAAG,GAAE,IAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;CAK7D"}
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,27 @@
|
|
|
1
1
|
import { getSocialPlatformSetup } from "./server.js";
|
|
2
|
-
import { ObjectRegistry, SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
2
|
+
import { ObjectRegistry, RuntimeError, SmrtCollection, SmrtObject, crossPackageRef, field, foreignKey, smrt } from "@happyvertical/smrt-core";
|
|
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
6
|
//#region src/__smrt-register__.ts
|
|
7
|
-
ObjectRegistry.registerPackageManifest(JSON.parse("{\"version\":\"1.0.0\",\"timestamp\":0,\"packageName\":\"@happyvertical/smrt-social\",\"packageVersion\":\"0.54.2\",\"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\":{\"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\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"oauth_states_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"oauth_states_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"709e111f\"},\"importPath\":\"@happyvertical/smrt-social\"},\"@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\":{\"getSlug\":{\"name\":\"getSlug\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<string | null | undefined>\",\"isStatic\":false,\"isPublic\":true},\"setCredentials\":{\"name\":\"setCredentials\",\"async\":true,\"parameters\":[{\"name\":\"credentials\",\"type\":\"Record<string, unknown>\",\"optional\":false},{\"name\":\"options\",\"type\":\"object\",\"optional\":true,\"memberTypes\":[\"string\"]}],\"returnType\":\"Promise<void>\",\"isStatic\":false,\"isPublic\":true},\"getCredentials\":{\"name\":\"getCredentials\",\"async\":true,\"parameters\":[],\"returnType\":\"Promise<Record<string, unknown> | null>\",\"isStatic\":false,\"isPublic\":true}},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":{\"skipApiCheck\":true},\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"social_accounts_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_accounts_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"0c175da6\"},\"importPath\":\"@happyvertical/smrt-social\"},\"@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\":{},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"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,\"foreignKey\":{\"table\":\"social_posts\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"social_post_analytics_snapshots_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_post_analytics_snapshots_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"social_post_analytics_snapshots_social_post_id_idx\",\"columns\":[\"social_post_id\"]}],\"version\":\"bd17983d\"},\"importPath\":\"@happyvertical/smrt-social\"},\"@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\"},\"createdByUserId\":{\"type\":\"crossPackageRef\",\"required\":false,\"related\":\"@happyvertical/smrt-users:User\"},\"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\":{},\"decoratorConfig\":{\"tableStrategy\":\"sti\",\"api\":{\"include\":[\"list\",\"get\",\"create\",\"update\",\"delete\"]},\"mcp\":{\"include\":[\"list\",\"get\"]},\"cli\":true,\"tenantScoped\":{\"mode\":\"optional\"},\"conflictColumns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"]},\"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 \\\"created_by_user_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,\"foreignKey\":{\"table\":\"social_accounts\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"created_by_user_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"social_posts_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_posts_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"social_posts_social_account_id_idx\",\"columns\":[\"social_account_id\"]},{\"name\":\"social_posts_created_by_user_id_idx\",\"columns\":[\"created_by_user_id\"]},{\"name\":\"social_posts_video_content_id_idx\",\"columns\":[\"video_content_id\"]},{\"name\":\"social_posts_content_id_idx\",\"columns\":[\"content_id\"]}],\"version\":\"cfb50b15\"},\"importPath\":\"@happyvertical/smrt-social\"},\"@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\":{\"mcp\":false},\"extends\":\"SmrtCollection\",\"extendsTypeArg\":\"OAuthState\",\"exportName\":\"OAuthStateCollection\",\"collectionExportName\":\"OAuthStateCollectionCollection\",\"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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"oauth_states_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"oauth_states_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"709e111f\"},\"importPath\":\"@happyvertical/smrt-social\"},\"@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_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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"social_accounts_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_accounts_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]}],\"version\":\"0c175da6\"},\"importPath\":\"@happyvertical/smrt-social\"},\"@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,\"memberTypes\":[\"string\",\"SocialPlatformType\",\"PostAnalytics\",\"RawAnalyticsPayload\",\"Date\",\"string | null\"]}],\"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_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,\"foreignKey\":{\"table\":\"social_posts\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"social_post_analytics_snapshots_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_post_analytics_snapshots_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"social_post_analytics_snapshots_social_post_id_idx\",\"columns\":[\"social_post_id\"]}],\"version\":\"bd17983d\"},\"importPath\":\"@happyvertical/smrt-social\"},\"@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,\"unionBranches\":[{\"type\":\"Error\"},{\"type\":\"string\"}]}],\"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_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 \\\"created_by_user_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,\"foreignKey\":{\"table\":\"social_accounts\",\"column\":\"id\",\"onDelete\":\"NO ACTION\",\"onUpdate\":\"CASCADE\"}},\"created_by_user_id\":{\"type\":\"UUID\",\"referenceKind\":\"crossPackageRef\",\"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_slug_context_meta_type_idx\",\"columns\":[\"tenant_id\",\"slug\",\"context\",\"_meta_type\"],\"unique\":true,\"nullsNotDistinct\":true},{\"name\":\"social_posts_meta_type_idx\",\"columns\":[\"_meta_type\"]},{\"name\":\"social_posts_tenant_id_created_at_idx\",\"columns\":[\"tenant_id\",\"created_at\"]},{\"name\":\"social_posts_social_account_id_idx\",\"columns\":[\"social_account_id\"]},{\"name\":\"social_posts_created_by_user_id_idx\",\"columns\":[\"created_by_user_id\"]},{\"name\":\"social_posts_video_content_id_idx\",\"columns\":[\"video_content_id\"]},{\"name\":\"social_posts_content_id_idx\",\"columns\":[\"content_id\"]}],\"version\":\"cfb50b15\"},\"importPath\":\"@happyvertical/smrt-social\"}},\"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.54.4","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},"createdByUserId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-users:User"},"returnTo":{"type":"text","required":false}},"methods":{"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":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context","_meta_type"]},"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 \\"created_by_user_id\\" UUID,\\n \\"return_to\\" 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},"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},"created_by_user_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false},"return_to":{"type":"TEXT","notNull":false}},"indexes":[{"name":"oauth_states_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"oauth_states_meta_type_idx","columns":["_meta_type"]},{"name":"oauth_states_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"oauth_states_created_by_user_id_idx","columns":["created_by_user_id"]}],"version":"ca0ff7c5"},"importPath":"@happyvertical/smrt-social"},"@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":{"getSlug":{"name":"getSlug","async":true,"parameters":[],"returnType":"Promise<string | null | undefined>","isStatic":false,"isPublic":true},"setCredentials":{"name":"setCredentials","async":true,"parameters":[{"name":"credentials","type":"Record<string, unknown>","optional":false},{"name":"options","type":"object","optional":true,"memberTypes":["string"]}],"returnType":"Promise<void>","isStatic":false,"isPublic":true},"getCredentials":{"name":"getCredentials","async":true,"parameters":[],"returnType":"Promise<Record<string, unknown> | null>","isStatic":false,"isPublic":true}},"decoratorConfig":{"tableStrategy":"sti","api":{"include":["list","get","create","update","delete"]},"mcp":{"include":["list","get"]},"cli":{"skipApiCheck":true},"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context","_meta_type"]},"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_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"social_accounts_meta_type_idx","columns":["_meta_type"]},{"name":"social_accounts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"0c175da6"},"importPath":"@happyvertical/smrt-social"},"@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":{},"decoratorConfig":{"tableStrategy":"sti","api":{"include":["list","get","create","delete"]},"mcp":{"include":["list","get"]},"cli":true,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context","_meta_type"]},"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,"foreignKey":{"table":"social_posts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"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_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"social_post_analytics_snapshots_meta_type_idx","columns":["_meta_type"]},{"name":"social_post_analytics_snapshots_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"social_post_analytics_snapshots_social_post_id_idx","columns":["social_post_id"]}],"version":"bd17983d"},"importPath":"@happyvertical/smrt-social"},"@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"},"createdByUserId":{"type":"crossPackageRef","required":false,"related":"@happyvertical/smrt-users:User"},"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":{},"decoratorConfig":{"tableStrategy":"sti","api":{"include":["list","get","create","update","delete"]},"mcp":{"include":["list","get"]},"cli":true,"tenantScoped":{"mode":"optional"},"conflictColumns":["tenant_id","slug","context","_meta_type"]},"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 \\"created_by_user_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,"foreignKey":{"table":"social_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"created_by_user_id":{"type":"UUID","referenceKind":"crossPackageRef","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_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"social_posts_meta_type_idx","columns":["_meta_type"]},{"name":"social_posts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"social_posts_social_account_id_idx","columns":["social_account_id"]},{"name":"social_posts_created_by_user_id_idx","columns":["created_by_user_id"]},{"name":"social_posts_video_content_id_idx","columns":["video_content_id"]},{"name":"social_posts_content_id_idx","columns":["content_id"]}],"version":"cfb50b15"},"importPath":"@happyvertical/smrt-social"},"@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},"consume":{"name":"consume","async":true,"parameters":[{"name":"state","type":"OAuthState","optional":false}],"returnType":"Promise<boolean>","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":{"mcp":false},"extends":"SmrtCollection","extendsTypeArg":"OAuthState","exportName":"OAuthStateCollection","collectionExportName":"OAuthStateCollectionCollection","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 \\"created_by_user_id\\" UUID,\\n \\"return_to\\" 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},"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},"created_by_user_id":{"type":"UUID","referenceKind":"crossPackageRef","notNull":false},"return_to":{"type":"TEXT","notNull":false}},"indexes":[{"name":"oauth_states_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"oauth_states_meta_type_idx","columns":["_meta_type"]},{"name":"oauth_states_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"oauth_states_created_by_user_id_idx","columns":["created_by_user_id"]}],"version":"ca0ff7c5"},"importPath":"@happyvertical/smrt-social"},"@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_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_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"social_accounts_meta_type_idx","columns":["_meta_type"]},{"name":"social_accounts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]}],"version":"0c175da6"},"importPath":"@happyvertical/smrt-social"},"@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,"memberTypes":["string","SocialPlatformType","PostAnalytics","RawAnalyticsPayload","Date","string | null"]}],"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_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,"foreignKey":{"table":"social_posts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"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_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"social_post_analytics_snapshots_meta_type_idx","columns":["_meta_type"]},{"name":"social_post_analytics_snapshots_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"social_post_analytics_snapshots_social_post_id_idx","columns":["social_post_id"]}],"version":"bd17983d"},"importPath":"@happyvertical/smrt-social"},"@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,"unionBranches":[{"type":"Error"},{"type":"string"}]}],"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_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 \\"created_by_user_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,"foreignKey":{"table":"social_accounts","column":"id","onDelete":"NO ACTION","onUpdate":"CASCADE"}},"created_by_user_id":{"type":"UUID","referenceKind":"crossPackageRef","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_slug_context_meta_type_idx","columns":["tenant_id","slug","context","_meta_type"],"unique":true,"nullsNotDistinct":true},{"name":"social_posts_meta_type_idx","columns":["_meta_type"]},{"name":"social_posts_tenant_id_created_at_idx","columns":["tenant_id","created_at"]},{"name":"social_posts_social_account_id_idx","columns":["social_account_id"]},{"name":"social_posts_created_by_user_id_idx","columns":["created_by_user_id"]},{"name":"social_posts_video_content_id_idx","columns":["video_content_id"]},{"name":"social_posts_content_id_idx","columns":["content_id"]}],"version":"cfb50b15"},"importPath":"@happyvertical/smrt-social"}},"moduleType":"smrt","smrtDependencies":["@happyvertical/smrt-content","@happyvertical/smrt-core","@happyvertical/smrt-secrets","@happyvertical/smrt-tenancy","@happyvertical/smrt-video"],"stampsConstructors":true}`));
|
|
8
8
|
//#endregion
|
|
9
9
|
//#region src/oauth-state.ts
|
|
10
10
|
var __defProp$3 = Object.defineProperty;
|
|
11
11
|
var __getOwnPropDesc$3 = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __defNormalProp$3 = (obj, key, value) => key in obj ? __defProp$3(obj, key, {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value
|
|
17
|
+
}) : obj[key] = value;
|
|
12
18
|
var __decorateClass$3 = (decorators, target, key, kind) => {
|
|
13
19
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$3(target, key) : target;
|
|
14
20
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
15
21
|
if (kind && result) __defProp$3(target, key, result);
|
|
16
22
|
return result;
|
|
17
23
|
};
|
|
24
|
+
var __publicField$3 = (obj, key, value) => __defNormalProp$3(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
18
25
|
var OAuthState = class extends SmrtObject {
|
|
19
26
|
tenantId = null;
|
|
20
27
|
/**
|
|
@@ -45,6 +52,13 @@ var OAuthState = class extends SmrtObject {
|
|
|
45
52
|
* States should be short-lived (10 minutes typical)
|
|
46
53
|
*/
|
|
47
54
|
expiresAt = new Date(Date.now() + 600 * 1e3);
|
|
55
|
+
createdByUserId = null;
|
|
56
|
+
/**
|
|
57
|
+
* Application-defined path to return to after the callback, for example the
|
|
58
|
+
* settings page that started the flow. Opaque to the framework: the host
|
|
59
|
+
* that reads it must validate it as a same-origin path before redirecting.
|
|
60
|
+
*/
|
|
61
|
+
returnTo = null;
|
|
48
62
|
constructor(options = {}) {
|
|
49
63
|
super(options);
|
|
50
64
|
if (options.platform !== void 0) this.platform = options.platform;
|
|
@@ -54,6 +68,8 @@ var OAuthState = class extends SmrtObject {
|
|
|
54
68
|
if (options.scopes !== void 0) this.scopes = options.scopes;
|
|
55
69
|
if (options.expiresAt !== void 0) this.expiresAt = options.expiresAt;
|
|
56
70
|
if (options.tenantId !== void 0) this.tenantId = options.tenantId;
|
|
71
|
+
if (options.createdByUserId !== void 0) this.createdByUserId = options.createdByUserId;
|
|
72
|
+
if (options.returnTo !== void 0) this.returnTo = options.returnTo;
|
|
57
73
|
}
|
|
58
74
|
/**
|
|
59
75
|
* Check if the state has expired
|
|
@@ -98,7 +114,9 @@ var OAuthState = class extends SmrtObject {
|
|
|
98
114
|
return btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
|
|
99
115
|
}
|
|
100
116
|
};
|
|
117
|
+
__publicField$3(OAuthState, "__smrtPackage__", "@happyvertical/smrt-social");
|
|
101
118
|
__decorateClass$3([tenantId({ nullable: true })], OAuthState.prototype, "tenantId", 2);
|
|
119
|
+
__decorateClass$3([crossPackageRef("@happyvertical/smrt-users:User")], OAuthState.prototype, "createdByUserId", 2);
|
|
102
120
|
OAuthState = __decorateClass$3([TenantScoped({ mode: "optional" }), smrt({
|
|
103
121
|
tableStrategy: "sti",
|
|
104
122
|
api: { include: [
|
|
@@ -117,6 +135,25 @@ var OAuthStateCollection = class extends SmrtCollection {
|
|
|
117
135
|
async findByState(state) {
|
|
118
136
|
return this.get({ state });
|
|
119
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Consume a loaded state exactly once.
|
|
140
|
+
*
|
|
141
|
+
* Deletes the record with a revision-guarded delete, so when two callbacks
|
|
142
|
+
* race on the same state only one delete removes the row. Returns `true`
|
|
143
|
+
* for that caller and `false` for every caller whose row was already gone
|
|
144
|
+
* or changed; any other failure propagates. Call it before acting on the
|
|
145
|
+
* state (exchanging the code), and stop when it returns `false`.
|
|
146
|
+
*/
|
|
147
|
+
async consume(state) {
|
|
148
|
+
if (!state.id || !state.updated_at) return false;
|
|
149
|
+
try {
|
|
150
|
+
await state.delete({ expectedUpdatedAt: state.updated_at });
|
|
151
|
+
return true;
|
|
152
|
+
} catch (error) {
|
|
153
|
+
if (error instanceof RuntimeError && error.code === "RUNTIME_REVISION_CONFLICT") return false;
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
120
157
|
async findExpired(now = /* @__PURE__ */ new Date()) {
|
|
121
158
|
return this.list({
|
|
122
159
|
where: { "expiresAt <=": now },
|
|
@@ -133,12 +170,19 @@ var OAuthStateCollection = class extends SmrtCollection {
|
|
|
133
170
|
//#region src/social-account.ts
|
|
134
171
|
var __defProp$2 = Object.defineProperty;
|
|
135
172
|
var __getOwnPropDesc$2 = Object.getOwnPropertyDescriptor;
|
|
173
|
+
var __defNormalProp$2 = (obj, key, value) => key in obj ? __defProp$2(obj, key, {
|
|
174
|
+
enumerable: true,
|
|
175
|
+
configurable: true,
|
|
176
|
+
writable: true,
|
|
177
|
+
value
|
|
178
|
+
}) : obj[key] = value;
|
|
136
179
|
var __decorateClass$2 = (decorators, target, key, kind) => {
|
|
137
180
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$2(target, key) : target;
|
|
138
181
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
139
182
|
if (kind && result) __defProp$2(target, key, result);
|
|
140
183
|
return result;
|
|
141
184
|
};
|
|
185
|
+
var __publicField$2 = (obj, key, value) => __defNormalProp$2(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
142
186
|
var SocialAccount = class extends SmrtObject {
|
|
143
187
|
tenantId = null;
|
|
144
188
|
/**
|
|
@@ -362,6 +406,7 @@ var SocialAccount = class extends SmrtObject {
|
|
|
362
406
|
return tenantId2;
|
|
363
407
|
}
|
|
364
408
|
};
|
|
409
|
+
__publicField$2(SocialAccount, "__smrtPackage__", "@happyvertical/smrt-social");
|
|
365
410
|
__decorateClass$2([tenantId({ nullable: true })], SocialAccount.prototype, "tenantId", 2);
|
|
366
411
|
SocialAccount = __decorateClass$2([TenantScoped({ mode: "optional" }), smrt({
|
|
367
412
|
tableStrategy: "sti",
|
|
@@ -402,12 +447,19 @@ var SocialAccountCollection = class extends SmrtCollection {
|
|
|
402
447
|
//#region src/social-post.ts
|
|
403
448
|
var __defProp$1 = Object.defineProperty;
|
|
404
449
|
var __getOwnPropDesc$1 = Object.getOwnPropertyDescriptor;
|
|
450
|
+
var __defNormalProp$1 = (obj, key, value) => key in obj ? __defProp$1(obj, key, {
|
|
451
|
+
enumerable: true,
|
|
452
|
+
configurable: true,
|
|
453
|
+
writable: true,
|
|
454
|
+
value
|
|
455
|
+
}) : obj[key] = value;
|
|
405
456
|
var __decorateClass$1 = (decorators, target, key, kind) => {
|
|
406
457
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc$1(target, key) : target;
|
|
407
458
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
408
459
|
if (kind && result) __defProp$1(target, key, result);
|
|
409
460
|
return result;
|
|
410
461
|
};
|
|
462
|
+
var __publicField$1 = (obj, key, value) => __defNormalProp$1(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
411
463
|
var SocialPost = class extends SmrtObject {
|
|
412
464
|
tenantId = null;
|
|
413
465
|
socialAccountId = null;
|
|
@@ -543,6 +595,7 @@ var SocialPost = class extends SmrtObject {
|
|
|
543
595
|
return parts.join("\n\n");
|
|
544
596
|
}
|
|
545
597
|
};
|
|
598
|
+
__publicField$1(SocialPost, "__smrtPackage__", "@happyvertical/smrt-social");
|
|
546
599
|
__decorateClass$1([tenantId({ nullable: true })], SocialPost.prototype, "tenantId", 2);
|
|
547
600
|
__decorateClass$1([foreignKey(SocialAccount)], SocialPost.prototype, "socialAccountId", 2);
|
|
548
601
|
__decorateClass$1([crossPackageRef("@happyvertical/smrt-users:User")], SocialPost.prototype, "createdByUserId", 2);
|
|
@@ -564,12 +617,19 @@ SocialPost = __decorateClass$1([TenantScoped({ mode: "optional" }), smrt({
|
|
|
564
617
|
//#region src/social-post-analytics-snapshot.ts
|
|
565
618
|
var __defProp = Object.defineProperty;
|
|
566
619
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
620
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
|
|
621
|
+
enumerable: true,
|
|
622
|
+
configurable: true,
|
|
623
|
+
writable: true,
|
|
624
|
+
value
|
|
625
|
+
}) : obj[key] = value;
|
|
567
626
|
var __decorateClass = (decorators, target, key, kind) => {
|
|
568
627
|
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
569
628
|
for (var i = decorators.length - 1, decorator; i >= 0; i--) if (decorator = decorators[i]) result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
570
629
|
if (kind && result) __defProp(target, key, result);
|
|
571
630
|
return result;
|
|
572
631
|
};
|
|
632
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
573
633
|
var SocialPostAnalyticsSnapshot = class extends SmrtObject {
|
|
574
634
|
tenantId = null;
|
|
575
635
|
socialPostId = null;
|
|
@@ -587,6 +647,7 @@ var SocialPostAnalyticsSnapshot = class extends SmrtObject {
|
|
|
587
647
|
if (options.capturedAt !== void 0) this.capturedAt = options.capturedAt;
|
|
588
648
|
}
|
|
589
649
|
};
|
|
650
|
+
__publicField(SocialPostAnalyticsSnapshot, "__smrtPackage__", "@happyvertical/smrt-social");
|
|
590
651
|
__decorateClass([tenantId({ nullable: true })], SocialPostAnalyticsSnapshot.prototype, "tenantId", 2);
|
|
591
652
|
__decorateClass([foreignKey(SocialPost)], SocialPostAnalyticsSnapshot.prototype, "socialPostId", 2);
|
|
592
653
|
__decorateClass([field({ required: true })], SocialPostAnalyticsSnapshot.prototype, "platform", 2);
|