248-sdk 0.1.0__tar.gz

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.
@@ -0,0 +1,11 @@
1
+ __pycache__/
2
+ .env
3
+ .DS_Store
4
+ .idea/
5
+ .vscode/
6
+ .pytest_cache/
7
+ .ruff_cache/
8
+ .mypy_cache/
9
+ .coverage
10
+ .coverage.*
11
+ .coverage.*
248_sdk-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,157 @@
1
+ Metadata-Version: 2.4
2
+ Name: 248-sdk
3
+ Version: 0.1.0
4
+ Summary: Shared SDK for 248 products - MongoDB models, PostgreSQL models, and SmartLead schemas
5
+ Project-URL: Repository, https://github.com/248ai/248-sdk
6
+ Author-email: Wenzo Rithelly <rithellyenzo@gmail.com>
7
+ License: MIT
8
+ Keywords: beanie,mongodb,postgresql,sdk,smartlead,sqlalchemy
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.10
14
+ Classifier: Programming Language :: Python :: 3.11
15
+ Classifier: Programming Language :: Python :: 3.12
16
+ Classifier: Typing :: Typed
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: beanie<3.0.0,>=2.0.1
19
+ Requires-Dist: motor<4.0.0,>=3.3.0
20
+ Requires-Dist: pydantic<3.0.0,>=2.0.0
21
+ Requires-Dist: sqlalchemy<3.0.0,>=2.0.0
22
+ Provides-Extra: all
23
+ Requires-Dist: mypy>=1.8.0; extra == 'all'
24
+ Requires-Dist: psycopg2-binary<3.0.0,>=2.9.0; extra == 'all'
25
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'all'
26
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'all'
27
+ Requires-Dist: pytest>=8.0.0; extra == 'all'
28
+ Requires-Dist: ruff>=0.2.0; extra == 'all'
29
+ Provides-Extra: asyncpg
30
+ Requires-Dist: asyncpg<1.0.0,>=0.29.0; extra == 'asyncpg'
31
+ Provides-Extra: dev
32
+ Requires-Dist: mypy>=1.8.0; extra == 'dev'
33
+ Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
34
+ Requires-Dist: pytest-cov>=4.0.0; extra == 'dev'
35
+ Requires-Dist: pytest>=8.0.0; extra == 'dev'
36
+ Requires-Dist: ruff>=0.2.0; extra == 'dev'
37
+ Provides-Extra: postgres
38
+ Requires-Dist: psycopg2-binary<3.0.0,>=2.9.0; extra == 'postgres'
39
+ Description-Content-Type: text/markdown
40
+
41
+ # 248 SDK
42
+
43
+ Shared SDK for 248 products - MongoDB models, PostgreSQL models, and SmartLead schemas.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ # From Git
49
+ pip install git+https://github.com/248ai/248-sdk.git
50
+
51
+ # With PostgreSQL support
52
+ pip install "248-sdk[postgres] @ git+https://github.com/248ai/248-sdk.git"
53
+
54
+ # Local development (editable)
55
+ pip install -e .
56
+ ```
57
+
58
+ ## Quick Start
59
+
60
+ ### MongoDB Models
61
+
62
+ ```python
63
+ import asyncio
64
+ from sdk_248 import mongodb
65
+ from sdk_248.models import Campaign, CampaignStatus
66
+
67
+ async def main():
68
+ # Initialize MongoDB connection
69
+ await mongodb.initialize(
70
+ connection_string="mongodb://localhost:27017",
71
+ database_name="mydb"
72
+ )
73
+
74
+ # Query campaigns
75
+ campaigns = await Campaign.find(
76
+ Campaign.status == CampaignStatus.RUNNING
77
+ ).to_list()
78
+
79
+ for campaign in campaigns:
80
+ print(f"Campaign: {campaign.name}")
81
+
82
+ # Close connection
83
+ await mongodb.close()
84
+
85
+ asyncio.run(main())
86
+ ```
87
+
88
+ ### PostgreSQL Models
89
+
90
+ ```python
91
+ from sdk_248 import postgres
92
+ from sdk_248.models import Organization
93
+
94
+ # Initialize PostgreSQL
95
+ postgres.initialize(
96
+ connection_string="postgresql://user:pass@localhost:5432/db"
97
+ )
98
+
99
+ # Use sessions
100
+ with postgres.session() as session:
101
+ orgs = session.query(Organization).all()
102
+ for org in orgs:
103
+ print(f"Organization: {org.name}")
104
+ ```
105
+
106
+ ### Using Models Without Database
107
+
108
+ ```python
109
+ from sdk_248.models import Lead, CampaignStatus
110
+
111
+ # Create models for validation/serialization
112
+ lead = Lead(
113
+ email="test@example.com",
114
+ first_name="John",
115
+ last_name="Doe"
116
+ )
117
+
118
+ # Serialize to dict
119
+ lead_dict = lead.model_dump()
120
+
121
+ # Use enums
122
+ status = CampaignStatus.RUNNING
123
+ ```
124
+
125
+ ## Available Exports
126
+
127
+ ### From `sdk_248`
128
+ - `MongoDBManager`, `mongodb` - MongoDB connection management
129
+ - `PostgresManager`, `postgres`, `Base` - PostgreSQL connection management
130
+
131
+ ### From `sdk_248.models`
132
+
133
+ #### Enums
134
+ - `CampaignStatus` - Campaign status values
135
+ - `EmailOrchestrator` - Email orchestrator options
136
+ - `AppType` - Application types
137
+ - `NodeType` - Node types for responder actions
138
+ - `ActionRunStatus` - Action run status values
139
+ - `CategoriserStatus` - Categoriser status values
140
+
141
+ #### MongoDB Models
142
+ - `Campaign` - Main campaign document (Beanie)
143
+ - `Lead` - Lead embedded model
144
+ - `ActionRun` - Action run embedded model
145
+ - `Node` - Responder node model
146
+
147
+ #### PostgreSQL Models
148
+ - `Organization` - Organization entity
149
+ - `OrganizationStatus` - Organization status enum
150
+
151
+ ### From `sdk_248.schemas`
152
+ - `CampaignSequenceInput` - Campaign sequence configuration
153
+ - `CampaignReplyWebhookSchema` - Reply webhook payload
154
+ - `EmailSentWebhookSchema` - Email sent webhook payload
155
+ - `Organization` - Organization response schema (Pydantic)
156
+ - `OrganizationCreate` - Organization create schema
157
+ - `OrganizationUpdate` - Organization update schema
@@ -0,0 +1,117 @@
1
+ # 248 SDK
2
+
3
+ Shared SDK for 248 products - MongoDB models, PostgreSQL models, and SmartLead schemas.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ # From Git
9
+ pip install git+https://github.com/248ai/248-sdk.git
10
+
11
+ # With PostgreSQL support
12
+ pip install "248-sdk[postgres] @ git+https://github.com/248ai/248-sdk.git"
13
+
14
+ # Local development (editable)
15
+ pip install -e .
16
+ ```
17
+
18
+ ## Quick Start
19
+
20
+ ### MongoDB Models
21
+
22
+ ```python
23
+ import asyncio
24
+ from sdk_248 import mongodb
25
+ from sdk_248.models import Campaign, CampaignStatus
26
+
27
+ async def main():
28
+ # Initialize MongoDB connection
29
+ await mongodb.initialize(
30
+ connection_string="mongodb://localhost:27017",
31
+ database_name="mydb"
32
+ )
33
+
34
+ # Query campaigns
35
+ campaigns = await Campaign.find(
36
+ Campaign.status == CampaignStatus.RUNNING
37
+ ).to_list()
38
+
39
+ for campaign in campaigns:
40
+ print(f"Campaign: {campaign.name}")
41
+
42
+ # Close connection
43
+ await mongodb.close()
44
+
45
+ asyncio.run(main())
46
+ ```
47
+
48
+ ### PostgreSQL Models
49
+
50
+ ```python
51
+ from sdk_248 import postgres
52
+ from sdk_248.models import Organization
53
+
54
+ # Initialize PostgreSQL
55
+ postgres.initialize(
56
+ connection_string="postgresql://user:pass@localhost:5432/db"
57
+ )
58
+
59
+ # Use sessions
60
+ with postgres.session() as session:
61
+ orgs = session.query(Organization).all()
62
+ for org in orgs:
63
+ print(f"Organization: {org.name}")
64
+ ```
65
+
66
+ ### Using Models Without Database
67
+
68
+ ```python
69
+ from sdk_248.models import Lead, CampaignStatus
70
+
71
+ # Create models for validation/serialization
72
+ lead = Lead(
73
+ email="test@example.com",
74
+ first_name="John",
75
+ last_name="Doe"
76
+ )
77
+
78
+ # Serialize to dict
79
+ lead_dict = lead.model_dump()
80
+
81
+ # Use enums
82
+ status = CampaignStatus.RUNNING
83
+ ```
84
+
85
+ ## Available Exports
86
+
87
+ ### From `sdk_248`
88
+ - `MongoDBManager`, `mongodb` - MongoDB connection management
89
+ - `PostgresManager`, `postgres`, `Base` - PostgreSQL connection management
90
+
91
+ ### From `sdk_248.models`
92
+
93
+ #### Enums
94
+ - `CampaignStatus` - Campaign status values
95
+ - `EmailOrchestrator` - Email orchestrator options
96
+ - `AppType` - Application types
97
+ - `NodeType` - Node types for responder actions
98
+ - `ActionRunStatus` - Action run status values
99
+ - `CategoriserStatus` - Categoriser status values
100
+
101
+ #### MongoDB Models
102
+ - `Campaign` - Main campaign document (Beanie)
103
+ - `Lead` - Lead embedded model
104
+ - `ActionRun` - Action run embedded model
105
+ - `Node` - Responder node model
106
+
107
+ #### PostgreSQL Models
108
+ - `Organization` - Organization entity
109
+ - `OrganizationStatus` - Organization status enum
110
+
111
+ ### From `sdk_248.schemas`
112
+ - `CampaignSequenceInput` - Campaign sequence configuration
113
+ - `CampaignReplyWebhookSchema` - Reply webhook payload
114
+ - `EmailSentWebhookSchema` - Email sent webhook payload
115
+ - `Organization` - Organization response schema (Pydantic)
116
+ - `OrganizationCreate` - Organization create schema
117
+ - `OrganizationUpdate` - Organization update schema
@@ -0,0 +1,78 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "248-sdk"
7
+ version = "0.1.0"
8
+ description = "Shared SDK for 248 products - MongoDB models, PostgreSQL models, and SmartLead schemas"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ authors = [
12
+ {name = "Wenzo Rithelly", email = "rithellyenzo@gmail.com"}
13
+ ]
14
+ requires-python = ">=3.10"
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.10",
21
+ "Programming Language :: Python :: 3.11",
22
+ "Programming Language :: Python :: 3.12",
23
+ "Typing :: Typed",
24
+ ]
25
+ keywords = ["sdk", "mongodb", "postgresql", "beanie", "sqlalchemy", "smartlead"]
26
+
27
+ dependencies = [
28
+ "pydantic>=2.0.0,<3.0.0",
29
+ "beanie>=2.0.1,<3.0.0",
30
+ "motor>=3.3.0,<4.0.0",
31
+ "sqlalchemy>=2.0.0,<3.0.0",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ postgres = [
36
+ "psycopg2-binary>=2.9.0,<3.0.0",
37
+ ]
38
+ asyncpg = [
39
+ "asyncpg>=0.29.0,<1.0.0",
40
+ ]
41
+ dev = [
42
+ "pytest>=8.0.0",
43
+ "pytest-asyncio>=0.23.0",
44
+ "pytest-cov>=4.0.0",
45
+ "mypy>=1.8.0",
46
+ "ruff>=0.2.0",
47
+ ]
48
+ all = [
49
+ "248-sdk[postgres,dev]",
50
+ ]
51
+
52
+ [project.urls]
53
+ Repository = "https://github.com/248ai/248-sdk"
54
+
55
+ [tool.hatch.build.targets.wheel]
56
+ packages = ["sdk_248"]
57
+
58
+ [tool.hatch.build.targets.sdist]
59
+ include = [
60
+ "/sdk_248",
61
+ ]
62
+
63
+ [tool.pytest.ini_options]
64
+ testpaths = ["tests"]
65
+ asyncio_mode = "auto"
66
+
67
+ [tool.mypy]
68
+ python_version = "3.10"
69
+ strict = true
70
+ warn_return_any = true
71
+ warn_unused_ignores = true
72
+
73
+ [tool.ruff]
74
+ line-length = 100
75
+ target-version = "py310"
76
+
77
+ [tool.ruff.lint]
78
+ select = ["E", "F", "I", "N", "W", "B", "Q"]
@@ -0,0 +1,34 @@
1
+ """248 SDK - Shared models and utilities for 248 products.
2
+
3
+ Usage:
4
+ from sdk_248 import mongodb, postgres
5
+ from sdk_248.models import Campaign, CampaignStatus
6
+
7
+ # Initialize MongoDB
8
+ await mongodb.initialize(
9
+ connection_string="mongodb://localhost:27017",
10
+ database_name="mydb"
11
+ )
12
+
13
+ # Use models
14
+ campaigns = await Campaign.find(
15
+ Campaign.status == CampaignStatus.RUNNING
16
+ ).to_list()
17
+ """
18
+
19
+ __version__ = "0.1.0"
20
+
21
+ # Database managers
22
+ from sdk_248.db.mongo import MongoDBManager, mongodb
23
+ from sdk_248.db.postgres import Base, PostgresManager, postgres
24
+
25
+ __all__ = [
26
+ # Version
27
+ "__version__",
28
+ # Database managers
29
+ "MongoDBManager",
30
+ "mongodb",
31
+ "PostgresManager",
32
+ "postgres",
33
+ "Base",
34
+ ]
@@ -0,0 +1,12 @@
1
+ """Database connection managers for the SDK."""
2
+
3
+ from sdk_248.db.mongo import MongoDBManager, mongodb
4
+ from sdk_248.db.postgres import Base, PostgresManager, postgres
5
+
6
+ __all__ = [
7
+ "MongoDBManager",
8
+ "mongodb",
9
+ "PostgresManager",
10
+ "postgres",
11
+ "Base",
12
+ ]
@@ -0,0 +1,119 @@
1
+ """MongoDB connection and Beanie initialization for the SDK."""
2
+
3
+ from typing import List, Optional, Type
4
+
5
+ from beanie import Document, init_beanie
6
+ from motor.motor_asyncio import AsyncIOMotorClient, AsyncIOMotorDatabase
7
+
8
+
9
+ class MongoDBManager:
10
+ """Manages MongoDB connections and Beanie initialization.
11
+
12
+ Usage:
13
+ # Option 1: Let the SDK create the client
14
+ from sdk_248 import mongodb, Campaign
15
+
16
+ await mongodb.initialize(
17
+ connection_string="mongodb://user:pass@host:27017",
18
+ database_name="mydb"
19
+ )
20
+
21
+ # Now use models
22
+ campaigns = await Campaign.find_all().to_list()
23
+
24
+ # Option 2: Use your own client
25
+ from motor.motor_asyncio import AsyncIOMotorClient
26
+ from sdk_248 import MongoDBManager, Campaign
27
+
28
+ client = AsyncIOMotorClient("mongodb://...")
29
+ manager = MongoDBManager()
30
+ await manager.initialize_with_client(
31
+ client=client,
32
+ database_name="mydb"
33
+ )
34
+ """
35
+
36
+ _client: Optional[AsyncIOMotorClient] = None
37
+ _database: Optional[AsyncIOMotorDatabase] = None
38
+ _initialized: bool = False
39
+
40
+ def _get_document_models(self) -> List[Type[Document]]:
41
+ """Get all Beanie document models to register.
42
+
43
+ Import here to avoid circular imports.
44
+ """
45
+ from sdk_248.models.mongo.campaign import Campaign
46
+
47
+ return [Campaign]
48
+
49
+ async def initialize(
50
+ self,
51
+ connection_string: str,
52
+ database_name: str,
53
+ document_models: Optional[List[Type[Document]]] = None,
54
+ ) -> None:
55
+ """Initialize MongoDB connection and Beanie ODM.
56
+
57
+ Args:
58
+ connection_string: MongoDB connection URI
59
+ database_name: Name of the database to use
60
+ document_models: Optional custom list of document models.
61
+ If None, uses default SDK models.
62
+ """
63
+ self._client = AsyncIOMotorClient(connection_string)
64
+ self._database = self._client[database_name]
65
+
66
+ models = document_models or self._get_document_models()
67
+ await init_beanie(database=self._database, document_models=models)
68
+ self._initialized = True
69
+
70
+ async def initialize_with_client(
71
+ self,
72
+ client: AsyncIOMotorClient,
73
+ database_name: str,
74
+ document_models: Optional[List[Type[Document]]] = None,
75
+ ) -> None:
76
+ """Initialize Beanie with an existing MongoDB client.
77
+
78
+ Args:
79
+ client: Existing AsyncIOMotorClient instance
80
+ database_name: Name of the database to use
81
+ document_models: Optional custom list of document models
82
+ """
83
+ self._client = client
84
+ self._database = client[database_name]
85
+
86
+ models = document_models or self._get_document_models()
87
+ await init_beanie(database=self._database, document_models=models)
88
+ self._initialized = True
89
+
90
+ async def close(self) -> None:
91
+ """Close the MongoDB connection."""
92
+ if self._client:
93
+ self._client.close()
94
+ self._client = None
95
+ self._database = None
96
+ self._initialized = False
97
+
98
+ @property
99
+ def database(self) -> AsyncIOMotorDatabase:
100
+ """Get the database instance."""
101
+ if not self._initialized:
102
+ raise RuntimeError("MongoDB not initialized. Call initialize() first.")
103
+ return self._database
104
+
105
+ @property
106
+ def client(self) -> AsyncIOMotorClient:
107
+ """Get the MongoDB client instance."""
108
+ if not self._initialized:
109
+ raise RuntimeError("MongoDB not initialized. Call initialize() first.")
110
+ return self._client
111
+
112
+ @property
113
+ def is_initialized(self) -> bool:
114
+ """Check if the database is initialized."""
115
+ return self._initialized
116
+
117
+
118
+ # Global instance for convenience
119
+ mongodb = MongoDBManager()
@@ -0,0 +1,139 @@
1
+ """PostgreSQL connection and SQLAlchemy setup for the SDK."""
2
+
3
+ from contextlib import contextmanager
4
+ from typing import Generator, Optional
5
+
6
+ from sqlalchemy import create_engine
7
+ from sqlalchemy.engine import Engine
8
+ from sqlalchemy.orm import Session, declarative_base, sessionmaker
9
+
10
+ # Create the declarative base for all SQLAlchemy models
11
+ Base = declarative_base()
12
+
13
+
14
+ class PostgresManager:
15
+ """Manages PostgreSQL connections and sessions.
16
+
17
+ Usage:
18
+ from sdk_248 import postgres, Organization
19
+
20
+ # Initialize PostgreSQL
21
+ postgres.initialize(
22
+ connection_string="postgresql://user:pass@host:5432/db"
23
+ )
24
+
25
+ # Use sessions
26
+ with postgres.session() as session:
27
+ orgs = session.query(Organization).all()
28
+
29
+ # Or create tables
30
+ postgres.create_tables()
31
+ """
32
+
33
+ _engine: Optional[Engine] = None
34
+ _session_factory: Optional[sessionmaker] = None
35
+ _initialized: bool = False
36
+
37
+ def initialize(
38
+ self,
39
+ connection_string: str,
40
+ echo: bool = False,
41
+ pool_size: int = 5,
42
+ max_overflow: int = 10,
43
+ ) -> None:
44
+ """Initialize PostgreSQL connection.
45
+
46
+ Args:
47
+ connection_string: PostgreSQL connection URI
48
+ echo: If True, log all SQL statements
49
+ pool_size: Connection pool size
50
+ max_overflow: Max connections beyond pool_size
51
+ """
52
+ self._engine = create_engine(
53
+ connection_string,
54
+ echo=echo,
55
+ pool_size=pool_size,
56
+ max_overflow=max_overflow,
57
+ )
58
+ self._session_factory = sessionmaker(
59
+ autocommit=False,
60
+ autoflush=False,
61
+ bind=self._engine,
62
+ )
63
+ self._initialized = True
64
+
65
+ def initialize_with_engine(self, engine: Engine) -> None:
66
+ """Initialize with an existing SQLAlchemy engine.
67
+
68
+ Args:
69
+ engine: Existing SQLAlchemy Engine instance
70
+ """
71
+ self._engine = engine
72
+ self._session_factory = sessionmaker(
73
+ autocommit=False,
74
+ autoflush=False,
75
+ bind=self._engine,
76
+ )
77
+ self._initialized = True
78
+
79
+ @contextmanager
80
+ def session(self) -> Generator[Session, None, None]:
81
+ """Get a database session (context manager).
82
+
83
+ Yields:
84
+ SQLAlchemy Session instance
85
+
86
+ Example:
87
+ with postgres.session() as session:
88
+ orgs = session.query(Organization).all()
89
+ """
90
+ if not self._initialized:
91
+ raise RuntimeError("PostgreSQL not initialized. Call initialize() first.")
92
+
93
+ session = self._session_factory()
94
+ try:
95
+ yield session
96
+ session.commit()
97
+ except Exception:
98
+ session.rollback()
99
+ raise
100
+ finally:
101
+ session.close()
102
+
103
+ def create_session(self) -> Session:
104
+ """Create a new session (caller responsible for closing).
105
+
106
+ Returns:
107
+ SQLAlchemy Session instance
108
+ """
109
+ if not self._initialized:
110
+ raise RuntimeError("PostgreSQL not initialized. Call initialize() first.")
111
+ return self._session_factory()
112
+
113
+ @property
114
+ def engine(self) -> Engine:
115
+ """Get the SQLAlchemy engine."""
116
+ if not self._initialized:
117
+ raise RuntimeError("PostgreSQL not initialized. Call initialize() first.")
118
+ return self._engine
119
+
120
+ def create_tables(self) -> None:
121
+ """Create all tables defined in models."""
122
+ if not self._initialized:
123
+ raise RuntimeError("PostgreSQL not initialized. Call initialize() first.")
124
+ Base.metadata.create_all(bind=self._engine)
125
+
126
+ def drop_tables(self) -> None:
127
+ """Drop all tables defined in models. Use with caution!"""
128
+ if not self._initialized:
129
+ raise RuntimeError("PostgreSQL not initialized. Call initialize() first.")
130
+ Base.metadata.drop_all(bind=self._engine)
131
+
132
+ @property
133
+ def is_initialized(self) -> bool:
134
+ """Check if the database is initialized."""
135
+ return self._initialized
136
+
137
+
138
+ # Global instance for convenience
139
+ postgres = PostgresManager()
@@ -0,0 +1,30 @@
1
+ """All data models for the 248 SDK."""
2
+
3
+ from sdk_248.models.enums import (
4
+ ActionRunStatus,
5
+ AppType,
6
+ CampaignStatus,
7
+ CategoriserStatus,
8
+ EmailOrchestrator,
9
+ NodeType,
10
+ )
11
+ from sdk_248.models.mongo import ActionRun, Campaign, Lead, Node
12
+ from sdk_248.models.postgres import Organization, OrganizationStatus
13
+
14
+ __all__ = [
15
+ # Enums
16
+ "ActionRunStatus",
17
+ "AppType",
18
+ "CampaignStatus",
19
+ "CategoriserStatus",
20
+ "EmailOrchestrator",
21
+ "NodeType",
22
+ # MongoDB models
23
+ "ActionRun",
24
+ "Campaign",
25
+ "Lead",
26
+ "Node",
27
+ # PostgreSQL models
28
+ "Organization",
29
+ "OrganizationStatus",
30
+ ]