kubun 0.9.0 → 0.11.0

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.
Files changed (47) hide show
  1. package/README.md +22 -234
  2. package/bin/dev.js +12 -4
  3. package/bin/run.js +11 -2
  4. package/lib/account.d.ts +2 -0
  5. package/lib/account.js +5 -0
  6. package/lib/client.d.ts +2 -0
  7. package/{dist → lib}/client.js +4 -1
  8. package/lib/commands/account.d.ts +2 -0
  9. package/lib/commands/account.js +24 -0
  10. package/lib/commands/graph.d.ts +2 -0
  11. package/lib/commands/graph.js +74 -0
  12. package/lib/commands/graphql.d.ts +2 -0
  13. package/lib/commands/graphql.js +33 -0
  14. package/lib/commands/mcp.d.ts +2 -0
  15. package/lib/commands/mcp.js +21 -0
  16. package/lib/commands/model.d.ts +2 -0
  17. package/lib/commands/model.js +69 -0
  18. package/lib/commands/serve.d.ts +2 -0
  19. package/lib/commands/serve.js +116 -0
  20. package/lib/fs.d.ts +4 -0
  21. package/{dist → lib}/fs.js +6 -2
  22. package/lib/identity.d.ts +19 -0
  23. package/lib/identity.js +31 -0
  24. package/lib/index.d.ts +3 -0
  25. package/lib/index.js +19 -0
  26. package/lib/options.d.ts +19 -0
  27. package/lib/options.js +47 -0
  28. package/lib/program.d.ts +2 -0
  29. package/lib/program.js +28 -0
  30. package/lib/ui.d.ts +5 -0
  31. package/lib/ui.js +23 -0
  32. package/package.json +36 -45
  33. package/bin/dev.cmd +0 -3
  34. package/bin/run.cmd +0 -3
  35. package/dist/account.js +0 -5
  36. package/dist/commands/account/generate.js +0 -10
  37. package/dist/commands/account/id.js +0 -18
  38. package/dist/commands/graph/deploy.js +0 -32
  39. package/dist/commands/graph/mutate.js +0 -32
  40. package/dist/commands/graph/query.js +0 -32
  41. package/dist/commands/graphql/schema.js +0 -41
  42. package/dist/commands/mcp.js +0 -33
  43. package/dist/commands/model/cluster.js +0 -35
  44. package/dist/commands/model/create.js +0 -69
  45. package/dist/commands/serve.js +0 -126
  46. package/dist/index.js +0 -1
  47. package/oclif.manifest.json +0 -533
package/README.md CHANGED
@@ -1,247 +1,35 @@
1
- kubun
2
- =================
1
+ # kubun
3
2
 
4
- Kubun CLI
3
+ Kubun CLI.
5
4
 
6
-
7
- [![oclif](https://img.shields.io/badge/cli-oclif-brightgreen.svg)](https://oclif.io)
8
5
  [![Version](https://img.shields.io/npm/v/kubun.svg)](https://npmjs.org/package/kubun)
9
6
  [![Downloads/week](https://img.shields.io/npm/dw/kubun.svg)](https://npmjs.org/package/kubun)
10
7
 
8
+ ## Usage
11
9
 
12
- <!-- toc -->
13
- * [Usage](#usage)
14
- * [Commands](#commands)
15
- <!-- tocstop -->
16
- # Usage
17
- <!-- usage -->
18
10
  ```sh-session
19
- $ npm install -g kubun
20
- $ kubun COMMAND
21
- running command...
22
- $ kubun (--version)
23
- kubun/0.9.0 darwin-arm64 node-v24.15.0
24
- $ kubun --help [COMMAND]
25
- USAGE
26
- $ kubun COMMAND
27
- ...
28
- ```
29
- <!-- usagestop -->
30
- # Commands
31
- <!-- commands -->
32
- * [`kubun account generate`](#kubun-account-generate)
33
- * [`kubun account id`](#kubun-account-id)
34
- * [`kubun graph deploy`](#kubun-graph-deploy)
35
- * [`kubun graph mutate ID TEXT`](#kubun-graph-mutate-id-text)
36
- * [`kubun graph query ID TEXT`](#kubun-graph-query-id-text)
37
- * [`kubun graphql schema`](#kubun-graphql-schema)
38
- * [`kubun help [COMMAND]`](#kubun-help-command)
39
- * [`kubun mcp`](#kubun-mcp)
40
- * [`kubun model cluster`](#kubun-model-cluster)
41
- * [`kubun model create NAME SCHEMA`](#kubun-model-create-name-schema)
42
- * [`kubun serve`](#kubun-serve)
43
-
44
- ## `kubun account generate`
45
-
46
- Generate a random private key to use as account signer
47
-
48
- ```
49
- USAGE
50
- $ kubun account generate
51
-
52
- DESCRIPTION
53
- Generate a random private key to use as account signer
54
- ```
55
-
56
- ## `kubun account id`
57
-
58
- Display the DID of an account given its private key
59
-
60
- ```
61
- USAGE
62
- $ kubun account id -k <value>
63
-
64
- FLAGS
65
- -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
66
-
67
- DESCRIPTION
68
- Display the DID of an account given its private key
69
- ```
70
-
71
- ## `kubun graph deploy`
72
-
73
- Deploy a documents model graph
74
-
11
+ $ pnpm add -g kubun
12
+ $ kubun --help
13
+ $ kubun <command> --help
75
14
  ```
76
- USAGE
77
- $ kubun graph deploy -c <value>... -k <value> [--id <value>] [-n <value>] [--url <value>]
78
15
 
79
- FLAGS
80
- -c, --cluster=<value>... (required) path of the JSON file of the cluster
81
- -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
82
- -n, --name=<value> graph name
83
- --id=<value> graph ID
84
- --url=<value> Kubun server URL
16
+ The CLI is built on [commander](https://github.com/tj/commander.js) with [`@tejika/cli`](https://www.npmjs.com/package/@tejika/cli); status output renders to stderr (via ink) and data payloads to stdout, so command output stays pipeable.
85
17
 
86
- DESCRIPTION
87
- Deploy a documents model graph
88
- ```
18
+ ## Commands
89
19
 
90
- ## `kubun graph mutate ID TEXT`
20
+ Run `kubun <command> --help` for the full, authoritative flag list — the descriptions below are a summary.
91
21
 
92
- Execute a GraphQL mutation on a graph
22
+ | Command | Description |
23
+ | --- | --- |
24
+ | `kubun account generate` | Generate a random private key to use as account signer |
25
+ | `kubun account id` | Display the DID of an account given its private key |
26
+ | `kubun graph mutate <id> <text>` | Execute a GraphQL mutation on a graph |
27
+ | `kubun graph query <id> <text>` | Execute a GraphQL query on a graph |
28
+ | `kubun graph deploy` | Deploy a documents model graph |
29
+ | `kubun graphql schema` | Create a GraphQL schema from clusters of document models |
30
+ | `kubun model cluster` | Create a documents cluster model |
31
+ | `kubun model create <name> <schema>` | Create a document model |
32
+ | `kubun mcp` | Start an MCP server for Kubun |
33
+ | `kubun serve` | Start a local Kubun server |
93
34
 
94
- ```
95
- USAGE
96
- $ kubun graph mutate ID TEXT -k <value> [--url <value>] [--variables <value>]
97
-
98
- ARGUMENTS
99
- ID graph ID
100
- TEXT mutation text
101
-
102
- FLAGS
103
- -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
104
- --url=<value> Kubun server URL
105
- --variables=<value> query variables as JSON string
106
-
107
- DESCRIPTION
108
- Execute a GraphQL mutation on a graph
109
- ```
110
-
111
- ## `kubun graph query ID TEXT`
112
-
113
- Execute a GraphQL query on a graph
114
-
115
- ```
116
- USAGE
117
- $ kubun graph query ID TEXT -k <value> [--url <value>] [--variables <value>]
118
-
119
- ARGUMENTS
120
- ID graph ID
121
- TEXT query text
122
-
123
- FLAGS
124
- -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
125
- --url=<value> Kubun server URL
126
- --variables=<value> query variables as JSON string
127
-
128
- DESCRIPTION
129
- Execute a GraphQL query on a graph
130
- ```
131
-
132
- ## `kubun graphql schema`
133
-
134
- Create a GraphQL schema from clusters of document models
135
-
136
- ```
137
- USAGE
138
- $ kubun graphql schema -c <value>... [-o <value>]
139
-
140
- FLAGS
141
- -c, --cluster=<value>... (required) path of the JSON file of the cluster
142
- -o, --output=<value> output file for the GraphQL schema
143
-
144
- DESCRIPTION
145
- Create a GraphQL schema from clusters of document models
146
- ```
147
-
148
- ## `kubun help [COMMAND]`
149
-
150
- Display help for kubun.
151
-
152
- ```
153
- USAGE
154
- $ kubun help [COMMAND...] [-n]
155
-
156
- ARGUMENTS
157
- [COMMAND...] Command to show help for.
158
-
159
- FLAGS
160
- -n, --nested-commands Include all nested commands in the output.
161
-
162
- DESCRIPTION
163
- Display help for kubun.
164
- ```
165
-
166
- _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/6.2.46/src/commands/help.ts)_
167
-
168
- ## `kubun mcp`
169
-
170
- Start an MCP server for Kubun
171
-
172
- ```
173
- USAGE
174
- $ kubun mcp [-c <value> | -d <value>] [-k <value>]
175
-
176
- FLAGS
177
- -c, --connect=<value> URL of an existing Kubun HTTP server to connect to
178
- -d, --db=<value> SQLite database path or PostgreSQL URL
179
- -k, --privateKey=<value> [env: KUBUN_PRIVATE_KEY] base64-encoded private key
180
-
181
- DESCRIPTION
182
- Start an MCP server for Kubun
183
- ```
184
-
185
- ## `kubun model cluster`
186
-
187
- Create a documents cluster model
188
-
189
- ```
190
- USAGE
191
- $ kubun model cluster -m <value>... [-o <value>]
192
-
193
- FLAGS
194
- -m, --model=<value>... (required) document model as JSON string
195
- -o, --output=<value> output file for the cluster
196
-
197
- DESCRIPTION
198
- Create a documents cluster model
199
- ```
200
-
201
- ## `kubun model create NAME SCHEMA`
202
-
203
- Create a document model
204
-
205
- ```
206
- USAGE
207
- $ kubun model create NAME SCHEMA [-b default|interface|unique] [-c] [-o <value>] [-u <value>...]
208
-
209
- ARGUMENTS
210
- NAME document model name
211
- SCHEMA document schema as JSON string
212
-
213
- FLAGS
214
- -b, --behavior=<option> [default: default] behavior of the document
215
- <options: default|interface|unique>
216
- -c, --cluster create a cluster model instead of a document model
217
- -o, --output=<value> output file
218
- -u, --uniqueField=<value>... unique field of the document when behavior is set to "unique"
219
-
220
- DESCRIPTION
221
- Create a document model
222
- ```
223
-
224
- ## `kubun serve`
225
-
226
- Start a local Kubun server
227
-
228
- ```
229
- USAGE
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
-
233
- FLAGS
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
243
-
244
- DESCRIPTION
245
- Start a local Kubun server
246
- ```
247
- <!-- commandsstop -->
35
+ Common flags: `-k, --private-key <value>` (also read from `KUBUN_PRIVATE_KEY`), `--url <value>`, `-l, --log-level <level>`, `-p, --port <port>`, `-a, --allowed-origin <origin>` (also `KUBUN_ALLOWED_ORIGIN`).
package/bin/dev.js CHANGED
@@ -1,6 +1,14 @@
1
- #!/usr/bin/env -S node --loader ts-node/esm --disable-warning=ExperimentalWarning
1
+ #!/usr/bin/env -S node --disable-warning=ExperimentalWarning
2
2
 
3
- // eslint-disable-next-line n/shebang
4
- import { execute } from '@oclif/core'
3
+ import { run } from '../lib/index.js'
5
4
 
6
- await execute({ development: true, dir: import.meta.url })
5
+ process.on('unhandledRejection', (reason) => {
6
+ const message = reason instanceof Error ? reason.message : String(reason)
7
+ process.stderr.write(`✘ ${message}\n`)
8
+ if (process.env.KUBUN_DEBUG === '1' && reason instanceof Error && reason.stack != null) {
9
+ process.stderr.write(`${reason.stack}\n`)
10
+ }
11
+ process.exitCode = 1
12
+ })
13
+
14
+ await run(process.argv)
package/bin/run.js CHANGED
@@ -1,5 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { execute } from '@oclif/core'
3
+ import { run } from '../lib/index.js'
4
4
 
5
- await execute({ dir: import.meta.url })
5
+ process.on('unhandledRejection', (reason) => {
6
+ const message = reason instanceof Error ? reason.message : String(reason)
7
+ process.stderr.write(`✘ ${message}\n`)
8
+ if (process.env.KUBUN_DEBUG === '1' && reason instanceof Error && reason.stack != null) {
9
+ process.stderr.write(`${reason.stack}\n`)
10
+ }
11
+ process.exitCode = 1
12
+ })
13
+
14
+ await run(process.argv)
@@ -0,0 +1,2 @@
1
+ import { type SigningIdentity } from '@kokuin/token';
2
+ export declare function getSigner(key: string): SigningIdentity;
package/lib/account.js ADDED
@@ -0,0 +1,5 @@
1
+ import { createSigningIdentity } from '@kokuin/token';
2
+ import { fromB64 } from '@sozai/codec';
3
+ export function getSigner(key) {
4
+ return createSigningIdentity(fromB64(key));
5
+ }
@@ -0,0 +1,2 @@
1
+ import { HTTPClient } from '@kubun/http-client';
2
+ export declare function createClient(signerKey: string, url?: string): HTTPClient;
@@ -1,5 +1,8 @@
1
1
  import { HTTPClient } from '@kubun/http-client';
2
2
  import { getSigner } from './account.js';
3
3
  export function createClient(signerKey, url = 'http://localhost:4321') {
4
- return new HTTPClient({ identity: getSigner(signerKey), url });
4
+ return new HTTPClient({
5
+ identity: getSigner(signerKey),
6
+ url
7
+ });
5
8
  }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createAccountCommand(): Command;
@@ -0,0 +1,24 @@
1
+ import { randomPrivateKey } from '@kokuin/token';
2
+ import { toB64 } from '@sozai/codec';
3
+ import { Command } from 'commander';
4
+ import { getSigner } from '../account.js';
5
+ import { withPrivateKey } from '../options.js';
6
+ function createGenerateCommand() {
7
+ return new Command('generate').description('Generate a random private key to use as account signer').action(async ()=>{
8
+ const key = await randomPrivateKey();
9
+ console.log(toB64(key));
10
+ });
11
+ }
12
+ function createIDCommand() {
13
+ const cmd = new Command('id').description('Display the DID of an account given its private key');
14
+ withPrivateKey(cmd, {
15
+ required: true
16
+ });
17
+ cmd.action((opts)=>{
18
+ console.log(getSigner(opts.privateKey).id);
19
+ });
20
+ return cmd;
21
+ }
22
+ export function createAccountCommand() {
23
+ return new Command('account').description('Account commands').addCommand(createGenerateCommand()).addCommand(createIDCommand());
24
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createGraphCommand(): Command;
@@ -0,0 +1,74 @@
1
+ import { Command } from 'commander';
2
+ import { createClient } from '../client.js';
3
+ import { readJSON } from '../fs.js';
4
+ import { withPrivateKey, withURL } from '../options.js';
5
+ import { renderNotice, withSpinner } from '../ui.js';
6
+ function parseVariables(value) {
7
+ if (!value) {
8
+ return {};
9
+ }
10
+ try {
11
+ return JSON.parse(value);
12
+ } catch {
13
+ throw new Error(`--variables is not valid JSON: ${value}`);
14
+ }
15
+ }
16
+ function createMutateCommand() {
17
+ const cmd = new Command('mutate').description('Execute a GraphQL mutation on a graph').argument('<id>', 'graph ID').argument('<text>', 'mutation text').option('--variables <json>', 'query variables as JSON string');
18
+ withPrivateKey(cmd, {
19
+ required: true
20
+ });
21
+ withURL(cmd);
22
+ cmd.action(async (id, text, opts)=>{
23
+ const client = createClient(opts.privateKey, opts.url);
24
+ const result = await withSpinner('Executing graph mutation...', ()=>client.mutateGraph({
25
+ id,
26
+ text,
27
+ variables: parseVariables(opts.variables)
28
+ }));
29
+ renderNotice('success', 'Graph mutation executed');
30
+ console.log(JSON.stringify(result, null, 2));
31
+ });
32
+ return cmd;
33
+ }
34
+ function createQueryCommand() {
35
+ const cmd = new Command('query').description('Execute a GraphQL query on a graph').argument('<id>', 'graph ID').argument('<text>', 'query text').option('--variables <json>', 'query variables as JSON string');
36
+ withPrivateKey(cmd, {
37
+ required: true
38
+ });
39
+ withURL(cmd);
40
+ cmd.action(async (id, text, opts)=>{
41
+ const client = createClient(opts.privateKey, opts.url);
42
+ const result = await withSpinner('Querying graph...', ()=>client.queryGraph({
43
+ id,
44
+ text,
45
+ variables: parseVariables(opts.variables)
46
+ }));
47
+ renderNotice('success', 'Graph query executed');
48
+ console.log(JSON.stringify(result, null, 2));
49
+ });
50
+ return cmd;
51
+ }
52
+ function createDeployCommand() {
53
+ const cmd = new Command('deploy').description('Deploy a documents model graph').requiredOption('-c, --cluster <path...>', 'path of the JSON file of the cluster (repeatable)').option('--id <id>', 'graph ID').option('-n, --name <name>', 'graph name');
54
+ withPrivateKey(cmd, {
55
+ required: true
56
+ });
57
+ withURL(cmd);
58
+ cmd.action(async (opts)=>{
59
+ const client = createClient(opts.privateKey, opts.url);
60
+ const graph = await withSpinner('Deploying graph clusters...', async ()=>{
61
+ const clusters = await Promise.all(opts.cluster.map((path)=>readJSON(path)));
62
+ return client.deployGraph({
63
+ clusters,
64
+ id: opts.id,
65
+ name: opts.name
66
+ });
67
+ });
68
+ renderNotice('success', `Deployed graph with ID: ${graph.id}`);
69
+ });
70
+ return cmd;
71
+ }
72
+ export function createGraphCommand() {
73
+ return new Command('graph').description('Graph commands').addCommand(createMutateCommand()).addCommand(createQueryCommand()).addCommand(createDeployCommand());
74
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createGraphQLCommand(): Command;
@@ -0,0 +1,33 @@
1
+ import { createSchema } from '@kubun/graphql';
2
+ import { clusterToRecord, GraphModel } from '@kubun/protocol';
3
+ import { Command } from 'commander';
4
+ import { printSchema } from 'graphql';
5
+ import { readJSON, writeFile } from '../fs.js';
6
+ import { renderNotice, withSpinner } from '../ui.js';
7
+ function createSchemaCommand() {
8
+ const cmd = new Command('schema').description('Create a GraphQL schema from clusters of document models').requiredOption('-c, --cluster <path...>', 'path of the JSON file of the cluster (repeatable)').option('-o, --output <file>', 'output file for the GraphQL schema');
9
+ cmd.action(async (opts)=>{
10
+ const schema = await withSpinner('Loading clusters...', async ()=>{
11
+ const clusterModels = await Promise.all(opts.cluster.map((path)=>readJSON(path)));
12
+ const clusters = {};
13
+ for (const cluster of clusterModels){
14
+ Object.assign(clusters, clusterToRecord(cluster));
15
+ }
16
+ const model = GraphModel.fromClusters({
17
+ clusters
18
+ });
19
+ return printSchema(createSchema(model));
20
+ });
21
+ if (opts.output == null) {
22
+ renderNotice('success', 'GraphQL schema generated');
23
+ console.log(schema);
24
+ } else {
25
+ await writeFile(opts.output, schema);
26
+ renderNotice('success', `GraphQL schema written to ${opts.output}`);
27
+ }
28
+ });
29
+ return cmd;
30
+ }
31
+ export function createGraphQLCommand() {
32
+ return new Command('graphql').description('GraphQL commands').addCommand(createSchemaCommand());
33
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createMCPCommand(): Command;
@@ -0,0 +1,21 @@
1
+ import { createConfig } from '@kubun/mcp';
2
+ import { serveProcess } from '@mokei/context-server';
3
+ import { Command } from 'commander';
4
+ import { getSigner } from '../account.js';
5
+ import { withPrivateKey } from '../options.js';
6
+ export function createMCPCommand() {
7
+ const cmd = new Command('mcp').description('Start an MCP server for Kubun').option('-c, --connect <url>', 'URL of an existing Kubun HTTP server to connect to').option('-d, --db <path>', 'SQLite database path or PostgreSQL URL');
8
+ withPrivateKey(cmd);
9
+ cmd.action(async (opts)=>{
10
+ if (opts.connect != null && opts.db != null) {
11
+ throw new Error('--connect and --db are mutually exclusive');
12
+ }
13
+ const config = await createConfig({
14
+ connect: opts.connect,
15
+ database: opts.db,
16
+ identity: opts.privateKey ? getSigner(opts.privateKey) : undefined
17
+ });
18
+ serveProcess(config);
19
+ });
20
+ return cmd;
21
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createModelCommand(): Command;
@@ -0,0 +1,69 @@
1
+ import { ClusterBuilder } from '@kubun/protocol';
2
+ import { Command, Option } from 'commander';
3
+ import { writeJSON } from '../fs.js';
4
+ import { renderNotice } from '../ui.js';
5
+ function parseJSON(label, value) {
6
+ try {
7
+ return JSON.parse(value);
8
+ } catch {
9
+ throw new Error(`${label} is not valid JSON: ${value}`);
10
+ }
11
+ }
12
+ function createClusterCommand() {
13
+ const cmd = new Command('cluster').description('Create a documents cluster model').requiredOption('-m, --model <json...>', 'document model as JSON string (repeatable)').option('-o, --output <file>', 'output file for the cluster');
14
+ cmd.action(async (opts)=>{
15
+ const builder = new ClusterBuilder();
16
+ builder.addAll(opts.model.map((model)=>parseJSON('--model', model)));
17
+ const cluster = builder.build();
18
+ if (opts.output == null) {
19
+ renderNotice('success', 'Cluster model created');
20
+ console.log(JSON.stringify(cluster));
21
+ } else {
22
+ await writeJSON(opts.output, cluster);
23
+ renderNotice('success', `Cluster model written to ${opts.output}`);
24
+ }
25
+ });
26
+ return cmd;
27
+ }
28
+ function createCreateCommand() {
29
+ const cmd = new Command('create').description('Create a document model').argument('<name>', 'document model name').argument('<schema>', 'document schema as JSON string').addOption(new Option('-b, --behavior <behavior>', 'behavior of the document').choices([
30
+ 'default',
31
+ 'interface',
32
+ 'unique'
33
+ ]).default('default')).option('-c, --cluster', 'create a cluster model instead of a document model').option('-o, --output <file>', 'output file').option('-u, --unique-field <field...>', 'unique field of the document when behavior is "unique" (repeatable)');
34
+ cmd.action(async (name, schema, opts)=>{
35
+ const model = {
36
+ name,
37
+ behavior: opts.behavior,
38
+ schema: parseJSON('<schema>', schema)
39
+ };
40
+ if (opts.behavior === 'unique') {
41
+ model.uniqueFields = opts.uniqueField;
42
+ }
43
+ const builder = new ClusterBuilder();
44
+ builder.add(model);
45
+ if (opts.cluster) {
46
+ const cluster = builder.build();
47
+ if (opts.output == null) {
48
+ renderNotice('success', 'Cluster model created');
49
+ console.log(JSON.stringify(cluster));
50
+ } else {
51
+ await writeJSON(opts.output, cluster);
52
+ renderNotice('success', `Cluster model written to ${opts.output}`);
53
+ }
54
+ return;
55
+ }
56
+ const document = builder.cluster[0];
57
+ if (opts.output == null) {
58
+ renderNotice('success', 'Document model created');
59
+ console.log(JSON.stringify(document));
60
+ } else {
61
+ await writeJSON(opts.output, document);
62
+ renderNotice('success', `Document model written to ${opts.output}`);
63
+ }
64
+ });
65
+ return cmd;
66
+ }
67
+ export function createModelCommand() {
68
+ return new Command('model').description('Model commands').addCommand(createClusterCommand()).addCommand(createCreateCommand());
69
+ }
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function createServeCommand(): Command;