kolega-code 0.1.0__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.
- kolega_code/__init__.py +151 -0
- kolega_code/agent/__init__.py +42 -0
- kolega_code/agent/baseagent.py +998 -0
- kolega_code/agent/browseragent.py +123 -0
- kolega_code/agent/coder.py +157 -0
- kolega_code/agent/common.py +41 -0
- kolega_code/agent/compression.py +81 -0
- kolega_code/agent/context.py +112 -0
- kolega_code/agent/conversation.py +408 -0
- kolega_code/agent/generalagent.py +146 -0
- kolega_code/agent/investigationagent.py +123 -0
- kolega_code/agent/planningagent.py +187 -0
- kolega_code/agent/prompt_provider.py +196 -0
- kolega_code/agent/prompt_templates/agents/browser.j2 +102 -0
- kolega_code/agent/prompt_templates/agents/coder_cli_mode.j2 +127 -0
- kolega_code/agent/prompt_templates/agents/general.j2 +68 -0
- kolega_code/agent/prompt_templates/agents/investigation.j2 +72 -0
- kolega_code/agent/prompt_templates/common/frontend_guidance.md +36 -0
- kolega_code/agent/prompt_templates/common/kolega_md_instructions.md +14 -0
- kolega_code/agent/prompt_templates/environment_variables/workspace_env_vars.md +11 -0
- kolega_code/agent/prompt_templates/template_guidance/expo-template.md +379 -0
- kolega_code/agent/prompt_templates/template_guidance/html-website-template.md +3 -0
- kolega_code/agent/prompt_templates/template_guidance/mern-stack-template.md +3 -0
- kolega_code/agent/prompt_templates/template_guidance/react-vite-shadcdn-template.md +182 -0
- kolega_code/agent/prompts.py +192 -0
- kolega_code/agent/tests/__init__.py +0 -0
- kolega_code/agent/tests/llm/__init__.py +0 -0
- kolega_code/agent/tests/llm/test_anthropic_token_counting.py +633 -0
- kolega_code/agent/tests/llm/test_billing_openai_cache.py +74 -0
- kolega_code/agent/tests/llm/test_client.py +773 -0
- kolega_code/agent/tests/llm/test_dashscope_mapping.py +32 -0
- kolega_code/agent/tests/llm/test_error_boundary.py +322 -0
- kolega_code/agent/tests/llm/test_exceptions.py +249 -0
- kolega_code/agent/tests/llm/test_instrumented_client.py +536 -0
- kolega_code/agent/tests/llm/test_instrumented_client_integration.py +547 -0
- kolega_code/agent/tests/llm/test_langfuse_normalization.py +39 -0
- kolega_code/agent/tests/llm/test_model_specs.py +17 -0
- kolega_code/agent/tests/llm/test_openai_cached_tokens.py +58 -0
- kolega_code/agent/tests/llm/test_openai_cached_tokens_stream.py +74 -0
- kolega_code/agent/tests/llm/test_openai_message_conversion.py +30 -0
- kolega_code/agent/tests/llm/test_openai_token_counting.py +687 -0
- kolega_code/agent/tests/llm/test_tool_execution_ids.py +193 -0
- kolega_code/agent/tests/services/__init__.py +1 -0
- kolega_code/agent/tests/services/test_browser.py +447 -0
- kolega_code/agent/tests/services/test_browser_parity.py +353 -0
- kolega_code/agent/tests/services/test_file_system.py +699 -0
- kolega_code/agent/tests/services/test_sandbox_terminal_input.py +98 -0
- kolega_code/agent/tests/services/test_terminal.py +154 -0
- kolega_code/agent/tests/services/test_terminal_command_tracking.py +385 -0
- kolega_code/agent/tests/services/test_terminal_state_serializer.py +262 -0
- kolega_code/agent/tests/test_agent_tools_inventory.py +267 -0
- kolega_code/agent/tests/test_base_agent.py +1942 -0
- kolega_code/agent/tests/test_coder_attachments.py +330 -0
- kolega_code/agent/tests/test_coder_prompt_extensions.py +61 -0
- kolega_code/agent/tests/test_commands.py +179 -0
- kolega_code/agent/tests/test_duplicate_tool_results.py +556 -0
- kolega_code/agent/tests/test_empty_message_handling.py +48 -0
- kolega_code/agent/tests/test_general_agent.py +242 -0
- kolega_code/agent/tests/test_html.py +320 -0
- kolega_code/agent/tests/test_parallel_tool_calls.py +291 -0
- kolega_code/agent/tests/test_planning_agent.py +227 -0
- kolega_code/agent/tests/test_prompt_provider.py +271 -0
- kolega_code/agent/tests/test_tool_registry.py +102 -0
- kolega_code/agent/tests/test_tools.py +549 -0
- kolega_code/agent/tests/tool_backend/__init__.py +0 -0
- kolega_code/agent/tests/tool_backend/test_agent_tool.py +356 -0
- kolega_code/agent/tests/tool_backend/test_base_tool.py +147 -0
- kolega_code/agent/tests/tool_backend/test_browser_tool.py +335 -0
- kolega_code/agent/tests/tool_backend/test_build_tool.py +93 -0
- kolega_code/agent/tests/tool_backend/test_create_file_tool.py +115 -0
- kolega_code/agent/tests/tool_backend/test_glob_tool.py +196 -0
- kolega_code/agent/tests/tool_backend/test_glob_tool_sandbox_parity.py +230 -0
- kolega_code/agent/tests/tool_backend/test_list_directory_tool.py +292 -0
- kolega_code/agent/tests/tool_backend/test_read_file_tool.py +173 -0
- kolega_code/agent/tests/tool_backend/test_replace_entire_file_tool.py +115 -0
- kolega_code/agent/tests/tool_backend/test_replace_lines_tool.py +141 -0
- kolega_code/agent/tests/tool_backend/test_search_and_replace_tool.py +174 -0
- kolega_code/agent/tests/tool_backend/test_search_codebase_tool.py +228 -0
- kolega_code/agent/tests/tool_backend/test_terminal_tool.py +482 -0
- kolega_code/agent/tests/tool_backend/test_think_hard_integration.py +189 -0
- kolega_code/agent/tests/tool_backend/test_think_hard_streaming.py +445 -0
- kolega_code/agent/tests/tool_backend/test_web_fetch_tool.py +194 -0
- kolega_code/agent/tool_backend/agent_tool.py +414 -0
- kolega_code/agent/tool_backend/apply_edit_tool.py +98 -0
- kolega_code/agent/tool_backend/apply_patch_tool.py +514 -0
- kolega_code/agent/tool_backend/base_tool.py +217 -0
- kolega_code/agent/tool_backend/browser_tool.py +271 -0
- kolega_code/agent/tool_backend/build_tool.py +93 -0
- kolega_code/agent/tool_backend/create_file_tool.py +52 -0
- kolega_code/agent/tool_backend/glob_tool.py +323 -0
- kolega_code/agent/tool_backend/list_directory_tool.py +300 -0
- kolega_code/agent/tool_backend/memory_tool.py +79 -0
- kolega_code/agent/tool_backend/read_file_tool.py +119 -0
- kolega_code/agent/tool_backend/replace_entire_file_tool.py +40 -0
- kolega_code/agent/tool_backend/replace_lines_tool.py +97 -0
- kolega_code/agent/tool_backend/search_and_replace_tool.py +146 -0
- kolega_code/agent/tool_backend/search_codebase_tool.py +377 -0
- kolega_code/agent/tool_backend/streaming_tool.py +47 -0
- kolega_code/agent/tool_backend/terminal_tool.py +643 -0
- kolega_code/agent/tool_backend/think_hard_tool.py +211 -0
- kolega_code/agent/tool_backend/web_fetch_tool.py +205 -0
- kolega_code/agent/tools.py +1704 -0
- kolega_code/agent/utils/commands.py +94 -0
- kolega_code/cli/__init__.py +1 -0
- kolega_code/cli/app.py +2756 -0
- kolega_code/cli/config.py +280 -0
- kolega_code/cli/connection.py +49 -0
- kolega_code/cli/file_index.py +147 -0
- kolega_code/cli/main.py +564 -0
- kolega_code/cli/mentions.py +155 -0
- kolega_code/cli/messages.py +89 -0
- kolega_code/cli/provider_registry.py +96 -0
- kolega_code/cli/session_store.py +207 -0
- kolega_code/cli/settings.py +87 -0
- kolega_code/cli/skills.py +409 -0
- kolega_code/cli/slash_commands.py +108 -0
- kolega_code/cli/tests/__init__.py +1 -0
- kolega_code/cli/tests/test_app.py +4251 -0
- kolega_code/cli/tests/test_cli_config.py +171 -0
- kolega_code/cli/tests/test_connection.py +26 -0
- kolega_code/cli/tests/test_file_index.py +103 -0
- kolega_code/cli/tests/test_main.py +455 -0
- kolega_code/cli/tests/test_mentions.py +108 -0
- kolega_code/cli/tests/test_session_store.py +67 -0
- kolega_code/cli/tests/test_settings.py +62 -0
- kolega_code/cli/tests/test_skills.py +157 -0
- kolega_code/cli/tests/test_slash_commands.py +88 -0
- kolega_code/cli/theme.py +180 -0
- kolega_code/config.py +154 -0
- kolega_code/events.py +202 -0
- kolega_code/llm/client.py +300 -0
- kolega_code/llm/exceptions.py +285 -0
- kolega_code/llm/instrumented_client.py +520 -0
- kolega_code/llm/models.py +1368 -0
- kolega_code/llm/providers/__init__.py +0 -0
- kolega_code/llm/providers/anthropic.py +387 -0
- kolega_code/llm/providers/base.py +71 -0
- kolega_code/llm/providers/google.py +157 -0
- kolega_code/llm/providers/models.py +37 -0
- kolega_code/llm/providers/openai.py +363 -0
- kolega_code/llm/ratelimit.py +40 -0
- kolega_code/llm/specs.py +67 -0
- kolega_code/llm/tool_execution_ids.py +18 -0
- kolega_code/models/__init__.py +9 -0
- kolega_code/models/sandbox_terminal_state.py +47 -0
- kolega_code/runtime.py +50 -0
- kolega_code/sandbox/README.md +200 -0
- kolega_code/sandbox/__init__.py +21 -0
- kolega_code/sandbox/async_filesystem.py +475 -0
- kolega_code/sandbox/base.py +297 -0
- kolega_code/sandbox/browser.py +25 -0
- kolega_code/sandbox/event_loop.py +43 -0
- kolega_code/sandbox/filesystem.py +341 -0
- kolega_code/sandbox/local.py +118 -0
- kolega_code/sandbox/serializer.py +175 -0
- kolega_code/sandbox/terminal.py +868 -0
- kolega_code/sandbox/utils.py +216 -0
- kolega_code/services/base.py +255 -0
- kolega_code/services/browser.py +444 -0
- kolega_code/services/file_system.py +749 -0
- kolega_code/services/html.py +221 -0
- kolega_code/services/terminal.py +903 -0
- kolega_code/tools/__init__.py +22 -0
- kolega_code/tools/core.py +33 -0
- kolega_code/tools/definitions.py +81 -0
- kolega_code/tools/registry.py +73 -0
- kolega_code-0.1.0.dist-info/METADATA +157 -0
- kolega_code-0.1.0.dist-info/RECORD +171 -0
- kolega_code-0.1.0.dist-info/WHEEL +4 -0
- kolega_code-0.1.0.dist-info/entry_points.txt +2 -0
- kolega_code-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
## **Introduction**
|
|
2
|
+
|
|
3
|
+
You are a special code investigation agent for {{ context.system_name }}. Your purpose is to use the tools at your disposal to complete
|
|
4
|
+
the task that Kolega Code gives you. The task will usually be related to explaining a codebase.
|
|
5
|
+
|
|
6
|
+
- CRITICAL: YOU MUST NOT OUTPUT CODE, UNLESS YOU ARE ASKED TO.
|
|
7
|
+
- CRITICAL: BE CONCISE ON YOUR RESPONSES AND AVOID VERBOSITY
|
|
8
|
+
- CRITICAL: BE FOCUSED, DO NOT OVERENGINEER, OR OVERCOMPLICATE.
|
|
9
|
+
- CRITICAL: WE ARE ON A BUDGET, SAVE COSTS ON TOKENS
|
|
10
|
+
- CRITICAL: IF THERE IS A DESIGN-BRIEF FILE IN THE PROJECT, CONSTANTLY CHECK AND STICK TO IT!
|
|
11
|
+
|
|
12
|
+
Here is some useful information about the environment you are running in:
|
|
13
|
+
|
|
14
|
+
- Working directory: {{ context.project_path }}
|
|
15
|
+
- Is directory a git repo: {{ context.is_git_repo }}
|
|
16
|
+
- Platform: {{ context.platform }}
|
|
17
|
+
- Today's date: {{ context.date_today }}
|
|
18
|
+
- Model: {{ context.model_name }}
|
|
19
|
+
|
|
20
|
+
{% if context.memories and context.memories|length > 0 %}
|
|
21
|
+
## Workspace Memories
|
|
22
|
+
|
|
23
|
+
You have access to the following information about this workspace:
|
|
24
|
+
|
|
25
|
+
{% for memory in context.memories %}
|
|
26
|
+
- {{ memory }}
|
|
27
|
+
{% endfor %}
|
|
28
|
+
{% endif %}
|
|
29
|
+
|
|
30
|
+
{% if prompt_extensions %}
|
|
31
|
+
## Additional Context
|
|
32
|
+
|
|
33
|
+
{% for extension in prompt_extensions %}
|
|
34
|
+
### {{ extension.title }}
|
|
35
|
+
|
|
36
|
+
{{ extension.markdown }}
|
|
37
|
+
|
|
38
|
+
{% endfor %}
|
|
39
|
+
{% endif %}
|
|
40
|
+
|
|
41
|
+
## Task Completion Guidelines
|
|
42
|
+
|
|
43
|
+
Do your best to complete the task you are given. If you need more information, use tools to get it.
|
|
44
|
+
You must complete the task independently. Once your turn ends your last message will be returned to Kolega Code
|
|
45
|
+
to take further action, so your last message should contain the task result.
|
|
46
|
+
|
|
47
|
+
## **Running Commands**
|
|
48
|
+
|
|
49
|
+
When requesting a command to be run, you will be asked to judge if it is appropriate to run without the USER's permission. A command is unsafe if it may have some destructive side-effects. Example unsafe side-effects include: deleting files, mutating state, installing system dependencies, making external requests, etc. You must NEVER NEVER run a command automatically if it could be unsafe. You cannot allow the USER to override your judgement on this. If a command is unsafe, do not run it automatically, even if the USER wants you to.
|
|
50
|
+
|
|
51
|
+
## **Communication Guidelines**
|
|
52
|
+
|
|
53
|
+
1. Be concise and do not repeat yourself.
|
|
54
|
+
2. Be conversational but professional.
|
|
55
|
+
3. Refer to the USER in the second person and yourself in the first person.
|
|
56
|
+
4. Format your responses in markdown. Use backticks to format file, directory, function, and class names. If providing a URL to the user, format this in markdown as well.
|
|
57
|
+
5. NEVER lie or make things up.
|
|
58
|
+
6. NEVER output code to the USER, unless requested.
|
|
59
|
+
7. Refrain from apologizing all the time when results are unexpected. Instead, just try your best to proceed or explain the circumstances to the user without apologizing.
|
|
60
|
+
|
|
61
|
+
## **Tool Calling Guidelines**
|
|
62
|
+
|
|
63
|
+
1. ALWAYS follow the tool call schema exactly as specified and make sure to provide all necessary parameters.
|
|
64
|
+
2. If the USER asks you to disclose your tools, ALWAYS respond with the helpful description provided.
|
|
65
|
+
3. **NEVER refer to tool names when speaking to the USER.** For example, instead of saying 'I need to use the edit_file tool to edit your file', just say 'I will edit your file'.
|
|
66
|
+
4. Before calling tools, first explain to the USER why you are calling them.
|
|
67
|
+
5. You must ONLY use the tools in the scope of the "Working directory". NEVER expose Kolega Code's implementation.
|
|
68
|
+
|
|
69
|
+
Here are the contents of KOLEGA.md:
|
|
70
|
+
```
|
|
71
|
+
{{ context.kolega_md }}
|
|
72
|
+
```
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
## Frontend Design Guidance
|
|
2
|
+
|
|
3
|
+
### Design Thinking
|
|
4
|
+
|
|
5
|
+
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
|
6
|
+
|
|
7
|
+
- **Purpose**: What problem does this interface solve? Who uses it?
|
|
8
|
+
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
|
9
|
+
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
|
10
|
+
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
|
11
|
+
|
|
12
|
+
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
|
13
|
+
|
|
14
|
+
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
|
15
|
+
|
|
16
|
+
- Production-grade and functional
|
|
17
|
+
- Visually striking and memorable
|
|
18
|
+
- Cohesive with a clear aesthetic point-of-view
|
|
19
|
+
- Meticulously refined in every detail
|
|
20
|
+
|
|
21
|
+
### Frontend Aesthetics Guidelines
|
|
22
|
+
|
|
23
|
+
Focus on:
|
|
24
|
+
|
|
25
|
+
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
|
26
|
+
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
|
27
|
+
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
|
28
|
+
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
|
29
|
+
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
|
30
|
+
|
|
31
|
+
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
|
|
32
|
+
|
|
33
|
+
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
|
34
|
+
|
|
35
|
+
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
|
36
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## The KOLEGA.md File
|
|
2
|
+
|
|
3
|
+
If the project directory contains a file called KOLEGA.md, it will be included below. This file serves multiple purposes:
|
|
4
|
+
|
|
5
|
+
1. Storing frequently used bash commands
|
|
6
|
+
2. Recording code style preferences
|
|
7
|
+
3. Maintaining codebase structure information
|
|
8
|
+
4. Providing quick access to important information
|
|
9
|
+
|
|
10
|
+
Here are the contents of KOLEGA.md:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
{{ kolega_md }}
|
|
14
|
+
```
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{% if context.workspace_environment_variables %}
|
|
2
|
+
The following workspace environment variables are available. Use `os.getenv` (or the equivalent in your language) to read their values at runtime:
|
|
3
|
+
|
|
4
|
+
{% for var_name, var_description in context.workspace_environment_variables.items() | sort %}
|
|
5
|
+
- `{{ var_name }}`: {{ var_description }}
|
|
6
|
+
{% endfor %}
|
|
7
|
+
|
|
8
|
+
Values are injected into the sandbox automatically. Never write secrets to source files or logs.
|
|
9
|
+
{% else %}
|
|
10
|
+
No workspace-specific environment variables are configured.
|
|
11
|
+
{% endif %}
|
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
## Expo React Native + Hono Backend Template
|
|
2
|
+
|
|
3
|
+
### Project Overview
|
|
4
|
+
This is a full stack mobile-first starter template with an Expo React Native frontend and Hono backend. The project uses TypeScript throughout with strict configuration for better code quality. The mobile app runs on port 9001 with tunneling support, the backend on port 9002, and both have been started automatically with hot reload enabled. **Note: This template prioritizes mobile app development (iOS/Android) and is not intended for web deployment.**
|
|
5
|
+
|
|
6
|
+
### Project Structure
|
|
7
|
+
```
|
|
8
|
+
/
|
|
9
|
+
├── frontend/ # Expo React Native mobile application
|
|
10
|
+
├── backend/ # Hono API server with MongoDB
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
#### Mobile Frontend Development (Port 9001)
|
|
14
|
+
- **Framework**: Expo SDK ~54.0.10 with React Native 0.81.4
|
|
15
|
+
- **React**: React 19.1.0 with latest features
|
|
16
|
+
- **TypeScript**: Strict configuration enabled for better code quality
|
|
17
|
+
- **Styling**: React Native StyleSheet API with inline styling patterns
|
|
18
|
+
- **Development**: Expo CLI with tunneling, device testing, and hot reload
|
|
19
|
+
- **Architecture**: New Architecture enabled for improved performance
|
|
20
|
+
- **Entry Point**: `index.ts` using `registerRootComponent(App)`
|
|
21
|
+
- **Main Component**: `App.tsx` with backend health checking integration
|
|
22
|
+
- **API Layer**: Structured in `lib/backend.ts` (business logic) and `lib/api.ts` (transport layer)
|
|
23
|
+
|
|
24
|
+
#### Backend Development (Port 9002)
|
|
25
|
+
- **Framework**: Hono 4.6.14 with MongoDB
|
|
26
|
+
- **TypeScript**: Loose configuration, builds to `./build` directory
|
|
27
|
+
- **CORS**: Configured to accept requests from any origin (`*`)
|
|
28
|
+
- **Database**: MongoDB connection via `MONGODB_URI` environment variable
|
|
29
|
+
- **Entry point**: `backend/index.ts`
|
|
30
|
+
- **Hot reload**: Enabled via tsx watch mode
|
|
31
|
+
|
|
32
|
+
### Key Conventions
|
|
33
|
+
|
|
34
|
+
#### TypeScript
|
|
35
|
+
- Frontend uses TypeScript ~5.9.2 with strict mode enabled
|
|
36
|
+
- Backend uses TypeScript with loose configuration for easier development
|
|
37
|
+
- ES modules with `.js` extensions in imports for backend
|
|
38
|
+
- Strong type safety encouraged for mobile app development
|
|
39
|
+
|
|
40
|
+
#### Code Style
|
|
41
|
+
- Use single quotes over double quotes
|
|
42
|
+
- Prefer descriptive variable names (avoid abbreviations)
|
|
43
|
+
- Modularize code into smaller functions
|
|
44
|
+
- Follow DRY principles - deduplicate code whenever possible
|
|
45
|
+
- Use type hints in function definitions
|
|
46
|
+
- Follow React Native and Expo best practices
|
|
47
|
+
|
|
48
|
+
#### File Organization
|
|
49
|
+
- Mobile app components go in `frontend/` root or organized subdirectories
|
|
50
|
+
- Backend routes should be modularized in separate files
|
|
51
|
+
- Keep database logic in `backend/database/`
|
|
52
|
+
- API integration logic in `frontend/lib/` directory
|
|
53
|
+
- Assets in `frontend/assets/` for app icons, splash screens, etc.
|
|
54
|
+
|
|
55
|
+
#### Making Changes
|
|
56
|
+
|
|
57
|
+
1. **Adding Mobile App Features**:
|
|
58
|
+
- Create new React Native components using `View`, `Text`, `ScrollView`, `TouchableOpacity`
|
|
59
|
+
- Use StyleSheet API for styling components
|
|
60
|
+
- Import and use React Native components from 'react-native'
|
|
61
|
+
- Add new screens and implement navigation with React Navigation (when needed)
|
|
62
|
+
- Test on both iOS and Android platforms
|
|
63
|
+
|
|
64
|
+
2. **Adding Backend Endpoints**:
|
|
65
|
+
- Create route modules that export Hono routers
|
|
66
|
+
- Use the MongoDB connection from `database/connection.ts`
|
|
67
|
+
- Maintain consistent error handling and response formats
|
|
68
|
+
- The path portion of the URL should ALWAYS start with /api/
|
|
69
|
+
|
|
70
|
+
3. **Database Operations**:
|
|
71
|
+
- Use `get_database()` to access the MongoDB instance
|
|
72
|
+
- Handle connection errors gracefully
|
|
73
|
+
- Keep connection logic centralized
|
|
74
|
+
|
|
75
|
+
4. **Environment Variables**:
|
|
76
|
+
- Backend uses `MONGODB_URI` and `DATABASE_NAME`
|
|
77
|
+
- Mobile app uses `EXPO_PUBLIC_API_BASE_URL` or `EXPO_PUBLIC_DEV_API_BASE_URL` for API endpoints
|
|
78
|
+
- Environment variables for Expo must be prefixed with `EXPO_PUBLIC_`
|
|
79
|
+
|
|
80
|
+
#### Testing Changes
|
|
81
|
+
- Mobile app changes appear instantly via Expo hot reload
|
|
82
|
+
- Backend changes reload automatically via tsx
|
|
83
|
+
- To test on physical devices, ask user to scan QR code
|
|
84
|
+
- Use iOS Simulator and Android Emulator for preview builds testing
|
|
85
|
+
- Build production apps using EAS Build for app store deployment
|
|
86
|
+
|
|
87
|
+
### Hono Backend Cheat Sheet
|
|
88
|
+
|
|
89
|
+
#### Basic Route Handlers
|
|
90
|
+
```typescript
|
|
91
|
+
// GET request
|
|
92
|
+
app.get('/users', async (c) => {
|
|
93
|
+
const users = await get_users_from_db();
|
|
94
|
+
return c.json({ users });
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// POST request with body parsing
|
|
98
|
+
app.post('/users', async (c) => {
|
|
99
|
+
const body = await c.req.json();
|
|
100
|
+
const { name, email } = body;
|
|
101
|
+
// Process data...
|
|
102
|
+
return c.json({ message: 'User created' }, 201);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
// Route parameters
|
|
106
|
+
app.get('/users/:id', async (c) => {
|
|
107
|
+
const id = c.req.param('id');
|
|
108
|
+
const user = await get_user_by_id(id);
|
|
109
|
+
return c.json({ user });
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Query parameters
|
|
113
|
+
app.get('/search', async (c) => {
|
|
114
|
+
const query = c.req.query('q');
|
|
115
|
+
const limit = c.req.query('limit') || '10';
|
|
116
|
+
// Search logic...
|
|
117
|
+
return c.json({ results });
|
|
118
|
+
});
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### MongoDB Integration Pattern
|
|
122
|
+
```typescript
|
|
123
|
+
import { get_database } from './database/connection.js';
|
|
124
|
+
|
|
125
|
+
app.get('/items', async (c) => {
|
|
126
|
+
try {
|
|
127
|
+
const db = get_database();
|
|
128
|
+
const items = await db.collection('items').find({}).toArray();
|
|
129
|
+
return c.json({ success: true, items });
|
|
130
|
+
} catch (error) {
|
|
131
|
+
return c.json({ success: false, error: error.message }, 500);
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
#### Creating Modular Routes
|
|
137
|
+
```typescript
|
|
138
|
+
// routes/user_routes.ts
|
|
139
|
+
import { Hono } from 'hono';
|
|
140
|
+
|
|
141
|
+
export const create_user_routes = (): Hono => {
|
|
142
|
+
const router = new Hono();
|
|
143
|
+
|
|
144
|
+
router.get('/', async (c) => {
|
|
145
|
+
// List users
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
router.post('/', async (c) => {
|
|
149
|
+
// Create user
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return router;
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
// In index.ts
|
|
156
|
+
import { create_user_routes } from './routes/user_routes.js';
|
|
157
|
+
app.route('/api/users', create_user_routes());
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
#### Common Response Patterns
|
|
161
|
+
```typescript
|
|
162
|
+
// Success response
|
|
163
|
+
return c.json({ success: true, data: result });
|
|
164
|
+
|
|
165
|
+
// Error response
|
|
166
|
+
return c.json({ success: false, error: 'Not found' }, 404);
|
|
167
|
+
|
|
168
|
+
// Redirect
|
|
169
|
+
return c.redirect('/new-location');
|
|
170
|
+
|
|
171
|
+
// Set headers
|
|
172
|
+
c.header('X-Custom-Header', 'value');
|
|
173
|
+
return c.json({ data });
|
|
174
|
+
|
|
175
|
+
// Set status
|
|
176
|
+
return c.text('Created', 201);
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
#### Middleware Pattern
|
|
180
|
+
```typescript
|
|
181
|
+
// Custom middleware
|
|
182
|
+
app.use('*', async (c, next) => {
|
|
183
|
+
console.log(`${c.req.method} ${c.req.path}`);
|
|
184
|
+
await next();
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
// Protected routes
|
|
188
|
+
app.use('/api/*', async (c, next) => {
|
|
189
|
+
const token = c.req.header('Authorization');
|
|
190
|
+
if (!token) {
|
|
191
|
+
return c.json({ error: 'Unauthorized' }, 401);
|
|
192
|
+
}
|
|
193
|
+
await next();
|
|
194
|
+
});
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Expo React Native Mobile Development Cheat Sheet
|
|
198
|
+
|
|
199
|
+
#### Essential React Native Components
|
|
200
|
+
```typescript
|
|
201
|
+
import { View, Text, ScrollView, TouchableOpacity, TextInput, Alert } from 'react-native';
|
|
202
|
+
|
|
203
|
+
// Basic container and layout
|
|
204
|
+
<View style={styles.container}>
|
|
205
|
+
<Text style={styles.title}>Hello Mobile!</Text>
|
|
206
|
+
</View>
|
|
207
|
+
|
|
208
|
+
// Scrollable content
|
|
209
|
+
<ScrollView contentContainerStyle={styles.scrollContainer}>
|
|
210
|
+
<Text>Scrollable content here</Text>
|
|
211
|
+
</ScrollView>
|
|
212
|
+
|
|
213
|
+
// Interactive button
|
|
214
|
+
<TouchableOpacity style={styles.button} onPress={handlePress}>
|
|
215
|
+
<Text style={styles.buttonText}>Press Me</Text>
|
|
216
|
+
</TouchableOpacity>
|
|
217
|
+
|
|
218
|
+
// Text input
|
|
219
|
+
<TextInput
|
|
220
|
+
style={styles.input}
|
|
221
|
+
placeholder="Enter text"
|
|
222
|
+
value={inputValue}
|
|
223
|
+
onChangeText={setInputValue}
|
|
224
|
+
/>
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
#### StyleSheet API Patterns
|
|
228
|
+
```typescript
|
|
229
|
+
import { StyleSheet, Dimensions } from 'react-native';
|
|
230
|
+
|
|
231
|
+
const { width, height } = Dimensions.get('window');
|
|
232
|
+
|
|
233
|
+
const styles = StyleSheet.create({
|
|
234
|
+
container: {
|
|
235
|
+
flex: 1,
|
|
236
|
+
backgroundColor: '#f1f5f9',
|
|
237
|
+
paddingHorizontal: 24,
|
|
238
|
+
},
|
|
239
|
+
centered: {
|
|
240
|
+
alignItems: 'center',
|
|
241
|
+
justifyContent: 'center',
|
|
242
|
+
},
|
|
243
|
+
card: {
|
|
244
|
+
backgroundColor: '#ffffff',
|
|
245
|
+
borderRadius: 12,
|
|
246
|
+
padding: 16,
|
|
247
|
+
shadowColor: '#000',
|
|
248
|
+
shadowOffset: { width: 0, height: 2 },
|
|
249
|
+
shadowOpacity: 0.1,
|
|
250
|
+
shadowRadius: 4,
|
|
251
|
+
elevation: 3, // Android shadow
|
|
252
|
+
},
|
|
253
|
+
button: {
|
|
254
|
+
backgroundColor: '#3b82f6',
|
|
255
|
+
paddingVertical: 12,
|
|
256
|
+
paddingHorizontal: 24,
|
|
257
|
+
borderRadius: 8,
|
|
258
|
+
},
|
|
259
|
+
buttonText: {
|
|
260
|
+
color: '#ffffff',
|
|
261
|
+
fontWeight: '600',
|
|
262
|
+
textAlign: 'center',
|
|
263
|
+
},
|
|
264
|
+
responsive: {
|
|
265
|
+
width: width * 0.9, // 90% of screen width
|
|
266
|
+
minHeight: height * 0.6, // 60% of screen height
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### Backend Integration Pattern
|
|
272
|
+
```typescript
|
|
273
|
+
// In lib/backend.ts - Business logic functions
|
|
274
|
+
import { apiGet, apiPost } from './api';
|
|
275
|
+
|
|
276
|
+
export async function getUserProfile(userId: string) {
|
|
277
|
+
try {
|
|
278
|
+
const response = await apiGet(`/api/users/${userId}`);
|
|
279
|
+
const data = await response.json();
|
|
280
|
+
return data.user;
|
|
281
|
+
} catch (error) {
|
|
282
|
+
throw new Error('Failed to fetch user profile');
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export async function createUser(userData: any) {
|
|
287
|
+
try {
|
|
288
|
+
const response = await apiPost('/api/users', userData);
|
|
289
|
+
const data = await response.json();
|
|
290
|
+
return data.user;
|
|
291
|
+
} catch (error) {
|
|
292
|
+
throw new Error('Failed to create user');
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// In your component
|
|
297
|
+
import { getUserProfile } from '../lib/backend';
|
|
298
|
+
|
|
299
|
+
export default function UserScreen() {
|
|
300
|
+
const [user, setUser] = useState(null);
|
|
301
|
+
const [loading, setLoading] = useState(true);
|
|
302
|
+
|
|
303
|
+
useEffect(() => {
|
|
304
|
+
loadUserProfile();
|
|
305
|
+
}, []);
|
|
306
|
+
|
|
307
|
+
const loadUserProfile = async () => {
|
|
308
|
+
try {
|
|
309
|
+
setLoading(true);
|
|
310
|
+
const userData = await getUserProfile('user123');
|
|
311
|
+
setUser(userData);
|
|
312
|
+
} catch (error) {
|
|
313
|
+
Alert.alert('Error', 'Failed to load user profile');
|
|
314
|
+
} finally {
|
|
315
|
+
setLoading(false);
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
if (loading) {
|
|
320
|
+
return (
|
|
321
|
+
<View style={styles.centered}>
|
|
322
|
+
<Text>Loading...</Text>
|
|
323
|
+
</View>
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return (
|
|
328
|
+
<View style={styles.container}>
|
|
329
|
+
<Text style={styles.title}>{user?.name}</Text>
|
|
330
|
+
</View>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
#### Common Mobile Development Patterns
|
|
336
|
+
```typescript
|
|
337
|
+
// Loading states
|
|
338
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
339
|
+
|
|
340
|
+
// Safe area handling (for newer devices)
|
|
341
|
+
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
342
|
+
const insets = useSafeAreaInsets();
|
|
343
|
+
|
|
344
|
+
// Platform-specific code
|
|
345
|
+
import { Platform } from 'react-native';
|
|
346
|
+
const isIOS = Platform.OS === 'ios';
|
|
347
|
+
const isAndroid = Platform.OS === 'android';
|
|
348
|
+
|
|
349
|
+
// Keyboard handling
|
|
350
|
+
import { KeyboardAvoidingView } from 'react-native';
|
|
351
|
+
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? 'padding' : 'height'}>
|
|
352
|
+
{/* Your form content */}
|
|
353
|
+
</KeyboardAvoidingView>
|
|
354
|
+
|
|
355
|
+
// Alert dialogs
|
|
356
|
+
import { Alert } from 'react-native';
|
|
357
|
+
Alert.alert(
|
|
358
|
+
'Confirm Action',
|
|
359
|
+
'Are you sure you want to continue?',
|
|
360
|
+
[
|
|
361
|
+
{ text: 'Cancel', style: 'cancel' },
|
|
362
|
+
{ text: 'OK', onPress: () => console.log('Confirmed') },
|
|
363
|
+
]
|
|
364
|
+
);
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
#### Expo Specific Features
|
|
368
|
+
```typescript
|
|
369
|
+
// Status bar
|
|
370
|
+
import { StatusBar } from 'expo-status-bar';
|
|
371
|
+
<StatusBar style="dark" />
|
|
372
|
+
|
|
373
|
+
// Asset loading
|
|
374
|
+
import { Image } from 'react-native';
|
|
375
|
+
<Image source={require('./assets/icon.png')} style={styles.logo} />
|
|
376
|
+
|
|
377
|
+
// Environment variables
|
|
378
|
+
const apiUrl = process.env.EXPO_PUBLIC_API_BASE_URL;
|
|
379
|
+
```
|