kontexted 0.1.5
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.
- package/README.md +75 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +48 -0
- package/dist/commands/logout.d.ts +5 -0
- package/dist/commands/logout.js +33 -0
- package/dist/commands/mcp.d.ts +15 -0
- package/dist/commands/mcp.js +65 -0
- package/dist/commands/server/doctor.d.ts +4 -0
- package/dist/commands/server/doctor.js +33 -0
- package/dist/commands/server/index.d.ts +6 -0
- package/dist/commands/server/index.js +125 -0
- package/dist/commands/server/init.d.ts +6 -0
- package/dist/commands/server/init.js +112 -0
- package/dist/commands/server/logs.d.ts +7 -0
- package/dist/commands/server/logs.js +39 -0
- package/dist/commands/server/migrate.d.ts +4 -0
- package/dist/commands/server/migrate.js +29 -0
- package/dist/commands/server/show-invite.d.ts +4 -0
- package/dist/commands/server/show-invite.js +29 -0
- package/dist/commands/server/start.d.ts +6 -0
- package/dist/commands/server/start.js +44 -0
- package/dist/commands/server/status.d.ts +4 -0
- package/dist/commands/server/status.js +23 -0
- package/dist/commands/server/stop.d.ts +6 -0
- package/dist/commands/server/stop.js +32 -0
- package/dist/commands/show-config.d.ts +5 -0
- package/dist/commands/show-config.js +19 -0
- package/dist/commands/skill.d.ts +5 -0
- package/dist/commands/skill.js +211 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +25 -0
- package/dist/lib/api-client.d.ts +36 -0
- package/dist/lib/api-client.js +130 -0
- package/dist/lib/config.d.ts +17 -0
- package/dist/lib/config.js +46 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.js +6 -0
- package/dist/lib/logger.d.ts +24 -0
- package/dist/lib/logger.js +76 -0
- package/dist/lib/mcp-client.d.ts +14 -0
- package/dist/lib/mcp-client.js +62 -0
- package/dist/lib/oauth.d.ts +42 -0
- package/dist/lib/oauth.js +383 -0
- package/dist/lib/profile.d.ts +37 -0
- package/dist/lib/profile.js +49 -0
- package/dist/lib/proxy-server.d.ts +12 -0
- package/dist/lib/proxy-server.js +131 -0
- package/dist/lib/server/binary.d.ts +32 -0
- package/dist/lib/server/binary.js +127 -0
- package/dist/lib/server/config.d.ts +57 -0
- package/dist/lib/server/config.js +136 -0
- package/dist/lib/server/constants.d.ts +29 -0
- package/dist/lib/server/constants.js +35 -0
- package/dist/lib/server/daemon.d.ts +34 -0
- package/dist/lib/server/daemon.js +199 -0
- package/dist/lib/server/index.d.ts +5 -0
- package/dist/lib/server/index.js +5 -0
- package/dist/lib/server/migrate.d.ts +9 -0
- package/dist/lib/server/migrate.js +51 -0
- package/dist/lib/server-url.d.ts +8 -0
- package/dist/lib/server-url.js +25 -0
- package/dist/skill-init/index.d.ts +3 -0
- package/dist/skill-init/index.js +3 -0
- package/dist/skill-init/providers/base.d.ts +26 -0
- package/dist/skill-init/providers/base.js +1 -0
- package/dist/skill-init/providers/index.d.ts +13 -0
- package/dist/skill-init/providers/index.js +17 -0
- package/dist/skill-init/providers/opencode.d.ts +5 -0
- package/dist/skill-init/providers/opencode.js +48 -0
- package/dist/skill-init/templates/index.d.ts +3 -0
- package/dist/skill-init/templates/index.js +3 -0
- package/dist/skill-init/templates/kontexted-cli.d.ts +2 -0
- package/dist/skill-init/templates/kontexted-cli.js +169 -0
- package/dist/skill-init/utils.d.ts +66 -0
- package/dist/skill-init/utils.js +122 -0
- package/dist/types/index.d.ts +67 -0
- package/dist/types/index.js +4 -0
- package/package.json +50 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { logError } from "../lib/logger.js";
|
|
5
|
+
// Tools that modify data
|
|
6
|
+
const WRITE_TOOLS = new Set(["createFolder", "createNote", "updateNote", "deleteNote", "deleteFolder"]);
|
|
7
|
+
/**
|
|
8
|
+
* Convert JSON schema to Zod schema, removing workspaceSlug
|
|
9
|
+
*/
|
|
10
|
+
function jsonSchemaToZod(jsonSchema) {
|
|
11
|
+
if (!jsonSchema || typeof jsonSchema !== "object") {
|
|
12
|
+
return z.object({});
|
|
13
|
+
}
|
|
14
|
+
const properties = jsonSchema.properties ?? {};
|
|
15
|
+
const required = new Set(jsonSchema.required ?? []);
|
|
16
|
+
// Remove workspaceSlug as it's injected by the proxy
|
|
17
|
+
const { workspaceSlug, ...otherProperties } = properties;
|
|
18
|
+
const shape = {};
|
|
19
|
+
for (const [key, propSchema] of Object.entries(otherProperties)) {
|
|
20
|
+
const type = propSchema?.type;
|
|
21
|
+
if (type === "string") {
|
|
22
|
+
let zodType = z.string();
|
|
23
|
+
if (propSchema.minLength === 1) {
|
|
24
|
+
zodType = zodType.min(1);
|
|
25
|
+
}
|
|
26
|
+
shape[key] = zodType;
|
|
27
|
+
}
|
|
28
|
+
else if (type === "integer") {
|
|
29
|
+
let zodType = z.number().int();
|
|
30
|
+
if (propSchema.exclusiveMinimum === 0) {
|
|
31
|
+
zodType = zodType.positive();
|
|
32
|
+
}
|
|
33
|
+
if (propSchema.minimum !== undefined) {
|
|
34
|
+
zodType = zodType.min(propSchema.minimum);
|
|
35
|
+
}
|
|
36
|
+
if (propSchema.maximum !== undefined) {
|
|
37
|
+
zodType = zodType.max(propSchema.maximum);
|
|
38
|
+
}
|
|
39
|
+
shape[key] = zodType;
|
|
40
|
+
}
|
|
41
|
+
else if (type === "number") {
|
|
42
|
+
let zodType = z.number();
|
|
43
|
+
if (propSchema.minimum !== undefined) {
|
|
44
|
+
zodType = zodType.min(propSchema.minimum);
|
|
45
|
+
}
|
|
46
|
+
if (propSchema.maximum !== undefined) {
|
|
47
|
+
zodType = zodType.max(propSchema.maximum);
|
|
48
|
+
}
|
|
49
|
+
shape[key] = zodType;
|
|
50
|
+
}
|
|
51
|
+
else if (type === "boolean") {
|
|
52
|
+
shape[key] = z.boolean();
|
|
53
|
+
}
|
|
54
|
+
else if (type === "array") {
|
|
55
|
+
shape[key] = z.array(z.any());
|
|
56
|
+
}
|
|
57
|
+
else if (type === "object") {
|
|
58
|
+
shape[key] = z.record(z.any());
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
shape[key] = z.any();
|
|
62
|
+
}
|
|
63
|
+
// Make optional if not in required list
|
|
64
|
+
if (!required.has(key)) {
|
|
65
|
+
shape[key] = shape[key].optional();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return z.object(shape);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Start the MCP proxy server that bridges stdio to HTTP
|
|
72
|
+
*/
|
|
73
|
+
export async function startProxyServer(options) {
|
|
74
|
+
const { client, workspaceSlug, tools, writeEnabled } = options;
|
|
75
|
+
const server = new McpServer({
|
|
76
|
+
name: "kontexted-proxy",
|
|
77
|
+
version: "0.1.0",
|
|
78
|
+
});
|
|
79
|
+
// Filter and register tools
|
|
80
|
+
const filteredTools = tools.filter((tool) => {
|
|
81
|
+
if (writeEnabled) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
return !WRITE_TOOLS.has(tool.name);
|
|
85
|
+
});
|
|
86
|
+
for (const tool of filteredTools) {
|
|
87
|
+
const inputSchema = jsonSchemaToZod(tool.inputSchema ?? {});
|
|
88
|
+
server.registerTool(tool.name, {
|
|
89
|
+
title: tool.title ?? tool.name,
|
|
90
|
+
description: tool.description ?? "",
|
|
91
|
+
inputSchema,
|
|
92
|
+
}, async (args) => {
|
|
93
|
+
// Inject workspaceSlug into arguments
|
|
94
|
+
const finalArgs = {
|
|
95
|
+
workspaceSlug,
|
|
96
|
+
...(args ?? {}),
|
|
97
|
+
};
|
|
98
|
+
const result = await client.callTool({
|
|
99
|
+
name: tool.name,
|
|
100
|
+
arguments: finalArgs,
|
|
101
|
+
});
|
|
102
|
+
// Convert old format (toolResult) to new format (content) if needed
|
|
103
|
+
if ("toolResult" in result) {
|
|
104
|
+
return {
|
|
105
|
+
content: [
|
|
106
|
+
{
|
|
107
|
+
type: "text",
|
|
108
|
+
text: JSON.stringify(result.toolResult),
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
_meta: result._meta,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
return result;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const transport = new StdioServerTransport();
|
|
118
|
+
await server.connect(transport);
|
|
119
|
+
logError(`Proxy server started with ${filteredTools.length} tools (${writeEnabled ? "write enabled" : "read-only"})`);
|
|
120
|
+
// Handle graceful shutdown
|
|
121
|
+
process.on("SIGINT", async () => {
|
|
122
|
+
await client.close();
|
|
123
|
+
await server.close();
|
|
124
|
+
process.exit(0);
|
|
125
|
+
});
|
|
126
|
+
process.on("SIGTERM", async () => {
|
|
127
|
+
await client.close();
|
|
128
|
+
await server.close();
|
|
129
|
+
process.exit(0);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gets the current platform identifier (e.g., "darwin-arm64")
|
|
3
|
+
*/
|
|
4
|
+
export declare function getPlatform(): string;
|
|
5
|
+
/**
|
|
6
|
+
* Checks if the current platform is supported
|
|
7
|
+
*/
|
|
8
|
+
export declare function isPlatformSupported(): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Gets the package name for the current platform
|
|
11
|
+
*/
|
|
12
|
+
export declare function getPlatformPackage(): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Resolves the path to the server binary
|
|
15
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
16
|
+
*/
|
|
17
|
+
export declare function getBinaryPath(): string | null;
|
|
18
|
+
/**
|
|
19
|
+
* Resolves the path to the migration tool binary
|
|
20
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
21
|
+
*/
|
|
22
|
+
export declare function getMigratePath(): string | null;
|
|
23
|
+
/**
|
|
24
|
+
* Resolves the path to the migrations directory
|
|
25
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
26
|
+
*/
|
|
27
|
+
export declare function getMigrationsDir(): string | null;
|
|
28
|
+
/**
|
|
29
|
+
* Resolves the path to the public directory (frontend assets)
|
|
30
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
31
|
+
*/
|
|
32
|
+
export declare function getPublicDir(): string | null;
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { createRequire } from 'module';
|
|
2
|
+
import { existsSync } from 'fs';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { PLATFORM_PACKAGES } from './constants.js';
|
|
5
|
+
/**
|
|
6
|
+
* Gets the current platform identifier (e.g., "darwin-arm64")
|
|
7
|
+
*/
|
|
8
|
+
export function getPlatform() {
|
|
9
|
+
return `${process.platform}-${process.arch}`;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Checks if the current platform is supported
|
|
13
|
+
*/
|
|
14
|
+
export function isPlatformSupported() {
|
|
15
|
+
const platform = getPlatform();
|
|
16
|
+
return platform in PLATFORM_PACKAGES;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Gets the package name for the current platform
|
|
20
|
+
*/
|
|
21
|
+
export function getPlatformPackage() {
|
|
22
|
+
const platform = getPlatform();
|
|
23
|
+
return PLATFORM_PACKAGES[platform] || null;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Resolves the path to the server binary
|
|
27
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
28
|
+
*/
|
|
29
|
+
export function getBinaryPath() {
|
|
30
|
+
if (!isPlatformSupported()) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const pkg = getPlatformPackage();
|
|
34
|
+
if (!pkg) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
// Use createRequire to resolve the package location
|
|
39
|
+
const require = createRequire(import.meta.url);
|
|
40
|
+
const packagePath = require.resolve(`${pkg}/package.json`);
|
|
41
|
+
const binaryName = process.platform === 'win32' ? 'kontexted.exe' : 'kontexted';
|
|
42
|
+
const binPath = join(packagePath, '..', 'bin', binaryName);
|
|
43
|
+
if (existsSync(binPath)) {
|
|
44
|
+
return binPath;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Resolves the path to the migration tool binary
|
|
54
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
55
|
+
*/
|
|
56
|
+
export function getMigratePath() {
|
|
57
|
+
if (!isPlatformSupported()) {
|
|
58
|
+
return null;
|
|
59
|
+
}
|
|
60
|
+
const pkg = getPlatformPackage();
|
|
61
|
+
if (!pkg) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const require = createRequire(import.meta.url);
|
|
66
|
+
const packagePath = require.resolve(`${pkg}/package.json`);
|
|
67
|
+
const binaryName = process.platform === 'win32' ? 'kontexted-migrate.exe' : 'kontexted-migrate';
|
|
68
|
+
const migratePath = join(packagePath, '..', 'bin', binaryName);
|
|
69
|
+
if (existsSync(migratePath)) {
|
|
70
|
+
return migratePath;
|
|
71
|
+
}
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Resolves the path to the migrations directory
|
|
80
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
81
|
+
*/
|
|
82
|
+
export function getMigrationsDir() {
|
|
83
|
+
if (!isPlatformSupported()) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const pkg = getPlatformPackage();
|
|
87
|
+
if (!pkg) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const require = createRequire(import.meta.url);
|
|
92
|
+
const packagePath = require.resolve(`${pkg}/package.json`);
|
|
93
|
+
const migrationsDir = join(packagePath, '..', 'migrations');
|
|
94
|
+
if (existsSync(migrationsDir)) {
|
|
95
|
+
return migrationsDir;
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resolves the path to the public directory (frontend assets)
|
|
105
|
+
* Returns null if the package is not installed or platform is unsupported
|
|
106
|
+
*/
|
|
107
|
+
export function getPublicDir() {
|
|
108
|
+
if (!isPlatformSupported()) {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
const pkg = getPlatformPackage();
|
|
112
|
+
if (!pkg) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
try {
|
|
116
|
+
const require = createRequire(import.meta.url);
|
|
117
|
+
const packagePath = require.resolve(`${pkg}/package.json`);
|
|
118
|
+
const publicDir = join(packagePath, '..', 'public');
|
|
119
|
+
if (existsSync(publicDir)) {
|
|
120
|
+
return publicDir;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server configuration interface
|
|
3
|
+
*/
|
|
4
|
+
export interface ServerConfig {
|
|
5
|
+
database: {
|
|
6
|
+
dialect: 'sqlite' | 'postgresql';
|
|
7
|
+
url: string;
|
|
8
|
+
};
|
|
9
|
+
server: {
|
|
10
|
+
port: number;
|
|
11
|
+
host: string;
|
|
12
|
+
};
|
|
13
|
+
logging: {
|
|
14
|
+
level: 'debug' | 'info' | 'warn' | 'error';
|
|
15
|
+
};
|
|
16
|
+
collab: {
|
|
17
|
+
tokenSecret: string;
|
|
18
|
+
};
|
|
19
|
+
auth: {
|
|
20
|
+
betterAuthSecret: string;
|
|
21
|
+
inviteCode: string;
|
|
22
|
+
};
|
|
23
|
+
paths?: {
|
|
24
|
+
publicDir?: string;
|
|
25
|
+
migrationsDir?: string;
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generates a secure random token secret (32 bytes as hex string)
|
|
30
|
+
*/
|
|
31
|
+
export declare function generateTokenSecret(): string;
|
|
32
|
+
/**
|
|
33
|
+
* Generates a secure random auth secret (32 bytes as hex string)
|
|
34
|
+
*/
|
|
35
|
+
export declare function generateBetterAuthSecret(): string;
|
|
36
|
+
/**
|
|
37
|
+
* Generates a readable invite code (16 alphanumeric chars, lowercase, no ambiguous chars)
|
|
38
|
+
*/
|
|
39
|
+
export declare function generateInviteCode(): string;
|
|
40
|
+
/**
|
|
41
|
+
* Returns the default server configuration
|
|
42
|
+
*/
|
|
43
|
+
export declare function getDefaultConfig(): ServerConfig;
|
|
44
|
+
/**
|
|
45
|
+
* Checks if the configuration file exists
|
|
46
|
+
*/
|
|
47
|
+
export declare function configExists(): boolean;
|
|
48
|
+
/**
|
|
49
|
+
* Loads the server configuration from file
|
|
50
|
+
* Returns null if the config file doesn't exist or is invalid
|
|
51
|
+
*/
|
|
52
|
+
export declare function loadConfig(): ServerConfig | null;
|
|
53
|
+
/**
|
|
54
|
+
* Saves the server configuration to file
|
|
55
|
+
* Creates the directory if it doesn't exist
|
|
56
|
+
*/
|
|
57
|
+
export declare function saveConfig(config: ServerConfig): void;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
2
|
+
import { dirname } from 'path';
|
|
3
|
+
import { randomBytes } from 'crypto';
|
|
4
|
+
import { CONFIG_FILE, DATA_DIR, } from './constants.js';
|
|
5
|
+
import { getMigrationsDir, getPublicDir } from './binary.js';
|
|
6
|
+
/**
|
|
7
|
+
* Generates a secure random token secret (32 bytes as hex string)
|
|
8
|
+
*/
|
|
9
|
+
export function generateTokenSecret() {
|
|
10
|
+
return randomBytes(32).toString('hex');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Generates a secure random auth secret (32 bytes as hex string)
|
|
14
|
+
*/
|
|
15
|
+
export function generateBetterAuthSecret() {
|
|
16
|
+
return randomBytes(32).toString('hex');
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Generates a readable invite code (16 alphanumeric chars, lowercase, no ambiguous chars)
|
|
20
|
+
*/
|
|
21
|
+
export function generateInviteCode() {
|
|
22
|
+
// Use lowercase letters and digits, excluding: 0, o, 1, l (ambiguous)
|
|
23
|
+
const chars = 'abcdefghijkmnpqrstuvwxyz23456789';
|
|
24
|
+
let code = '';
|
|
25
|
+
for (let i = 0; i < 16; i++) {
|
|
26
|
+
code += chars[randomBytes(1)[0] % chars.length];
|
|
27
|
+
}
|
|
28
|
+
return code;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns the default server configuration
|
|
32
|
+
*/
|
|
33
|
+
export function getDefaultConfig() {
|
|
34
|
+
const migrationsDir = getMigrationsDir();
|
|
35
|
+
const publicDir = getPublicDir();
|
|
36
|
+
const config = {
|
|
37
|
+
database: {
|
|
38
|
+
dialect: 'sqlite',
|
|
39
|
+
url: `${DATA_DIR}/kontexted.db`,
|
|
40
|
+
},
|
|
41
|
+
server: {
|
|
42
|
+
port: 3000,
|
|
43
|
+
host: '127.0.0.1',
|
|
44
|
+
},
|
|
45
|
+
logging: {
|
|
46
|
+
level: 'info',
|
|
47
|
+
},
|
|
48
|
+
collab: {
|
|
49
|
+
tokenSecret: generateTokenSecret(),
|
|
50
|
+
},
|
|
51
|
+
auth: {
|
|
52
|
+
betterAuthSecret: generateBetterAuthSecret(),
|
|
53
|
+
inviteCode: generateInviteCode(),
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
// Add paths if platform package is available
|
|
57
|
+
if (migrationsDir || publicDir) {
|
|
58
|
+
config.paths = {
|
|
59
|
+
migrationsDir: migrationsDir || undefined,
|
|
60
|
+
publicDir: publicDir || undefined,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
return config;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Checks if the configuration file exists
|
|
67
|
+
*/
|
|
68
|
+
export function configExists() {
|
|
69
|
+
return existsSync(CONFIG_FILE);
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Loads the server configuration from file
|
|
73
|
+
* Returns null if the config file doesn't exist or is invalid
|
|
74
|
+
*/
|
|
75
|
+
export function loadConfig() {
|
|
76
|
+
if (!configExists()) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
const content = readFileSync(CONFIG_FILE, 'utf-8');
|
|
81
|
+
const parsed = JSON.parse(content);
|
|
82
|
+
// Basic validation
|
|
83
|
+
if (!parsed.server || !parsed.database) {
|
|
84
|
+
console.warn('Config file missing required fields, using defaults');
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
const tokenSecret = parsed.collab?.tokenSecret;
|
|
88
|
+
const betterAuthSecret = parsed.auth?.betterAuthSecret;
|
|
89
|
+
const inviteCode = parsed.auth?.inviteCode;
|
|
90
|
+
return {
|
|
91
|
+
database: {
|
|
92
|
+
dialect: parsed.database.dialect || 'sqlite',
|
|
93
|
+
url: parsed.database.url,
|
|
94
|
+
},
|
|
95
|
+
server: {
|
|
96
|
+
port: parsed.server.port || 3000,
|
|
97
|
+
host: parsed.server.host || '127.0.0.1',
|
|
98
|
+
},
|
|
99
|
+
logging: {
|
|
100
|
+
level: parsed.logging?.level || 'info',
|
|
101
|
+
},
|
|
102
|
+
collab: {
|
|
103
|
+
tokenSecret: tokenSecret || generateTokenSecret(),
|
|
104
|
+
},
|
|
105
|
+
auth: {
|
|
106
|
+
betterAuthSecret: betterAuthSecret || generateBetterAuthSecret(),
|
|
107
|
+
inviteCode: inviteCode || generateInviteCode(),
|
|
108
|
+
},
|
|
109
|
+
paths: {
|
|
110
|
+
publicDir: parsed.paths?.publicDir,
|
|
111
|
+
migrationsDir: parsed.paths?.migrationsDir,
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.warn('Failed to load config file:', error instanceof Error ? error.message : 'Unknown error');
|
|
117
|
+
return null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Saves the server configuration to file
|
|
122
|
+
* Creates the directory if it doesn't exist
|
|
123
|
+
*/
|
|
124
|
+
export function saveConfig(config) {
|
|
125
|
+
// Ensure the config directory exists
|
|
126
|
+
const configDir = dirname(CONFIG_FILE);
|
|
127
|
+
if (!existsSync(configDir)) {
|
|
128
|
+
mkdirSync(configDir, { recursive: true });
|
|
129
|
+
}
|
|
130
|
+
// Ensure the data directory exists
|
|
131
|
+
if (!existsSync(DATA_DIR)) {
|
|
132
|
+
mkdirSync(DATA_DIR, { recursive: true });
|
|
133
|
+
}
|
|
134
|
+
const content = JSON.stringify(config, null, 2);
|
|
135
|
+
writeFileSync(CONFIG_FILE, content, 'utf-8');
|
|
136
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base Kontexted directory in user's home
|
|
3
|
+
*/
|
|
4
|
+
export declare const KONTEXTED_DIR: string;
|
|
5
|
+
/**
|
|
6
|
+
* Path to the configuration file
|
|
7
|
+
*/
|
|
8
|
+
export declare const CONFIG_FILE: string;
|
|
9
|
+
/**
|
|
10
|
+
* Directory for data storage (databases, etc.)
|
|
11
|
+
*/
|
|
12
|
+
export declare const DATA_DIR: string;
|
|
13
|
+
/**
|
|
14
|
+
* Directory for log files
|
|
15
|
+
*/
|
|
16
|
+
export declare const LOGS_DIR: string;
|
|
17
|
+
/**
|
|
18
|
+
* Main server log file path
|
|
19
|
+
*/
|
|
20
|
+
export declare const LOG_FILE: string;
|
|
21
|
+
/**
|
|
22
|
+
* PID file for tracking the running server process
|
|
23
|
+
*/
|
|
24
|
+
export declare const PID_FILE: string;
|
|
25
|
+
/**
|
|
26
|
+
* Platform-specific package mapping
|
|
27
|
+
* Maps platform identifiers to their corresponding npm packages
|
|
28
|
+
*/
|
|
29
|
+
export declare const PLATFORM_PACKAGES: Record<string, string>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
/**
|
|
4
|
+
* Base Kontexted directory in user's home
|
|
5
|
+
*/
|
|
6
|
+
export const KONTEXTED_DIR = join(homedir(), '.kontexted');
|
|
7
|
+
/**
|
|
8
|
+
* Path to the configuration file
|
|
9
|
+
*/
|
|
10
|
+
export const CONFIG_FILE = join(KONTEXTED_DIR, 'config.json');
|
|
11
|
+
/**
|
|
12
|
+
* Directory for data storage (databases, etc.)
|
|
13
|
+
*/
|
|
14
|
+
export const DATA_DIR = join(KONTEXTED_DIR, 'data');
|
|
15
|
+
/**
|
|
16
|
+
* Directory for log files
|
|
17
|
+
*/
|
|
18
|
+
export const LOGS_DIR = join(KONTEXTED_DIR, 'logs');
|
|
19
|
+
/**
|
|
20
|
+
* Main server log file path
|
|
21
|
+
*/
|
|
22
|
+
export const LOG_FILE = join(LOGS_DIR, 'server.log');
|
|
23
|
+
/**
|
|
24
|
+
* PID file for tracking the running server process
|
|
25
|
+
*/
|
|
26
|
+
export const PID_FILE = join(KONTEXTED_DIR, 'server.pid');
|
|
27
|
+
/**
|
|
28
|
+
* Platform-specific package mapping
|
|
29
|
+
* Maps platform identifiers to their corresponding npm packages
|
|
30
|
+
*/
|
|
31
|
+
export const PLATFORM_PACKAGES = {
|
|
32
|
+
'darwin-arm64': '@kontexted/darwin-arm64',
|
|
33
|
+
'linux-x64': '@kontexted/linux-x64',
|
|
34
|
+
'win32-x64': '@kontexted/windows-x64',
|
|
35
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads the PID from the PID file
|
|
3
|
+
* Returns null if the file doesn't exist
|
|
4
|
+
*/
|
|
5
|
+
export declare function getPid(): number | null;
|
|
6
|
+
/**
|
|
7
|
+
* Checks if a process with the given PID is running
|
|
8
|
+
* Uses signal 0 to check process existence without actually sending a signal
|
|
9
|
+
*/
|
|
10
|
+
export declare function isRunning(pid: number): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Starts the server
|
|
13
|
+
* @param options.foreground - If true, runs in foreground (blocks). If false, runs as daemon
|
|
14
|
+
* @returns The PID of the started server
|
|
15
|
+
*/
|
|
16
|
+
export declare function startServer(options?: {
|
|
17
|
+
foreground?: boolean;
|
|
18
|
+
}): Promise<number>;
|
|
19
|
+
/**
|
|
20
|
+
* Stops the server
|
|
21
|
+
* @param options.force - If true, uses SIGKILL instead of SIGTERM
|
|
22
|
+
* @returns True if the server was stopped, false if it wasn't running
|
|
23
|
+
*/
|
|
24
|
+
export declare function stopServer(options?: {
|
|
25
|
+
force?: boolean;
|
|
26
|
+
}): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* Gets the current server status
|
|
29
|
+
*/
|
|
30
|
+
export declare function getServerStatus(): {
|
|
31
|
+
running: boolean;
|
|
32
|
+
pid?: number;
|
|
33
|
+
startedAt?: Date;
|
|
34
|
+
};
|