cinchdb 0.1.0__py3-none-any.whl → 0.1.2__py3-none-any.whl

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.
@@ -14,6 +14,7 @@ from cinchdb.cli.utils import (
14
14
  set_active_branch,
15
15
  validate_required_arg,
16
16
  )
17
+ from cinchdb.utils.name_validator import validate_name, InvalidNameError
17
18
 
18
19
  app = typer.Typer(help="Branch management commands", invoke_without_command=True)
19
20
  console = Console()
@@ -80,6 +81,14 @@ def create(
80
81
  ):
81
82
  """Create a new branch."""
82
83
  name = validate_required_arg(name, "name", ctx)
84
+
85
+ # Validate branch name
86
+ try:
87
+ validate_name(name, "branch")
88
+ except InvalidNameError as e:
89
+ console.print(f"[red]❌ {e}[/red]")
90
+ raise typer.Exit(1)
91
+
83
92
  config, config_data = get_config_with_data()
84
93
  db_name = config_data.active_database
85
94
  source_branch = source or config_data.active_branch
@@ -12,6 +12,7 @@ from cinchdb.cli.utils import (
12
12
  set_active_branch,
13
13
  validate_required_arg,
14
14
  )
15
+ from cinchdb.utils.name_validator import validate_name, InvalidNameError
15
16
 
16
17
  app = typer.Typer(help="Database management commands", invoke_without_command=True)
17
18
  console = Console()
@@ -64,6 +65,14 @@ def create(
64
65
  ):
65
66
  """Create a new database."""
66
67
  name = validate_required_arg(name, "name", ctx)
68
+
69
+ # Validate database name
70
+ try:
71
+ validate_name(name, "database")
72
+ except InvalidNameError as e:
73
+ console.print(f"[red]❌ {e}[/red]")
74
+ raise typer.Exit(1)
75
+
67
76
  config, config_data = get_config_with_data()
68
77
 
69
78
  # Create database directory structure
@@ -10,6 +10,7 @@ from cinchdb.config import Config
10
10
  from cinchdb.core.path_utils import get_project_root
11
11
  from cinchdb.managers.tenant import TenantManager
12
12
  from cinchdb.cli.utils import get_config_with_data, validate_required_arg
13
+ from cinchdb.utils.name_validator import validate_name, InvalidNameError
13
14
 
14
15
  app = typer.Typer(help="Tenant management commands", invoke_without_command=True)
15
16
  console = Console()
@@ -70,6 +71,14 @@ def create(
70
71
  ):
71
72
  """Create a new tenant."""
72
73
  name = validate_required_arg(name, "name", ctx)
74
+
75
+ # Validate tenant name
76
+ try:
77
+ validate_name(name, "tenant")
78
+ except InvalidNameError as e:
79
+ console.print(f"[red]❌ {e}[/red]")
80
+ raise typer.Exit(1)
81
+
73
82
  config, config_data = get_config_with_data()
74
83
  db_name = config_data.active_database
75
84
  branch_name = config_data.active_branch
@@ -155,6 +164,14 @@ def rename(
155
164
  """Rename a tenant."""
156
165
  old_name = validate_required_arg(old_name, "old_name", ctx)
157
166
  new_name = validate_required_arg(new_name, "new_name", ctx)
167
+
168
+ # Validate new tenant name
169
+ try:
170
+ validate_name(new_name, "tenant")
171
+ except InvalidNameError as e:
172
+ console.print(f"[red]❌ {e}[/red]")
173
+ raise typer.Exit(1)
174
+
158
175
  config, config_data = get_config_with_data()
159
176
  db_name = config_data.active_database
160
177
  branch_name = config_data.active_branch
@@ -13,6 +13,7 @@ from cinchdb.core.path_utils import (
13
13
  get_branch_path,
14
14
  list_branches,
15
15
  )
16
+ from cinchdb.utils.name_validator import validate_name
16
17
 
17
18
 
18
19
  class BranchManager:
@@ -63,7 +64,11 @@ class BranchManager:
63
64
 
64
65
  Raises:
65
66
  ValueError: If source doesn't exist or new branch already exists
67
+ InvalidNameError: If new branch name is invalid
66
68
  """
69
+ # Validate new branch name
70
+ validate_name(new_branch_name, "branch")
71
+
67
72
  # Validate source branch exists
68
73
  if source_branch not in list_branches(self.project_root, self.database):
69
74
  raise ValueError(f"Source branch '{source_branch}' does not exist")
@@ -12,6 +12,7 @@ from cinchdb.core.path_utils import (
12
12
  )
13
13
  from cinchdb.core.connection import DatabaseConnection
14
14
  from cinchdb.core.maintenance import check_maintenance_mode
15
+ from cinchdb.utils.name_validator import validate_name
15
16
 
16
17
 
17
18
  class TenantManager:
@@ -64,8 +65,12 @@ class TenantManager:
64
65
 
65
66
  Raises:
66
67
  ValueError: If tenant already exists
68
+ InvalidNameError: If tenant name is invalid
67
69
  MaintenanceError: If branch is in maintenance mode
68
70
  """
71
+ # Validate tenant name
72
+ validate_name(tenant_name, "tenant")
73
+
69
74
  # Check maintenance mode
70
75
  check_maintenance_mode(self.project_root, self.database, self.branch)
71
76
 
@@ -158,8 +163,12 @@ class TenantManager:
158
163
 
159
164
  Raises:
160
165
  ValueError: If source doesn't exist or target already exists
166
+ InvalidNameError: If target tenant name is invalid
161
167
  MaintenanceError: If branch is in maintenance mode
162
168
  """
169
+ # Validate target tenant name
170
+ validate_name(target_tenant, "tenant")
171
+
163
172
  # Check maintenance mode
164
173
  check_maintenance_mode(self.project_root, self.database, self.branch)
165
174
 
@@ -200,7 +209,11 @@ class TenantManager:
200
209
 
201
210
  Raises:
202
211
  ValueError: If old doesn't exist, new already exists, or trying to rename main
212
+ InvalidNameError: If new tenant name is invalid
203
213
  """
214
+ # Validate new tenant name
215
+ validate_name(new_name, "tenant")
216
+
204
217
  # Can't rename main tenant
205
218
  if old_name == "main":
206
219
  raise ValueError("Cannot rename the main tenant")
cinchdb/models/branch.py CHANGED
@@ -1,8 +1,9 @@
1
1
  """Branch model for CinchDB."""
2
2
 
3
3
  from typing import List, Optional, Dict, Any
4
- from pydantic import Field
4
+ from pydantic import Field, field_validator
5
5
  from .base import CinchDBBaseModel
6
+ from ..utils.name_validator import validate_name
6
7
 
7
8
 
8
9
  class Branch(CinchDBBaseModel):
@@ -21,6 +22,13 @@ class Branch(CinchDBBaseModel):
21
22
  )
22
23
  is_main: bool = Field(default=False, description="Whether this is the main branch")
23
24
 
25
+ @field_validator('name')
26
+ @classmethod
27
+ def validate_name_field(cls, v: str) -> str:
28
+ """Validate branch name meets naming requirements."""
29
+ validate_name(v, "branch")
30
+ return v
31
+
24
32
  def can_delete(self) -> bool:
25
33
  """Check if this branch can be deleted."""
26
34
  return self.name != "main" and not self.is_main
@@ -1,8 +1,9 @@
1
1
  """Database model for CinchDB."""
2
2
 
3
3
  from typing import List, Optional
4
- from pydantic import Field
4
+ from pydantic import Field, field_validator
5
5
  from .base import CinchDBBaseModel
6
+ from ..utils.name_validator import validate_name
6
7
 
7
8
 
8
9
  class Database(CinchDBBaseModel):
@@ -15,6 +16,13 @@ class Database(CinchDBBaseModel):
15
16
  active_branch: str = Field(default="main", description="Currently active branch")
16
17
  description: Optional[str] = Field(default=None, description="Database description")
17
18
 
19
+ @field_validator('name')
20
+ @classmethod
21
+ def validate_name_field(cls, v: str) -> str:
22
+ """Validate database name meets naming requirements."""
23
+ validate_name(v, "database")
24
+ return v
25
+
18
26
  def can_delete(self) -> bool:
19
27
  """Check if this database can be deleted."""
20
28
  return self.name != "main"
cinchdb/models/tenant.py CHANGED
@@ -1,8 +1,9 @@
1
1
  """Tenant model for CinchDB."""
2
2
 
3
3
  from typing import Optional
4
- from pydantic import Field
4
+ from pydantic import Field, field_validator
5
5
  from .base import CinchDBBaseModel
6
+ from ..utils.name_validator import validate_name
6
7
 
7
8
 
8
9
  class Tenant(CinchDBBaseModel):
@@ -14,6 +15,13 @@ class Tenant(CinchDBBaseModel):
14
15
  description: Optional[str] = Field(default=None, description="Tenant description")
15
16
  is_main: bool = Field(default=False, description="Whether this is the main tenant")
16
17
 
18
+ @field_validator('name')
19
+ @classmethod
20
+ def validate_name_field(cls, v: str) -> str:
21
+ """Validate tenant name meets naming requirements."""
22
+ validate_name(v, "tenant")
23
+ return v
24
+
17
25
  def can_delete(self) -> bool:
18
26
  """Check if this tenant can be deleted."""
19
27
  return self.name != "main" and not self.is_main
cinchdb/utils/__init__.py CHANGED
@@ -6,10 +6,20 @@ from cinchdb.utils.sql_validator import (
6
6
  SQLValidationError,
7
7
  SQLOperation
8
8
  )
9
+ from cinchdb.utils.name_validator import (
10
+ validate_name,
11
+ clean_name,
12
+ is_valid_name,
13
+ InvalidNameError
14
+ )
9
15
 
10
16
  __all__ = [
11
17
  "validate_sql_query",
12
18
  "validate_query_safe",
13
19
  "SQLValidationError",
14
- "SQLOperation"
20
+ "SQLOperation",
21
+ "validate_name",
22
+ "clean_name",
23
+ "is_valid_name",
24
+ "InvalidNameError"
15
25
  ]
@@ -0,0 +1,129 @@
1
+ """Name validation utilities for CinchDB entities.
2
+
3
+ Ensures branch, database, and tenant names are safe for filesystem operations
4
+ and follow consistent naming conventions.
5
+ """
6
+
7
+ import re
8
+ from typing import Optional
9
+
10
+
11
+ # Regex pattern for valid names: lowercase letters, numbers, dash, underscore, period
12
+ VALID_NAME_PATTERN = re.compile(r'^[a-z0-9][a-z0-9\-._]*[a-z0-9]$|^[a-z0-9]$')
13
+
14
+ # Reserved names that cannot be used
15
+ RESERVED_NAMES = {'con', 'prn', 'aux', 'nul', 'com1', 'com2', 'com3', 'com4',
16
+ 'com5', 'com6', 'com7', 'com8', 'com9', 'lpt1', 'lpt2',
17
+ 'lpt3', 'lpt4', 'lpt5', 'lpt6', 'lpt7', 'lpt8', 'lpt9'}
18
+
19
+
20
+ class InvalidNameError(ValueError):
21
+ """Raised when a name doesn't meet validation requirements."""
22
+ pass
23
+
24
+
25
+ def validate_name(name: str, entity_type: str = "entity") -> None:
26
+ """Validate that a name meets CinchDB naming requirements.
27
+
28
+ Valid names must:
29
+ - Contain only lowercase letters (a-z), numbers (0-9), dash (-), underscore (_), and period (.)
30
+ - Start and end with alphanumeric characters
31
+ - Be at least 1 character long
32
+ - Not exceed 255 characters (filesystem limit)
33
+ - Not be a reserved name
34
+
35
+ Args:
36
+ name: The name to validate
37
+ entity_type: Type of entity (branch, database, tenant) for error messages
38
+
39
+ Raises:
40
+ InvalidNameError: If the name is invalid
41
+ """
42
+ if not name:
43
+ raise InvalidNameError(f"{entity_type.capitalize()} name cannot be empty")
44
+
45
+ if len(name) > 255:
46
+ raise InvalidNameError(
47
+ f"{entity_type.capitalize()} name cannot exceed 255 characters"
48
+ )
49
+
50
+ # Check for lowercase requirement
51
+ if name != name.lower():
52
+ raise InvalidNameError(
53
+ f"{entity_type.capitalize()} name must be lowercase. "
54
+ f"Use '{name.lower()}' instead of '{name}'"
55
+ )
56
+
57
+ # Check pattern
58
+ if not VALID_NAME_PATTERN.match(name):
59
+ raise InvalidNameError(
60
+ f"Invalid {entity_type} name '{name}'. "
61
+ f"Names must contain only lowercase letters (a-z), numbers (0-9), "
62
+ f"dash (-), underscore (_), and period (.). "
63
+ f"Names must start and end with alphanumeric characters."
64
+ )
65
+
66
+ # Check for consecutive special characters
67
+ if '..' in name or '--' in name or '__' in name or '.-' in name or '-.' in name:
68
+ raise InvalidNameError(
69
+ f"Invalid {entity_type} name '{name}'. "
70
+ f"Names cannot contain consecutive special characters."
71
+ )
72
+
73
+ # Check reserved names
74
+ if name.lower() in RESERVED_NAMES:
75
+ raise InvalidNameError(
76
+ f"'{name}' is a reserved name and cannot be used as a {entity_type} name"
77
+ )
78
+
79
+
80
+ def clean_name(name: str) -> str:
81
+ """Clean a name to make it valid if possible.
82
+
83
+ This performs basic cleaning:
84
+ - Convert to lowercase
85
+ - Replace spaces with dashes
86
+ - Remove invalid characters
87
+
88
+ Args:
89
+ name: The name to clean
90
+
91
+ Returns:
92
+ Cleaned name
93
+
94
+ Note:
95
+ This is a best-effort cleaning. The result should still be validated
96
+ with validate_name() before use.
97
+ """
98
+ # Convert to lowercase
99
+ cleaned = name.lower()
100
+
101
+ # Replace spaces with dashes
102
+ cleaned = cleaned.replace(' ', '-')
103
+
104
+ # Remove invalid characters
105
+ cleaned = re.sub(r'[^a-z0-9\-._]', '', cleaned)
106
+
107
+ # Remove consecutive special characters
108
+ cleaned = re.sub(r'[-._]{2,}', '-', cleaned)
109
+
110
+ # Remove leading/trailing special characters
111
+ cleaned = cleaned.strip('-._')
112
+
113
+ return cleaned
114
+
115
+
116
+ def is_valid_name(name: str) -> bool:
117
+ """Check if a name is valid without raising an exception.
118
+
119
+ Args:
120
+ name: The name to check
121
+
122
+ Returns:
123
+ True if valid, False otherwise
124
+ """
125
+ try:
126
+ validate_name(name)
127
+ return True
128
+ except InvalidNameError:
129
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cinchdb
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: A Git-like SQLite database management system with branching and multi-tenancy
5
5
  Project-URL: Homepage, https://github.com/russellromney/cinchdb
6
6
  Project-URL: Documentation, https://russellromney.github.io/cinchdb
@@ -18,14 +18,11 @@ Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
20
  Requires-Python: >=3.10
21
- Requires-Dist: fastapi>=0.115.0
22
21
  Requires-Dist: pydantic>=2.0.0
23
- Requires-Dist: python-multipart>=0.0.12
24
22
  Requires-Dist: requests>=2.28.0
25
23
  Requires-Dist: rich>=13.0.0
26
24
  Requires-Dist: toml>=0.10.0
27
25
  Requires-Dist: typer>=0.9.0
28
- Requires-Dist: uvicorn>=0.32.0
29
26
  Description-Content-Type: text/markdown
30
27
 
31
28
  # CinchDB
@@ -34,11 +31,11 @@ Description-Content-Type: text/markdown
34
31
 
35
32
  NOTE: CinchDB is in early alpha. This is project to test out an idea. Do not use this in production.
36
33
 
37
- CinchDB is for projects that need to isolate data per-tenant [or even per-user](https://turso.tech/blog/give-each-of-your-users-their-own-sqlite-database-b74445f4) and/or want to test out changes to structure safely in branchces. Plus, queries can be super, super fast because data is separated per tenant so it's <data_size>/<n_tenants> instead of <data_size>
34
+ CinchDB is for projects that need fast queries, data isolated data per-tenant [or even per-user](https://turso.tech/blog/give-each-of-your-users-their-own-sqlite-database-b74445f4), and a branchable database.
38
35
 
39
36
  On a meta level, I made this because I wanted a database structure that I felt comfortable letting AI agents take full control over, safely, and I didn't want to run my own Postgres instance somewhere or pay for it on e.g. Neon - I don't need hyperscaling, I just need super fast queries.
40
37
 
41
- Because it's so lightweight and its only dependencies are FastAPI, pydantic, requests, and Typer, it is super cheap to run on a small VM like from [Fly.io](https://fly.io) and I don't need to SSH into it to connect - I can just store an API key in my local projects.
38
+ Because it's so lightweight and its only dependencies are pydantic, requests, and Typer, it makes for a perfect local development database that can be controlled programmatically.
42
39
 
43
40
 
44
41
  ```bash
@@ -61,9 +58,9 @@ cinch branch merge-into-main feature
61
58
  cinch tenant create customer_a
62
59
  cinch query "SELECT * FROM users" --tenant customer_a
63
60
 
64
- # API server
65
- uv pip install cinchdb[server]
66
- cinch-server serve
61
+ # Connect to remote CinchDB instance
62
+ cinch remote add production https://your-cinchdb-server.com your-api-key
63
+ cinch remote use production
67
64
 
68
65
  # Autogenerate Python SDK from database
69
66
  cinch codegen generate python cinchdb_models/
@@ -77,9 +74,9 @@ CinchDB combines SQLite with Git-like workflows for database schema management:
77
74
  - **Multi-tenant isolation** - shared schema, isolated data per tenant
78
75
  - **Automatic change tracking** - all schema changes tracked and mergeable
79
76
  - **Safe structure changes** - change merges happen atomically with zero rollback risk (seriously)
80
- - **Remote deployment** - FastAPI server with UUID authentication
77
+ - **Remote connectivity** - Connect to hosted CinchDB instances
81
78
  - **Type-safe SDK** - Python and TypeScript SDKs with full type safety
82
- - **API server for remote hosting** - Useful for running many web projects
79
+ - **Remote-capable** - CLI and SDK can connect to remote instances
83
80
  - **SDK generation from database schema** - Generate a typesafe SDK from your database models for CRUD operations
84
81
 
85
82
  ## Installation
@@ -136,24 +133,25 @@ post_id = db.insert("posts", {"title": "Hello World", "content": "First post"})
136
133
  db.update("posts", post_id, {"content": "Updated content"})
137
134
  ```
138
135
 
139
- ### Remote API
136
+ ### Remote Connection
140
137
 
141
138
  ```python
142
- # Connect to remote API
143
- db = cinchdb.connect_api("https://api.example.com", "your-api-key", "myapp")
139
+ # Connect to remote instance
140
+ db = cinchdb.connect("myapp", url="https://your-cinchdb-server.com", api_key="your-api-key")
144
141
 
145
142
  # Same interface as local
146
143
  results = db.query("SELECT * FROM users")
147
144
  user_id = db.insert("users", {"username": "alice", "email": "alice@example.com"})
148
145
  ```
149
146
 
150
- ## API Server
147
+ ## Remote Access
151
148
 
152
- Start the server:
149
+ Connect to a remote CinchDB instance:
153
150
 
154
151
  ```bash
155
- cinch-server serve --create-key
156
- # Creates API key (works after shutdown as well) and starts server on http://localhost:8000
152
+ cinch remote add production https://your-cinchdb-server.com your-api-key
153
+ cinch remote use production
154
+ # Now all commands will use the remote instance
157
155
  ```
158
156
 
159
157
  Interactive docs at `/docs`, health check at `/health`.
@@ -162,7 +160,7 @@ Interactive docs at `/docs`, health check at `/health`.
162
160
 
163
161
  - **Python SDK**: Core functionality (local + remote)
164
162
  - **CLI**: Full-featured command-line interface
165
- - **FastAPI Server**: REST API with authentication
163
+ - **Remote Access**: Connect to hosted CinchDB instances
166
164
  - **TypeScript SDK**: Browser and Node.js client
167
165
 
168
166
  ## Development
@@ -1,34 +1,18 @@
1
1
  cinchdb/__init__.py,sha256=NZdSzfhRguSBTjJ2dcESOQYy53OZEuBndlB7U08GMY0,179
2
2
  cinchdb/__main__.py,sha256=OpkDqn9zkTZhhYgvv_grswWLAHKbmxs4M-8C6Z5HfWY,85
3
3
  cinchdb/config.py,sha256=Exzf0hCJgcg0PRRQz8EG7XFipx6fIVKO7IsQhpc0Q4o,6187
4
- cinchdb/api/__init__.py,sha256=5AHDlOXOxxzyI8pW7puntIILp8E7HOy4D62odLN518w,79
5
- cinchdb/api/app.py,sha256=iL9tYWYpJAAOzH9UHNbpl82Ibwz_zBCqxDXqARmxjbc,2172
6
- cinchdb/api/auth.py,sha256=uxRWWRjE6sQWNPH6BBsdHT_PlWN_iYr_hh76tVG9fTY,8167
7
- cinchdb/api/main.py,sha256=FpqhO7zTgh-r6y14mL0Cp-fGQ0TMmxPKCF7cNjDiCcw,4509
8
- cinchdb/api/routers/__init__.py,sha256=o4xLUjKRKYnBU-RQiDXQotKml0lZEwIudU5S5bW4gt8,323
9
- cinchdb/api/routers/auth.py,sha256=6Si_iQtDwj487Hv87AoV4vMWAJFnvd5JsFXghYqA7ao,3842
10
- cinchdb/api/routers/branches.py,sha256=gEYBDqvwSzt5uSSVDo_mo2ysLfUqaavyDClpzRfYTyA,11537
11
- cinchdb/api/routers/codegen.py,sha256=As9zfBmT7SMx1lrQfRg8TGofcRSOo_r77fCLmxuYkI4,5069
12
- cinchdb/api/routers/columns.py,sha256=bWMIInp0Ma9KPp7PHFSr25ROWNKjOkwl9KNc3bQeqMo,8313
13
- cinchdb/api/routers/data.py,sha256=rYnh6TwgLArA85AalOydg4txoXD0UWEItAvISuRVTao,14923
14
- cinchdb/api/routers/databases.py,sha256=I6yolh9IoqOoMrhWFFyCDFuKtLGgQGxL2dwEj2FEYeQ,5024
15
- cinchdb/api/routers/projects.py,sha256=70nwkXjGiK_pfTr6hv50viOjvQgv5yfC50mEgTByClE,3847
16
- cinchdb/api/routers/query.py,sha256=UEtdKLIeo5OjOHfJl3IU3q2o69NOAX0pCyOwb7ivquQ,5120
17
- cinchdb/api/routers/tables.py,sha256=Dg0ANMEVHXZyIO-mJBQCnJKfdRORKFqKaunLfJ_cTlo,10403
18
- cinchdb/api/routers/tenants.py,sha256=1xukbM5avvkr1CMuq1pr78CNyE_9xk2Yg35mZFDvl-c,5692
19
- cinchdb/api/routers/views.py,sha256=pzovkLttjEAg0ecvPwaN5qFgBqNhD0_g0sqq9UNYAmc,6051
20
4
  cinchdb/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
5
  cinchdb/cli/main.py,sha256=_vBSigtAcYgGBB4qRt2p3ZH8QZ4Osk5rLRe5cOD5ryU,4335
22
6
  cinchdb/cli/utils.py,sha256=Alh3plAiVOGSk_ETqTmh2rYHHFULelizsQOR4e-_KJw,5661
23
7
  cinchdb/cli/commands/__init__.py,sha256=gQ6tnU0Rvm0-ESWFUBU-KDl5dpNOpUTG509hXOQQjwY,27
24
- cinchdb/cli/commands/branch.py,sha256=8sjumH0XPi8wYNltDH4HXlzRpcr-GHNAaw8zzmIYYus,17622
8
+ cinchdb/cli/commands/branch.py,sha256=pNltZ2yyUuVGG1D_x5Rmr3lcyr0ibC98xEQevTtt0Q0,17890
25
9
  cinchdb/cli/commands/codegen.py,sha256=WsRWmXNTDuaLPyECW5psXM9zOQnKHpUiv8BJnBAjMII,6189
26
10
  cinchdb/cli/commands/column.py,sha256=CQJZ-mkv_qaBnZDrNhKaunUdxVyz5zmbsZakUnz5-dg,11634
27
- cinchdb/cli/commands/database.py,sha256=qn1i0o_sRVID-yjIPYib1l9_7Qun0zzKvsqdLH1-Mcw,6597
11
+ cinchdb/cli/commands/database.py,sha256=TxJ3xZfAb7zyq2NrnL1PPYQWENsjMYq_GjuS3J0yuyw,6865
28
12
  cinchdb/cli/commands/query.py,sha256=yce0rvp3WQCzFA08cP1DoP2Yir4NSYxX1XxXPmmo3lM,5120
29
13
  cinchdb/cli/commands/remote.py,sha256=LecazBIlEAx8J85vONDrQyy3OEYkmYGCeTGS-c0PD1Y,4500
30
14
  cinchdb/cli/commands/table.py,sha256=ApDcn-iJ-Cjsf4ubQh8UVNBxJmhLQ_O2FxQeBRk6xMI,10511
31
- cinchdb/cli/commands/tenant.py,sha256=p6uReHyYh2Hl6ayWMHCTY_wUARcUHSl0n4Y20Nsi3gA,5752
15
+ cinchdb/cli/commands/tenant.py,sha256=G9jxj8rrSfXJqYYi6Lls21wDShYr1aDgj_vffbjG-j4,6223
32
16
  cinchdb/cli/commands/view.py,sha256=ZmS1IW7idzzHAXmgVyY3C4IQRo7toHb6fHNFY_tQJjI,6385
33
17
  cinchdb/cli/handlers/__init__.py,sha256=f2f-Cc96rSBLbVsiIbf-b4pZCKZoHfmhNEvnZ0OurRs,131
34
18
  cinchdb/cli/handlers/codegen_handler.py,sha256=i5we_AbiUW3zfO6pIKWxvtO8OvOqz3H__4xPmTLEuQM,6524
@@ -38,7 +22,7 @@ cinchdb/core/database.py,sha256=QDz3imoCvrWAA4zLuYaM6lUNRKDQWrYAQPfIJyZkgyw,1798
38
22
  cinchdb/core/maintenance.py,sha256=PAgrSL7Cj9p3rKHV0h_L7gupN6nLD0-5eQpJZNiqyEs,2097
39
23
  cinchdb/core/path_utils.py,sha256=J2UEu1X_NFOqDamcsrPrC7ZitGTg9Y-HFjmx4sHf5j8,3806
40
24
  cinchdb/managers/__init__.py,sha256=ic61ZUdsg-muq0ETYO6fuZRQWF4j7l920PthTkt2QrE,808
41
- cinchdb/managers/branch.py,sha256=4rsusRQlLNfM55IS2dzosnVju7rbeJdaR9jcMPM9Bl8,5165
25
+ cinchdb/managers/branch.py,sha256=uj_ReZF9lmXgwn0DhAh6xCrE2LieG1CVHHEeOzhnr1E,5373
42
26
  cinchdb/managers/change_applier.py,sha256=cHPhPgbJ9jeyrb6lkfRyumS8IHat0HiWfwZh-n7ButA,14310
43
27
  cinchdb/managers/change_comparator.py,sha256=08pwybpSt36cFwhZRSIkHynvFMUaLKEVwa8Ajn_R9yQ,6862
44
28
  cinchdb/managers/change_tracker.py,sha256=U93BPnuGv8xSaO5qr_y5Q8ppKrVXygozdp5zUvLUqwg,5054
@@ -48,21 +32,22 @@ cinchdb/managers/data.py,sha256=4wn9fxFPhrDvtudc1pdQmr0vf0w9H92VrzAIVyTXFCY,1540
48
32
  cinchdb/managers/merge_manager.py,sha256=R8S2hLkLJg4hLDpeJTzjVkduZgqPOjXtYgOSJhTXXrE,15690
49
33
  cinchdb/managers/query.py,sha256=c91J5FAR-Ze5Zy5HNEVIPvc8yuxe-xIv6XHH-lmdB2k,7307
50
34
  cinchdb/managers/table.py,sha256=9Z_RJxZ9fMm_gYbmHXGG0-xZ0cNia1y5tusnydW66_U,13155
51
- cinchdb/managers/tenant.py,sha256=sqLdfIqNkMBzM1b1iOYhVfgJqxhfzzjn5uoXOcP2bJg,8251
35
+ cinchdb/managers/tenant.py,sha256=ZMx9H8XHua512fFRK2xBxa3xjqJJ551xp399mGm16s4,8750
52
36
  cinchdb/managers/view.py,sha256=v9gYtRufZyxywPKLGvIjvlUXcxYh9CLRArefu9QX6zk,7809
53
37
  cinchdb/models/__init__.py,sha256=382OuS0BaKPA71GjqNW5lfVhtUYqmcMlLRin7HPi6XI,602
54
38
  cinchdb/models/base.py,sha256=7j4rlFTP5K9ZuF8vxwC7lMFEaL7O90NJ47Ig5i7ubcw,1320
55
- cinchdb/models/branch.py,sha256=nam76NJbLHHLbcQF2SaVADH7s2jrlFRGGRt_PDNhkwc,904
39
+ cinchdb/models/branch.py,sha256=vKw7rtwxKSpgXAHBKwf5Fkd4LjtiZcfDwtAqeq1LoBE,1180
56
40
  cinchdb/models/change.py,sha256=YpBWdI6yMT3uucd8duET9s75xr5JUWJqurkkyTlXPlk,1449
57
- cinchdb/models/database.py,sha256=kIlvIoGlN3Hhk5UDHo2gKT9g4GCGfKHDL0cpVtoimc8,691
41
+ cinchdb/models/database.py,sha256=Z_XZwBfjcZe7x6IsFD5fgD3a-k5ESzRoVukMlPpTIek,971
58
42
  cinchdb/models/project.py,sha256=6GMXUZUsEIebqQJgRXIthWzpWKuNNmJ3drgI1vFDrMo,644
59
43
  cinchdb/models/table.py,sha256=s6BGoHDuA-yzqQL9papRTVT2WcHjuY-SnoanGFDlFIE,2793
60
- cinchdb/models/tenant.py,sha256=Y7_J_dFwwnXPM0EgF3J_g2M3guycfjqpdGEl03LG7p0,691
44
+ cinchdb/models/tenant.py,sha256=Jut8qoHX79OG3zDNXAdDqzGmlGiV8trGe3t5kXbFt1E,967
61
45
  cinchdb/models/view.py,sha256=q6j-jYzFJuhRJO87rKt6Uv8hOizHQx8xwoPKoH6XnNY,530
62
- cinchdb/utils/__init__.py,sha256=9VXzZBggOfzdj8DTdGBqqOxJzBAm-WS1M_zeToF1fgs,282
46
+ cinchdb/utils/__init__.py,sha256=1mBU1H2C9urYA8Z_v5BTdAfDe0mQ6GMAK0AM3zRPv5k,487
47
+ cinchdb/utils/name_validator.py,sha256=sOeufsnIH2b7I9C3xUkQdmNv8NgnReVb6BVJkczwbeE,3955
63
48
  cinchdb/utils/sql_validator.py,sha256=7STxsVO7bD4gZ8mfimQSt4_Yfckw62plUS_X_xJ48Vo,5427
64
- cinchdb-0.1.0.dist-info/METADATA,sha256=s9s1w2lUNuc2fQ-SqdHEcD2j6rzDjUhrxw8ZednTI6A,5998
65
- cinchdb-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
66
- cinchdb-0.1.0.dist-info/entry_points.txt,sha256=Zzlwp632_jT5OZBkrewvH3-RWUJ9E5vD_BNme6J-A1I,83
67
- cinchdb-0.1.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
68
- cinchdb-0.1.0.dist-info/RECORD,,
49
+ cinchdb-0.1.2.dist-info/METADATA,sha256=JpVRmU-ESHcuOVkon7bhSDSxy08wnEunEkKivHSVG24,5802
50
+ cinchdb-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
51
+ cinchdb-0.1.2.dist-info/entry_points.txt,sha256=VBOIzvnGbkKudMCCmNORS3885QSyjZUVKJQ-Syqa62w,47
52
+ cinchdb-0.1.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
53
+ cinchdb-0.1.2.dist-info/RECORD,,
@@ -1,3 +1,2 @@
1
1
  [console_scripts]
2
2
  cinch = cinchdb.cli.main:app
3
- cinch-server = cinchdb.api.main:cli
cinchdb/api/__init__.py DELETED
@@ -1,5 +0,0 @@
1
- """CinchDB API package."""
2
-
3
- from cinchdb.api.app import app
4
-
5
- __all__ = ["app"]
cinchdb/api/app.py DELETED
@@ -1,76 +0,0 @@
1
- """FastAPI application for CinchDB."""
2
-
3
- from fastapi import FastAPI
4
- from fastapi.middleware.cors import CORSMiddleware
5
- from contextlib import asynccontextmanager
6
-
7
- from cinchdb import __version__
8
- from cinchdb.api.routers import (
9
- auth,
10
- projects,
11
- databases,
12
- branches,
13
- tenants,
14
- tables,
15
- columns,
16
- views,
17
- query,
18
- data,
19
- codegen,
20
- )
21
-
22
-
23
- @asynccontextmanager
24
- async def lifespan(app: FastAPI):
25
- """Application lifespan events."""
26
- # Startup
27
- print(f"Starting CinchDB API v{__version__}")
28
- yield
29
- # Shutdown
30
- print("Shutting down CinchDB API")
31
-
32
-
33
- # Create FastAPI app
34
- app = FastAPI(
35
- title="CinchDB API",
36
- description="Git-like SQLite database management system",
37
- version=__version__,
38
- lifespan=lifespan,
39
- docs_url="/docs",
40
- redoc_url="/redoc",
41
- openapi_url="/openapi.json",
42
- )
43
-
44
- # Configure CORS
45
- app.add_middleware(
46
- CORSMiddleware,
47
- allow_origins=["*"], # Configure appropriately for production
48
- allow_credentials=True,
49
- allow_methods=["*"],
50
- allow_headers=["*"],
51
- )
52
-
53
- # Include routers
54
- app.include_router(auth.router, prefix="/api/v1/auth", tags=["auth"])
55
- app.include_router(projects.router, prefix="/api/v1/projects", tags=["projects"])
56
- app.include_router(databases.router, prefix="/api/v1/databases", tags=["databases"])
57
- app.include_router(branches.router, prefix="/api/v1/branches", tags=["branches"])
58
- app.include_router(tenants.router, prefix="/api/v1/tenants", tags=["tenants"])
59
- app.include_router(tables.router, prefix="/api/v1/tables", tags=["tables"])
60
- app.include_router(columns.router, prefix="/api/v1/columns", tags=["columns"])
61
- app.include_router(views.router, prefix="/api/v1/views", tags=["views"])
62
- app.include_router(query.router, prefix="/api/v1/query", tags=["query"])
63
- app.include_router(data.router, prefix="/api/v1/tables", tags=["data"])
64
- app.include_router(codegen.router, prefix="/api/v1/codegen", tags=["codegen"])
65
-
66
-
67
- @app.get("/")
68
- async def root():
69
- """Root endpoint."""
70
- return {"name": "CinchDB API", "version": __version__, "status": "running"}
71
-
72
-
73
- @app.get("/health")
74
- async def health_check():
75
- """Health check endpoint."""
76
- return {"status": "healthy"}