@happyvertical/smrt-social 0.54.3 → 0.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +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 +31 -2
- package/dist/index.js.map +1 -1
- package/dist/manifest.json +58 -5
- 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 +9 -9
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,10 +1,10 @@
|
|
|
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.3","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"],"stampsConstructors":true}`));
|
|
7
|
+
ObjectRegistry.registerPackageManifest(JSON.parse(`{"version":"1.0.0","timestamp":0,"packageName":"@happyvertical/smrt-social","packageVersion":"0.55.0","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;
|
|
@@ -52,6 +52,13 @@ var OAuthState = class extends SmrtObject {
|
|
|
52
52
|
* States should be short-lived (10 minutes typical)
|
|
53
53
|
*/
|
|
54
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;
|
|
55
62
|
constructor(options = {}) {
|
|
56
63
|
super(options);
|
|
57
64
|
if (options.platform !== void 0) this.platform = options.platform;
|
|
@@ -61,6 +68,8 @@ var OAuthState = class extends SmrtObject {
|
|
|
61
68
|
if (options.scopes !== void 0) this.scopes = options.scopes;
|
|
62
69
|
if (options.expiresAt !== void 0) this.expiresAt = options.expiresAt;
|
|
63
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;
|
|
64
73
|
}
|
|
65
74
|
/**
|
|
66
75
|
* Check if the state has expired
|
|
@@ -107,6 +116,7 @@ var OAuthState = class extends SmrtObject {
|
|
|
107
116
|
};
|
|
108
117
|
__publicField$3(OAuthState, "__smrtPackage__", "@happyvertical/smrt-social");
|
|
109
118
|
__decorateClass$3([tenantId({ nullable: true })], OAuthState.prototype, "tenantId", 2);
|
|
119
|
+
__decorateClass$3([crossPackageRef("@happyvertical/smrt-users:User")], OAuthState.prototype, "createdByUserId", 2);
|
|
110
120
|
OAuthState = __decorateClass$3([TenantScoped({ mode: "optional" }), smrt({
|
|
111
121
|
tableStrategy: "sti",
|
|
112
122
|
api: { include: [
|
|
@@ -125,6 +135,25 @@ var OAuthStateCollection = class extends SmrtCollection {
|
|
|
125
135
|
async findByState(state) {
|
|
126
136
|
return this.get({ state });
|
|
127
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
|
+
}
|
|
128
157
|
async findExpired(now = /* @__PURE__ */ new Date()) {
|
|
129
158
|
return this.list({
|
|
130
159
|
where: { "expiresAt <=": now },
|