repr-cli 0.2.17__py3-none-any.whl → 0.2.18__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.
- repr/__init__.py +1 -1
- repr/cli.py +160 -37
- repr/dashboard/dist/assets/index-B-aCjaCw.js +384 -0
- repr/dashboard/dist/assets/index-C7Gzxc4f.js +384 -0
- repr/dashboard/dist/assets/index-CQdMXo6g.js +391 -0
- repr/dashboard/dist/assets/index-Cs8ofFGd.js +384 -0
- repr/dashboard/dist/assets/index-DwN0SeMc.css +1 -0
- repr/dashboard/dist/assets/index-YFch_e0S.js +384 -0
- repr/dashboard/dist/index.html +2 -2
- repr/dashboard/server.py +191 -0
- {repr_cli-0.2.17.dist-info → repr_cli-0.2.18.dist-info}/METADATA +1 -1
- {repr_cli-0.2.17.dist-info → repr_cli-0.2.18.dist-info}/RECORD +16 -10
- {repr_cli-0.2.17.dist-info → repr_cli-0.2.18.dist-info}/WHEEL +0 -0
- {repr_cli-0.2.17.dist-info → repr_cli-0.2.18.dist-info}/entry_points.txt +0 -0
- {repr_cli-0.2.17.dist-info → repr_cli-0.2.18.dist-info}/licenses/LICENSE +0 -0
- {repr_cli-0.2.17.dist-info → repr_cli-0.2.18.dist-info}/top_level.txt +0 -0
repr/__init__.py
CHANGED
repr/cli.py
CHANGED
|
@@ -1981,6 +1981,165 @@ def push(
|
|
|
1981
1981
|
print_success(f"Pushed {pushed}/{len(stories_payload)} stories")
|
|
1982
1982
|
|
|
1983
1983
|
|
|
1984
|
+
@app.command()
|
|
1985
|
+
def publish(
|
|
1986
|
+
story_id: Optional[str] = typer.Argument(None, help="Story ID to publish (omit for batch publish)"),
|
|
1987
|
+
all_stories: bool = typer.Option(False, "--all", "-a", help="Republish all stories, including already-pushed"),
|
|
1988
|
+
repo: Optional[str] = typer.Option(None, "--repo", "-r", help="Publish stories from specific repository"),
|
|
1989
|
+
visibility: Optional[str] = typer.Option(None, "--visibility", "-v", help="Override visibility: public, private, connections"),
|
|
1990
|
+
dry_run: bool = typer.Option(False, "--dry-run", help="Preview what would be published"),
|
|
1991
|
+
):
|
|
1992
|
+
"""
|
|
1993
|
+
Publish stories to repr.dev.
|
|
1994
|
+
|
|
1995
|
+
Publish = Upload to cloud with current visibility (or override).
|
|
1996
|
+
|
|
1997
|
+
Supports three scopes:
|
|
1998
|
+
- Global: Publish all unpushed stories (or all with --all)
|
|
1999
|
+
- Repo: Publish stories from a specific repository (--repo)
|
|
2000
|
+
- Story: Publish a single story by ID
|
|
2001
|
+
|
|
2002
|
+
Examples:
|
|
2003
|
+
repr publish # Unpushed stories only
|
|
2004
|
+
repr publish --all # All stories (re-publish)
|
|
2005
|
+
repr publish --repo myproject # Stories from specific repo
|
|
2006
|
+
repr publish 01HXYZ123 # Single story by ID
|
|
2007
|
+
repr publish --visibility public # Publish as public
|
|
2008
|
+
repr publish --repo myproject --dry-run # Preview
|
|
2009
|
+
"""
|
|
2010
|
+
from .privacy import check_cloud_permission, log_cloud_operation
|
|
2011
|
+
from .api import push_stories_batch, APIError, AuthError
|
|
2012
|
+
from .db import get_db
|
|
2013
|
+
|
|
2014
|
+
# Check authentication
|
|
2015
|
+
if not get_access_token():
|
|
2016
|
+
print_error("Not authenticated")
|
|
2017
|
+
print_info("Run 'repr login' to authenticate")
|
|
2018
|
+
raise typer.Exit(1)
|
|
2019
|
+
|
|
2020
|
+
allowed, reason = check_cloud_permission("push")
|
|
2021
|
+
if not allowed:
|
|
2022
|
+
print_error("Publishing blocked")
|
|
2023
|
+
print_info(reason)
|
|
2024
|
+
raise typer.Exit(1)
|
|
2025
|
+
|
|
2026
|
+
# Validate visibility if provided
|
|
2027
|
+
valid_visibilities = {"public", "private", "connections"}
|
|
2028
|
+
if visibility and visibility not in valid_visibilities:
|
|
2029
|
+
print_error(f"Invalid visibility: {visibility}")
|
|
2030
|
+
print_info(f"Valid options: {', '.join(valid_visibilities)}")
|
|
2031
|
+
raise typer.Exit(1)
|
|
2032
|
+
|
|
2033
|
+
db = get_db()
|
|
2034
|
+
|
|
2035
|
+
# Determine which stories to publish based on scope
|
|
2036
|
+
if story_id:
|
|
2037
|
+
# Single story mode
|
|
2038
|
+
story = db.get_story(story_id)
|
|
2039
|
+
if not story:
|
|
2040
|
+
print_error(f"Story not found: {story_id}")
|
|
2041
|
+
raise typer.Exit(1)
|
|
2042
|
+
all_stories_list = [story]
|
|
2043
|
+
scope_desc = f"story {story_id[:8]}..."
|
|
2044
|
+
elif repo:
|
|
2045
|
+
# Repo mode - get stories from specific repo
|
|
2046
|
+
projects = db.list_projects()
|
|
2047
|
+
project_ids = [p["id"] for p in projects if p["name"] == repo]
|
|
2048
|
+
if not project_ids:
|
|
2049
|
+
print_error(f"Repository not found: {repo}")
|
|
2050
|
+
print_info("Use 'repr repos list' to see tracked repositories")
|
|
2051
|
+
raise typer.Exit(1)
|
|
2052
|
+
all_stories_list = [s for s in db.list_stories(limit=10000) if s.project_id in project_ids]
|
|
2053
|
+
scope_desc = f"repo '{repo}'"
|
|
2054
|
+
else:
|
|
2055
|
+
# Global mode
|
|
2056
|
+
all_stories_list = db.list_stories(limit=10000)
|
|
2057
|
+
scope_desc = "all repositories"
|
|
2058
|
+
|
|
2059
|
+
if not all_stories_list:
|
|
2060
|
+
print_info(f"No stories found for {scope_desc}")
|
|
2061
|
+
raise typer.Exit()
|
|
2062
|
+
|
|
2063
|
+
# Filter to unpushed unless --all is specified
|
|
2064
|
+
# Note: For now we don't track pushed_at in the schema, so --all just means republish everything
|
|
2065
|
+
# In future, we could filter by pushed_at column
|
|
2066
|
+
stories_to_publish = all_stories_list
|
|
2067
|
+
|
|
2068
|
+
if not stories_to_publish:
|
|
2069
|
+
print_info("No stories to publish")
|
|
2070
|
+
raise typer.Exit()
|
|
2071
|
+
|
|
2072
|
+
console.print(f"Found [bold]{len(stories_to_publish)}[/] stories from {scope_desc}")
|
|
2073
|
+
console.print()
|
|
2074
|
+
|
|
2075
|
+
if dry_run:
|
|
2076
|
+
console.print("[dim]Preview (dry-run):[/]")
|
|
2077
|
+
for story in stories_to_publish[:20]: # Limit preview to 20
|
|
2078
|
+
vis = visibility or story.visibility or "private"
|
|
2079
|
+
console.print(f" • [{vis}] {story.title[:55]}...")
|
|
2080
|
+
if len(stories_to_publish) > 20:
|
|
2081
|
+
console.print(f" ... and {len(stories_to_publish) - 20} more")
|
|
2082
|
+
console.print()
|
|
2083
|
+
console.print("Run without --dry-run to publish")
|
|
2084
|
+
raise typer.Exit()
|
|
2085
|
+
|
|
2086
|
+
# Build batch payload
|
|
2087
|
+
vis_label = visibility or "default"
|
|
2088
|
+
console.print(f"Publishing with visibility: [bold]{vis_label}[/]...")
|
|
2089
|
+
|
|
2090
|
+
stories_payload = []
|
|
2091
|
+
for story in stories_to_publish:
|
|
2092
|
+
payload = story.model_dump(mode="json")
|
|
2093
|
+
# Use override visibility or story's current visibility
|
|
2094
|
+
payload["visibility"] = visibility or story.visibility or "private"
|
|
2095
|
+
payload["client_id"] = story.id
|
|
2096
|
+
stories_payload.append(payload)
|
|
2097
|
+
|
|
2098
|
+
# Push all stories in batch with progress
|
|
2099
|
+
console.print(f"Publishing {len(stories_payload)} stories...")
|
|
2100
|
+
console.print()
|
|
2101
|
+
|
|
2102
|
+
with BatchProgress() as progress:
|
|
2103
|
+
try:
|
|
2104
|
+
result = asyncio.run(push_stories_batch(stories_payload))
|
|
2105
|
+
pushed = result.get("pushed", 0)
|
|
2106
|
+
failed = result.get("failed", 0)
|
|
2107
|
+
results = result.get("results", [])
|
|
2108
|
+
|
|
2109
|
+
# Display results
|
|
2110
|
+
for i, story_result in enumerate(results):
|
|
2111
|
+
story_title = stories_to_publish[i].title[:50] if i < len(stories_to_publish) else "Unknown"
|
|
2112
|
+
if story_result.get("success"):
|
|
2113
|
+
console.print(f" [{BRAND_SUCCESS}]✓[/] {story_title}")
|
|
2114
|
+
else:
|
|
2115
|
+
error_msg = story_result.get("error", "Unknown error")
|
|
2116
|
+
console.print(f" [{BRAND_ERROR}]✗[/] {story_title}: {error_msg}")
|
|
2117
|
+
|
|
2118
|
+
except (APIError, AuthError) as e:
|
|
2119
|
+
print_error(f"Publish failed: {e}")
|
|
2120
|
+
raise typer.Exit(1)
|
|
2121
|
+
|
|
2122
|
+
# Log operation
|
|
2123
|
+
if pushed > 0:
|
|
2124
|
+
log_cloud_operation(
|
|
2125
|
+
operation="publish",
|
|
2126
|
+
destination="repr.dev",
|
|
2127
|
+
payload_summary={
|
|
2128
|
+
"stories_published": pushed,
|
|
2129
|
+
"visibility": visibility or "default",
|
|
2130
|
+
"scope": "story" if story_id else ("repo" if repo else "global"),
|
|
2131
|
+
"repo": repo,
|
|
2132
|
+
},
|
|
2133
|
+
bytes_sent=0,
|
|
2134
|
+
)
|
|
2135
|
+
|
|
2136
|
+
console.print()
|
|
2137
|
+
if failed > 0:
|
|
2138
|
+
print_warning(f"Published {pushed}/{len(stories_payload)} stories ({failed} failed)")
|
|
2139
|
+
else:
|
|
2140
|
+
print_success(f"Published {pushed} stories to repr.dev")
|
|
2141
|
+
|
|
2142
|
+
|
|
1984
2143
|
@app.command()
|
|
1985
2144
|
def sync():
|
|
1986
2145
|
"""
|
|
@@ -3724,45 +3883,9 @@ def profile_link():
|
|
|
3724
3883
|
|
|
3725
3884
|
|
|
3726
3885
|
# =============================================================================
|
|
3727
|
-
#
|
|
3886
|
+
# UNPUBLISH COMMAND
|
|
3728
3887
|
# =============================================================================
|
|
3729
3888
|
|
|
3730
|
-
@app.command("publish")
|
|
3731
|
-
def publish_story(
|
|
3732
|
-
story_id: str = typer.Argument(..., help="Story ID to publish"),
|
|
3733
|
-
visibility: str = typer.Option("public", "--visibility", "-v", help="Visibility: public, friends, private"),
|
|
3734
|
-
):
|
|
3735
|
-
"""
|
|
3736
|
-
Set story visibility.
|
|
3737
|
-
|
|
3738
|
-
Examples:
|
|
3739
|
-
repr publish abc123
|
|
3740
|
-
repr publish abc123 --visibility friends
|
|
3741
|
-
"""
|
|
3742
|
-
from .api import set_story_visibility, AuthError
|
|
3743
|
-
|
|
3744
|
-
if visibility not in ("public", "friends", "private"):
|
|
3745
|
-
print_error(f"Invalid visibility: {visibility}")
|
|
3746
|
-
print_info("Valid options: public, friends, private")
|
|
3747
|
-
raise typer.Exit(1)
|
|
3748
|
-
|
|
3749
|
-
if not is_authenticated():
|
|
3750
|
-
print_error("Not authenticated")
|
|
3751
|
-
print_info("Run `repr login` first")
|
|
3752
|
-
raise typer.Exit(1)
|
|
3753
|
-
|
|
3754
|
-
try:
|
|
3755
|
-
with create_spinner(f"Setting visibility to {visibility}..."):
|
|
3756
|
-
result = asyncio.run(set_story_visibility(story_id, visibility))
|
|
3757
|
-
print_success(f"Story visibility set to {visibility}")
|
|
3758
|
-
except AuthError as e:
|
|
3759
|
-
print_error(str(e))
|
|
3760
|
-
raise typer.Exit(1)
|
|
3761
|
-
except APIError as e:
|
|
3762
|
-
print_error(f"API error: {e}")
|
|
3763
|
-
raise typer.Exit(1)
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
3889
|
@app.command("unpublish")
|
|
3767
3890
|
def unpublish_story(
|
|
3768
3891
|
story_id: str = typer.Argument(..., help="Story ID to unpublish"),
|