kubun 0.7.1 → 0.8.1
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 +13 -11
- package/dist/commands/graphql/schema.js +6 -2
- package/dist/commands/mcp.js +1 -1
- package/dist/commands/serve.js +88 -21
- package/oclif.manifest.json +17 -1
- package/package.json +23 -17
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g kubun
|
|
|
20
20
|
$ kubun COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ kubun (--version)
|
|
23
|
-
kubun/0.
|
|
23
|
+
kubun/0.8.1 darwin-arm64 node-v24.15.0
|
|
24
24
|
$ kubun --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ kubun COMMAND
|
|
@@ -163,7 +163,7 @@ DESCRIPTION
|
|
|
163
163
|
Display help for kubun.
|
|
164
164
|
```
|
|
165
165
|
|
|
166
|
-
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/
|
|
166
|
+
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/6.2.44/src/commands/help.ts)_
|
|
167
167
|
|
|
168
168
|
## `kubun mcp`
|
|
169
169
|
|
|
@@ -227,17 +227,19 @@ Start a local Kubun server
|
|
|
227
227
|
|
|
228
228
|
```
|
|
229
229
|
USAGE
|
|
230
|
-
$ kubun serve [-a <value>] [--
|
|
231
|
-
<value> | --id <value>]
|
|
230
|
+
$ kubun serve [-a <value>] [--autoAcceptPeers <value> --p2p] [--db <value>] [-l
|
|
231
|
+
trace|debug|info|warning|error|fatal] [-p <value>] [-k <value> | --id <value>]
|
|
232
232
|
|
|
233
233
|
FLAGS
|
|
234
|
-
-a, --allowedOrigin=<value>
|
|
235
|
-
-k, --privateKey=<value>
|
|
236
|
-
-l, --logLevel=<option>
|
|
237
|
-
|
|
238
|
-
-p, --port=<value>
|
|
239
|
-
--
|
|
240
|
-
--
|
|
234
|
+
-a, --allowedOrigin=<value> [default: *, env: KUBUN_ALLOWED_ORIGIN] allowed HTTP origin
|
|
235
|
+
-k, --privateKey=<value> [env: KUBUN_PRIVATE_KEY] base64-encoded private key
|
|
236
|
+
-l, --logLevel=<option> [default: warning] log level
|
|
237
|
+
<options: trace|debug|info|warning|error|fatal>
|
|
238
|
+
-p, --port=<value> port to listen on
|
|
239
|
+
--autoAcceptPeers=<value> comma-separated DIDs to auto-accept for peer join flows
|
|
240
|
+
--db=<value> path to the local SQLite database
|
|
241
|
+
--id=<value> server ID
|
|
242
|
+
--p2p enable P2P mode with sync and graph protocols over HTTP
|
|
241
243
|
|
|
242
244
|
DESCRIPTION
|
|
243
245
|
Start a local Kubun server
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { createSchema } from '@kubun/graphql';
|
|
2
|
-
import { GraphModel } from '@kubun/protocol';
|
|
2
|
+
import { clusterToRecord, GraphModel, } from '@kubun/protocol';
|
|
3
3
|
import { Command, Flags } from '@oclif/core';
|
|
4
4
|
import { printSchema } from 'graphql';
|
|
5
5
|
import ora from 'ora';
|
|
@@ -21,7 +21,11 @@ export default class CreateGraphQLSchema extends Command {
|
|
|
21
21
|
async run() {
|
|
22
22
|
const spinner = ora('Loading clusters...').start();
|
|
23
23
|
const { flags } = await this.parse(CreateGraphQLSchema);
|
|
24
|
-
const
|
|
24
|
+
const clusterModels = await Promise.all(flags.cluster.map((path) => readJSON(path)));
|
|
25
|
+
const clusters = {};
|
|
26
|
+
for (const cluster of clusterModels) {
|
|
27
|
+
Object.assign(clusters, clusterToRecord(cluster));
|
|
28
|
+
}
|
|
25
29
|
const model = GraphModel.fromClusters({ clusters });
|
|
26
30
|
const schema = printSchema(createSchema(model));
|
|
27
31
|
if (flags.output == null) {
|
package/dist/commands/mcp.js
CHANGED
|
@@ -23,7 +23,7 @@ export default class MCP extends Command {
|
|
|
23
23
|
};
|
|
24
24
|
async run() {
|
|
25
25
|
const { flags } = await this.parse(MCP);
|
|
26
|
-
const config = createConfig({
|
|
26
|
+
const config = await createConfig({
|
|
27
27
|
connect: flags.connect,
|
|
28
28
|
database: flags.db,
|
|
29
29
|
identity: flags.privateKey ? getSigner(flags.privateKey) : undefined,
|
package/dist/commands/serve.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { fromB64, toB64 } from '@enkaku/codec';
|
|
2
|
+
import { createFullIdentity, randomIdentity } from '@enkaku/token';
|
|
3
|
+
import { NodeSQLiteAdapter } from '@kubun/db-node-sqlite';
|
|
4
|
+
import { PostgresAdapter } from '@kubun/db-postgres';
|
|
5
|
+
import { KubunEngine } from '@kubun/engine';
|
|
6
|
+
import { getKubunLogger } from '@kubun/logger';
|
|
7
|
+
import { createHTTPPlugin } from '@kubun/plugin-http';
|
|
8
|
+
import { createP2PPlugin } from '@kubun/plugin-p2p';
|
|
9
|
+
import { createRPCPlugin } from '@kubun/plugin-rpc';
|
|
10
|
+
import { configureSync, getConsoleSink, getLogLevels } from '@logtape/logtape';
|
|
3
11
|
import { Command, Flags } from '@oclif/core';
|
|
4
12
|
import ora from 'ora';
|
|
5
13
|
import { resolvePath } from '../fs.js';
|
|
@@ -12,6 +20,10 @@ export default class Serve extends Command {
|
|
|
12
20
|
env: 'KUBUN_ALLOWED_ORIGIN',
|
|
13
21
|
default: '*',
|
|
14
22
|
}),
|
|
23
|
+
autoAcceptPeers: Flags.string({
|
|
24
|
+
description: 'comma-separated DIDs to auto-accept for peer join flows',
|
|
25
|
+
dependsOn: ['p2p'],
|
|
26
|
+
}),
|
|
15
27
|
db: Flags.file({ description: 'path to the local SQLite database' }),
|
|
16
28
|
id: Flags.string({ description: 'server ID' }),
|
|
17
29
|
logLevel: Flags.string({
|
|
@@ -20,6 +32,7 @@ export default class Serve extends Command {
|
|
|
20
32
|
options: getLogLevels(),
|
|
21
33
|
default: 'warning',
|
|
22
34
|
}),
|
|
35
|
+
p2p: Flags.boolean({ description: 'enable P2P mode with sync and graph protocols over HTTP' }),
|
|
23
36
|
port: Flags.integer({ char: 'p', description: 'port to listen on' }),
|
|
24
37
|
privateKey: Flags.string({
|
|
25
38
|
char: 'k',
|
|
@@ -32,28 +45,82 @@ export default class Serve extends Command {
|
|
|
32
45
|
const spinner = ora();
|
|
33
46
|
const { flags } = await this.parse(Serve);
|
|
34
47
|
spinner.start('Starting the server...');
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
48
|
+
// Configure logging
|
|
49
|
+
configureSync({
|
|
50
|
+
reset: true,
|
|
51
|
+
sinks: { console: getConsoleSink() },
|
|
52
|
+
loggers: [
|
|
53
|
+
{ category: ['logtape', 'meta'], lowestLevel: 'error', sinks: ['console'] },
|
|
54
|
+
{
|
|
55
|
+
category: ['kubun'],
|
|
56
|
+
lowestLevel: (flags.logLevel ?? 'warning'),
|
|
57
|
+
sinks: ['console'],
|
|
58
|
+
},
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
// Resolve identity
|
|
62
|
+
const logger = getKubunLogger('cli');
|
|
63
|
+
let identity;
|
|
42
64
|
if (flags.privateKey != null) {
|
|
43
|
-
|
|
65
|
+
const privateKey = fromB64(flags.privateKey);
|
|
66
|
+
identity = { ...createFullIdentity(privateKey), privateKey };
|
|
67
|
+
}
|
|
68
|
+
else if (flags.id != null) {
|
|
69
|
+
if (flags.p2p) {
|
|
70
|
+
this.error('P2P mode requires a signing identity. Use --private-key instead of --id.');
|
|
71
|
+
}
|
|
72
|
+
identity = { id: flags.id };
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
const generated = randomIdentity();
|
|
76
|
+
logger.warn('Generated random identity for server: {privateKey}, DID: {id}', {
|
|
77
|
+
id: generated.id,
|
|
78
|
+
privateKey: toB64(generated.privateKey),
|
|
79
|
+
});
|
|
80
|
+
identity = generated;
|
|
81
|
+
}
|
|
82
|
+
// Create DB adapter
|
|
83
|
+
const adapter = flags.db == null || flags.db === ':memory:'
|
|
84
|
+
? new NodeSQLiteAdapter({ database: ':memory:' })
|
|
85
|
+
: flags.db.startsWith('postgres://') || flags.db.startsWith('postgresql://')
|
|
86
|
+
? new PostgresAdapter({ url: flags.db })
|
|
87
|
+
: new NodeSQLiteAdapter({ database: resolvePath(flags.db) });
|
|
88
|
+
// Build plugin list
|
|
89
|
+
const autoAcceptPeers = flags.autoAcceptPeers
|
|
90
|
+
? flags.autoAcceptPeers.split(',').map((s) => s.trim())
|
|
91
|
+
: undefined;
|
|
92
|
+
const rpcAccessControl = autoAcceptPeers != null ? { '*': [identity.id, ...autoAcceptPeers] } : undefined;
|
|
93
|
+
const plugins = [
|
|
94
|
+
createRPCPlugin({
|
|
95
|
+
...(rpcAccessControl != null ? { accessControl: rpcAccessControl } : undefined),
|
|
96
|
+
allowDelegatedMutations: flags.p2p,
|
|
97
|
+
}),
|
|
98
|
+
createHTTPPlugin({ port: flags.port, allowedOrigin: flags.allowedOrigin }),
|
|
99
|
+
];
|
|
100
|
+
if (flags.p2p) {
|
|
101
|
+
plugins.push(createP2PPlugin({ http: true, autoAcceptPeers }));
|
|
44
102
|
}
|
|
45
|
-
|
|
46
|
-
|
|
103
|
+
// Create engine with plugins
|
|
104
|
+
const engine = new KubunEngine({
|
|
105
|
+
db: adapter,
|
|
106
|
+
identity,
|
|
107
|
+
plugins,
|
|
108
|
+
});
|
|
109
|
+
const http = await engine.getAPI('http');
|
|
110
|
+
await http.listening;
|
|
111
|
+
if (flags.p2p) {
|
|
112
|
+
const p2p = await engine.getAPI('p2p');
|
|
113
|
+
await p2p.syncReady;
|
|
47
114
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
? flags.db
|
|
52
|
-
: resolvePath(flags.db);
|
|
115
|
+
spinner.succeed(`HTTP server listening at ${http.getURL()}\n DID: ${identity.id}\n`);
|
|
116
|
+
if (flags.p2p && autoAcceptPeers) {
|
|
117
|
+
this.log(` Auto-accept peers: ${autoAcceptPeers.length} DID(s)`);
|
|
53
118
|
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
119
|
+
// Keep process alive until SIGINT/SIGTERM
|
|
120
|
+
await new Promise((resolve) => {
|
|
121
|
+
process.once('SIGINT', resolve);
|
|
122
|
+
process.once('SIGTERM', resolve);
|
|
123
|
+
});
|
|
124
|
+
await engine.dispose();
|
|
58
125
|
}
|
|
59
126
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -67,6 +67,16 @@
|
|
|
67
67
|
"multiple": false,
|
|
68
68
|
"type": "option"
|
|
69
69
|
},
|
|
70
|
+
"autoAcceptPeers": {
|
|
71
|
+
"dependsOn": [
|
|
72
|
+
"p2p"
|
|
73
|
+
],
|
|
74
|
+
"description": "comma-separated DIDs to auto-accept for peer join flows",
|
|
75
|
+
"name": "autoAcceptPeers",
|
|
76
|
+
"hasDynamicHelp": false,
|
|
77
|
+
"multiple": false,
|
|
78
|
+
"type": "option"
|
|
79
|
+
},
|
|
70
80
|
"db": {
|
|
71
81
|
"description": "path to the local SQLite database",
|
|
72
82
|
"name": "db",
|
|
@@ -98,6 +108,12 @@
|
|
|
98
108
|
],
|
|
99
109
|
"type": "option"
|
|
100
110
|
},
|
|
111
|
+
"p2p": {
|
|
112
|
+
"description": "enable P2P mode with sync and graph protocols over HTTP",
|
|
113
|
+
"name": "p2p",
|
|
114
|
+
"allowNo": false,
|
|
115
|
+
"type": "boolean"
|
|
116
|
+
},
|
|
101
117
|
"port": {
|
|
102
118
|
"char": "p",
|
|
103
119
|
"description": "port to listen on",
|
|
@@ -513,5 +529,5 @@
|
|
|
513
529
|
]
|
|
514
530
|
}
|
|
515
531
|
},
|
|
516
|
-
"version": "0.
|
|
532
|
+
"version": "0.8.1"
|
|
517
533
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kubun",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"license": "see LICENSE.md",
|
|
5
5
|
"description": "Kubun CLI",
|
|
6
6
|
"keywords": [],
|
|
@@ -29,32 +29,38 @@
|
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@enkaku/codec": "^0.14.0",
|
|
32
|
-
"@enkaku/token": "0.14.
|
|
33
|
-
"@logtape/logtape": "^2.0.
|
|
32
|
+
"@enkaku/token": "0.14.1",
|
|
33
|
+
"@logtape/logtape": "^2.0.5",
|
|
34
34
|
"@mokei/context-server": "^0.6.0",
|
|
35
|
-
"@oclif/core": "^4.
|
|
36
|
-
"@oclif/plugin-help": "^6.2.
|
|
37
|
-
"@oclif/plugin-plugins": "^5.4.
|
|
38
|
-
"graphql": "^16.13.
|
|
35
|
+
"@oclif/core": "^4.10.3",
|
|
36
|
+
"@oclif/plugin-help": "^6.2.44",
|
|
37
|
+
"@oclif/plugin-plugins": "^5.4.61",
|
|
38
|
+
"graphql": "^16.13.2",
|
|
39
39
|
"ora": "^9.3.0",
|
|
40
|
-
"@kubun/
|
|
41
|
-
"@kubun/
|
|
42
|
-
"@kubun/
|
|
43
|
-
"@kubun/
|
|
44
|
-
"@kubun/
|
|
45
|
-
"@kubun/
|
|
40
|
+
"@kubun/client": "^0.8.0",
|
|
41
|
+
"@kubun/db-postgres": "^0.8.1",
|
|
42
|
+
"@kubun/engine": "^0.8.1",
|
|
43
|
+
"@kubun/graphql": "^0.8.1",
|
|
44
|
+
"@kubun/db-node-sqlite": "^0.8.1",
|
|
45
|
+
"@kubun/logger": "^0.8.0",
|
|
46
|
+
"@kubun/http-client": "^0.8.0",
|
|
47
|
+
"@kubun/mcp": "^0.8.1",
|
|
48
|
+
"@kubun/plugin-rpc": "^0.8.1",
|
|
49
|
+
"@kubun/plugin-p2p": "^0.8.1",
|
|
50
|
+
"@kubun/protocol": "^0.8.0",
|
|
51
|
+
"@kubun/plugin-http": "^0.8.1"
|
|
46
52
|
},
|
|
47
53
|
"devDependencies": {
|
|
48
|
-
"@oclif/test": "^4.1.
|
|
49
|
-
"oclif": "^4.22.
|
|
54
|
+
"@oclif/test": "^4.1.17",
|
|
55
|
+
"oclif": "^4.22.96",
|
|
50
56
|
"ts-node": "^10",
|
|
51
|
-
"typescript": "^
|
|
57
|
+
"typescript": "^6.0.3"
|
|
52
58
|
},
|
|
53
59
|
"scripts": {
|
|
54
60
|
"kubun": "./bin/dev.js",
|
|
55
61
|
"build": "del dist && tsc -b",
|
|
56
62
|
"posttest": "pnpm run lint",
|
|
57
|
-
"test:types": "tsc --noEmit
|
|
63
|
+
"test:types": "tsc --noEmit",
|
|
58
64
|
"test:unit": "OCLIF_TEST_ROOT=. vitest run",
|
|
59
65
|
"test": "pnpm run test:types && pnpm run test:unit",
|
|
60
66
|
"version": "oclif readme && git add README.md"
|