Add CONTEXT.md generation on kisync init

Creates a comprehensive context file for AI assistants (Claude Code, Codex)
that explains the project structure, script execution model, execQuery usage,
query file naming conventions, and available sandbox globals.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-14 17:08:08 +03:00
parent 302c7ab9f5
commit 9f041c2d3d

View File

@@ -1,3 +1,5 @@
import * as fs from 'fs';
import * as path from 'path';
import * as readline from 'readline';
import chalk from 'chalk';
import { writeConfig, findProjectRoot } from '../config';
@@ -91,11 +93,173 @@ export async function initCommand(): Promise<void> {
writeConfig({ host, token }, cwd);
// Write default context file for AI assistants
writeDefaultContext(cwd);
console.log(chalk.green('\nProject initialized successfully!'));
console.log(chalk.gray(`Config saved to: ${cwd}/.kisync.json`));
console.log(chalk.gray(`AI context: ${cwd}/CONTEXT.md`));
console.log('');
console.log('Next steps:');
console.log(` ${chalk.cyan('kisync pull')} — download endpoints from server`);
console.log(` ${chalk.cyan('kisync status')} — check what changed`);
console.log(` ${chalk.cyan('kisync push')} — upload your changes`);
}
function writeDefaultContext(cwd: string): void {
const contextPath = path.join(cwd, 'CONTEXT.md');
if (fs.existsSync(contextPath)) return; // don't overwrite
const content = `# KIS API Builder — Project Context
This directory contains endpoint definitions synced from a KIS API Builder server via \`kisync\`.
## Directory Structure
\`\`\`
project-root/
├── .kisync.json # connection config (host, token) — DO NOT COMMIT
├── .kisync-state.json # sync state (hashes, timestamps) — DO NOT EDIT
├── CONTEXT.md # this file
├── FolderName/ # API folder
│ ├── _folder.json # folder metadata (id, name, parent_id)
│ └── EndpointName/ # single API endpoint
│ ├── endpoint.json # endpoint metadata (method, path, params, config)
│ ├── query.sql # SQL query (for sql-type endpoints)
│ ├── main.js # JavaScript script (for script-type endpoints)
│ ├── main.py # Python script (for script-type endpoints)
│ ├── request.http # HTTP request definition (for AQL-type endpoints)
│ └── queries/ # named queries used by scripts
│ ├── _index.json # query index (name → file, database binding)
│ ├── get_users.sql # SQL query file
│ └── get_data.http # AQL/HTTP query file
\`\`\`
## Script Execution Model
Scripts in \`main.js\` / \`main.py\` are NOT standalone programs.
They run inside an API Builder sandbox with pre-injected globals.
### IMPORTANT: Do NOT wrap code in functions
WRONG:
\`\`\`js
function main() {
const result = await execQuery('get_users');
return result.data;
}
main();
\`\`\`
CORRECT — write code directly at the top level:
\`\`\`js
const result = await execQuery('get_users');
return result.data;
\`\`\`
The server wraps the code in \`(async function() { <your code> })()\` automatically.
A top-level \`return\` statement sets the API response body.
### Available Globals (JavaScript)
| Global | Description |
|---|---|
| \`params\` | Object with request parameters (query string + body). Example: \`params.user_id\` |
| \`execQuery(name, extraParams?)\` | Execute a named query from the \`queries/\` folder. Returns \`{ success, data, rowCount, error }\` |
| \`console.log/warn/error/info\` | Captured logs, visible in API Builder UI |
| \`JSON, Date, Math, Array, Object, String, Number, Boolean, RegExp, Map, Set, Promise\` | Standard JS built-ins |
| \`setTimeout(fn, ms)\` | Capped at 30 seconds |
| \`parseInt, parseFloat, isNaN, isFinite\` | Standard utility functions |
| \`encodeURIComponent, decodeURIComponent, encodeURI, decodeURI\` | URL encoding |
No \`require\`, \`import\`, \`fetch\`, \`fs\`, \`process\`, or \`Buffer\` — the sandbox is isolated.
### Available Globals (Python)
| Global | Description |
|---|---|
| \`params\` | Dict with request parameters. Example: \`params["user_id"]\` |
| \`exec_query(name, additional_params=None)\` | Execute a named query. Returns dict \`{ "success", "data", "rowCount", "error" }\` |
| \`json, sys, datetime\` | Pre-imported standard modules |
Use \`return\` to set the response. The code is wrapped in a function automatically.
### execQuery / exec_query Explained
The function \`execQuery\` (JS) or \`exec_query\` (Python) runs a query defined in the \`queries/\` folder.
Each query file is mapped via \`queries/_index.json\`:
\`\`\`json
[
{
"name": "get_users",
"database_id": "abc-123",
"file": "get_users.sql"
},
{
"name": "get_data",
"database_id": "def-456",
"file": "get_data.http",
"type": "aql"
}
]
\`\`\`
**The \`name\` field is the key** — it's what you pass to \`execQuery("get_users")\`.
The \`file\` field is the corresponding SQL or HTTP file in the \`queries/\` directory.
SQL queries use \`$paramName\` placeholders that auto-bind from \`params\`:
\`\`\`sql
SELECT * FROM users WHERE id = $user_id AND status = $status
\`\`\`
You can also pass extra params:
\`\`\`js
const result = await execQuery('get_users', { status: 'active' });
// result.data — array of rows
// result.success — boolean
// result.rowCount — number of rows
\`\`\`
### AQL (HTTP) Queries
\`.http\` files define HTTP requests to external APIs:
\`\`\`http
POST https://example.com/api/patients
Content-Type: application/json
{
"name": "{{name}}",
"age": {{age}}
}
\`\`\`
### endpoint.json Fields
| Field | Description |
|---|---|
| \`id\` | Server-side UUID — do not change |
| \`name\` | Display name of the endpoint |
| \`method\` | HTTP method: GET, POST, PUT, DELETE |
| \`path\` | URL path, e.g. \`/api/users\` |
| \`execution_type\` | \`"sql"\`, \`"script"\`, or \`"aql"\` |
| \`parameters\` | Array of \`{ name, type, required, default_value, description }\` |
| \`database_name\` | Bound database name (for sql-type) |
| \`database_id\` | Bound database UUID |
| \`updated_at\` | Last server update timestamp — do not change |
## Sync Workflow
\`\`\`bash
kisync pull # download from server → local files
# ... edit files ...
kisync status # see what changed locally and on server
kisync push # upload changes (with conflict detection)
\`\`\`
Conflict detection: if someone else modified an endpoint on the server since your
last pull, \`push\` will warn you. Use \`--force\` to overwrite, or \`pull\` first to merge.
`;
fs.writeFileSync(contextPath, content, 'utf-8');
}