kubun 0.3.1 → 0.3.3

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 CHANGED
@@ -20,7 +20,7 @@ $ npm install -g kubun
20
20
  $ kubun COMMAND
21
21
  running command...
22
22
  $ kubun (--version)
23
- kubun/0.3.1 darwin-arm64 node-v23.9.0
23
+ kubun/0.3.3 darwin-arm64 node-v24.5.0
24
24
  $ kubun --help [COMMAND]
25
25
  USAGE
26
26
  $ kubun COMMAND
@@ -35,8 +35,6 @@ USAGE
35
35
  * [`kubun graph mutate ID TEXT`](#kubun-graph-mutate-id-text)
36
36
  * [`kubun graph query ID TEXT`](#kubun-graph-query-id-text)
37
37
  * [`kubun graphql schema`](#kubun-graphql-schema)
38
- * [`kubun hello PERSON`](#kubun-hello-person)
39
- * [`kubun hello world`](#kubun-hello-world)
40
38
  * [`kubun help [COMMAND]`](#kubun-help-command)
41
39
  * [`kubun model cluster`](#kubun-model-cluster)
42
40
  * [`kubun model create NAME SCHEMA`](#kubun-model-create-name-schema)
@@ -73,7 +71,7 @@ USAGE
73
71
  $ kubun account id -k <value>
74
72
 
75
73
  FLAGS
76
- -k, --privateKey=<value> (required) base64-encoded private key
74
+ -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
77
75
 
78
76
  DESCRIPTION
79
77
  Display the DID of an account given its private key
@@ -89,7 +87,7 @@ USAGE
89
87
 
90
88
  FLAGS
91
89
  -c, --cluster=<value>... (required) path of the JSON file of the cluster
92
- -k, --privateKey=<value> (required) base64-encoded private key
90
+ -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
93
91
  -n, --name=<value> graph name
94
92
  --id=<value> graph ID
95
93
  --url=<value> Kubun server URL
@@ -111,7 +109,7 @@ ARGUMENTS
111
109
  TEXT mutation text
112
110
 
113
111
  FLAGS
114
- -k, --privateKey=<value> (required) base64-encoded private key
112
+ -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
115
113
  --url=<value> Kubun server URL
116
114
  --variables=<value> query variables as JSON string
117
115
 
@@ -132,7 +130,7 @@ ARGUMENTS
132
130
  TEXT query text
133
131
 
134
132
  FLAGS
135
- -k, --privateKey=<value> (required) base64-encoded private key
133
+ -k, --privateKey=<value> (required) [env: KUBUN_PRIVATE_KEY] base64-encoded private key
136
134
  --url=<value> Kubun server URL
137
135
  --variables=<value> query variables as JSON string
138
136
 
@@ -156,44 +154,6 @@ DESCRIPTION
156
154
  Create a GraphQL schema from clusters of document models
157
155
  ```
158
156
 
159
- ## `kubun hello PERSON`
160
-
161
- Say hello
162
-
163
- ```
164
- USAGE
165
- $ kubun hello PERSON -f <value>
166
-
167
- ARGUMENTS
168
- PERSON Person to say hello to
169
-
170
- FLAGS
171
- -f, --from=<value> (required) Who is saying hello
172
-
173
- DESCRIPTION
174
- Say hello
175
-
176
- EXAMPLES
177
- $ kubun hello friend --from oclif
178
- hello friend from oclif! (./src/commands/hello/index.ts)
179
- ```
180
-
181
- ## `kubun hello world`
182
-
183
- Say hello world
184
-
185
- ```
186
- USAGE
187
- $ kubun hello world
188
-
189
- DESCRIPTION
190
- Say hello world
191
-
192
- EXAMPLES
193
- $ kubun hello world
194
- hello world! (./src/commands/hello/world.ts)
195
- ```
196
-
197
157
  ## `kubun help [COMMAND]`
198
158
 
199
159
  Display help for kubun.
@@ -203,7 +163,7 @@ USAGE
203
163
  $ kubun help [COMMAND...] [-n]
204
164
 
205
165
  ARGUMENTS
206
- COMMAND... Command to show help for.
166
+ [COMMAND...] Command to show help for.
207
167
 
208
168
  FLAGS
209
169
  -n, --nested-commands Include all nested commands in the output.
@@ -212,7 +172,7 @@ DESCRIPTION
212
172
  Display help for kubun.
213
173
  ```
214
174
 
215
- _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.27/src/commands/help.ts)_
175
+ _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.36/src/commands/help.ts)_
216
176
 
217
177
  ## `kubun model cluster`
218
178
 
@@ -274,7 +234,7 @@ EXAMPLES
274
234
  $ kubun plugins
275
235
  ```
276
236
 
277
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.36/src/commands/plugins/index.ts)_
237
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/index.ts)_
278
238
 
279
239
  ## `kubun plugins add PLUGIN`
280
240
 
@@ -348,7 +308,7 @@ EXAMPLES
348
308
  $ kubun plugins inspect myplugin
349
309
  ```
350
310
 
351
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.36/src/commands/plugins/inspect.ts)_
311
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/inspect.ts)_
352
312
 
353
313
  ## `kubun plugins install PLUGIN`
354
314
 
@@ -397,7 +357,7 @@ EXAMPLES
397
357
  $ kubun plugins install someuser/someplugin
398
358
  ```
399
359
 
400
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.36/src/commands/plugins/install.ts)_
360
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/install.ts)_
401
361
 
402
362
  ## `kubun plugins link PATH`
403
363
 
@@ -428,7 +388,7 @@ EXAMPLES
428
388
  $ kubun plugins link myplugin
429
389
  ```
430
390
 
431
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.36/src/commands/plugins/link.ts)_
391
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/link.ts)_
432
392
 
433
393
  ## `kubun plugins remove [PLUGIN]`
434
394
 
@@ -439,7 +399,7 @@ USAGE
439
399
  $ kubun plugins remove [PLUGIN...] [-h] [-v]
440
400
 
441
401
  ARGUMENTS
442
- PLUGIN... plugin to uninstall
402
+ [PLUGIN...] plugin to uninstall
443
403
 
444
404
  FLAGS
445
405
  -h, --help Show CLI help.
@@ -469,7 +429,7 @@ FLAGS
469
429
  --reinstall Reinstall all plugins after uninstalling.
470
430
  ```
471
431
 
472
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.36/src/commands/plugins/reset.ts)_
432
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/reset.ts)_
473
433
 
474
434
  ## `kubun plugins uninstall [PLUGIN]`
475
435
 
@@ -480,7 +440,7 @@ USAGE
480
440
  $ kubun plugins uninstall [PLUGIN...] [-h] [-v]
481
441
 
482
442
  ARGUMENTS
483
- PLUGIN... plugin to uninstall
443
+ [PLUGIN...] plugin to uninstall
484
444
 
485
445
  FLAGS
486
446
  -h, --help Show CLI help.
@@ -497,7 +457,7 @@ EXAMPLES
497
457
  $ kubun plugins uninstall myplugin
498
458
  ```
499
459
 
500
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.36/src/commands/plugins/uninstall.ts)_
460
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/uninstall.ts)_
501
461
 
502
462
  ## `kubun plugins unlink [PLUGIN]`
503
463
 
@@ -508,7 +468,7 @@ USAGE
508
468
  $ kubun plugins unlink [PLUGIN...] [-h] [-v]
509
469
 
510
470
  ARGUMENTS
511
- PLUGIN... plugin to uninstall
471
+ [PLUGIN...] plugin to uninstall
512
472
 
513
473
  FLAGS
514
474
  -h, --help Show CLI help.
@@ -541,7 +501,7 @@ DESCRIPTION
541
501
  Update installed plugins.
542
502
  ```
543
503
 
544
- _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.36/src/commands/plugins/update.ts)_
504
+ _See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v5.4.54/src/commands/plugins/update.ts)_
545
505
 
546
506
  ## `kubun serve`
547
507
 
@@ -549,13 +509,14 @@ Start a local Kubun server
549
509
 
550
510
  ```
551
511
  USAGE
552
- $ kubun serve [--db <value>] [-p <value>] [-k <value> | --id <value>]
512
+ $ kubun serve [-a <value>] [--db <value>] [-p <value>] [-k <value> | --id <value>]
553
513
 
554
514
  FLAGS
555
- -k, --privateKey=<value> base64-encoded private key
556
- -p, --port=<value> port to listen on
557
- --db=<value> path to the local SQLite database
558
- --id=<value> server ID
515
+ -a, --allowedOrigin=<value> [default: *, env: KUBUN_ALLOWED_ORIGIN] allowed HTTP origin
516
+ -k, --privateKey=<value> [env: KUBUN_PRIVATE_KEY] base64-encoded private key
517
+ -p, --port=<value> port to listen on
518
+ --db=<value> path to the local SQLite database
519
+ --id=<value> server ID
559
520
 
560
521
  DESCRIPTION
561
522
  Start a local Kubun server
package/dist/account.js CHANGED
@@ -1,5 +1,5 @@
1
- import { fromB64 } from '@enkaku/codec'
2
- import { getTokenSigner as signerFromKey } from '@enkaku/token'
1
+ import { fromB64 } from '@enkaku/codec';
2
+ import { getTokenSigner as signerFromKey } from '@enkaku/token';
3
3
  export function getSigner(key) {
4
- return signerFromKey(fromB64(key))
4
+ return signerFromKey(fromB64(key));
5
5
  }
package/dist/client.js CHANGED
@@ -1,5 +1,5 @@
1
- import { HTTPClient } from '@kubun/http-client'
2
- import { getSigner } from './account.js'
1
+ import { HTTPClient } from '@kubun/http-client';
2
+ import { getSigner } from './account.js';
3
3
  export function createClient(signerKey, url = 'http://localhost:4321') {
4
- return new HTTPClient({ signer: getSigner(signerKey), url })
4
+ return new HTTPClient({ signer: getSigner(signerKey), url });
5
5
  }
@@ -1,10 +1,10 @@
1
- import { toB64 } from '@enkaku/codec'
2
- import { randomPrivateKey } from '@enkaku/token'
3
- import { Command } from '@oclif/core'
1
+ import { toB64 } from '@enkaku/codec';
2
+ import { randomPrivateKey } from '@enkaku/token';
3
+ import { Command } from '@oclif/core';
4
4
  export default class GenerateAccount extends Command {
5
- static description = 'Generate a random private key to use as account signer'
6
- async run() {
7
- const key = await randomPrivateKey()
8
- this.log(toB64(key))
9
- }
5
+ static description = 'Generate a random private key to use as account signer';
6
+ async run() {
7
+ const key = await randomPrivateKey();
8
+ this.log(toB64(key));
9
+ }
10
10
  }
@@ -1,18 +1,18 @@
1
- import { Command, Flags } from '@oclif/core'
2
- import { getSigner } from '../../account.js'
1
+ import { Command, Flags } from '@oclif/core';
2
+ import { getSigner } from '../../account.js';
3
3
  export default class AccountID extends Command {
4
- static description = 'Display the DID of an account given its private key'
5
- static flags = {
6
- privateKey: Flags.string({
7
- description: 'base64-encoded private key',
8
- char: 'k',
9
- env: 'KUBUN_PRIVATE_KEY',
10
- required: true,
11
- }),
12
- }
13
- async run() {
14
- const { flags } = await this.parse(AccountID)
15
- const signer = getSigner(flags.privateKey)
16
- this.log(signer.id)
17
- }
4
+ static description = 'Display the DID of an account given its private key';
5
+ static flags = {
6
+ privateKey: Flags.string({
7
+ description: 'base64-encoded private key',
8
+ char: 'k',
9
+ env: 'KUBUN_PRIVATE_KEY',
10
+ required: true,
11
+ }),
12
+ };
13
+ async run() {
14
+ const { flags } = await this.parse(AccountID);
15
+ const signer = getSigner(flags.privateKey);
16
+ this.log(signer.id);
17
+ }
18
18
  }
@@ -1,32 +1,32 @@
1
- import { Command, Flags } from '@oclif/core'
2
- import ora from 'ora'
3
- import { createClient } from '../../client.js'
4
- import { readJSON } from '../../fs.js'
1
+ import { Command, Flags } from '@oclif/core';
2
+ import ora from 'ora';
3
+ import { createClient } from '../../client.js';
4
+ import { readJSON } from '../../fs.js';
5
5
  export default class DeployGraph extends Command {
6
- static description = 'Deploy a documents model graph'
7
- static flags = {
8
- cluster: Flags.string({
9
- description: 'path of the JSON file of the cluster',
10
- char: 'c',
11
- required: true,
12
- multiple: true,
13
- }),
14
- id: Flags.string({ description: 'graph ID' }),
15
- name: Flags.string({ description: 'graph name', char: 'n' }),
16
- privateKey: Flags.string({
17
- description: 'base64-encoded private key',
18
- char: 'k',
19
- env: 'KUBUN_PRIVATE_KEY',
20
- required: true,
21
- }),
22
- url: Flags.string({ description: 'Kubun server URL' }),
23
- }
24
- async run() {
25
- const spinner = ora('Deploying graph clusters...').start()
26
- const { flags } = await this.parse(DeployGraph)
27
- const client = createClient(flags.privateKey, flags.url)
28
- const clusters = await Promise.all(flags.cluster.map((path) => readJSON(path)))
29
- const graph = await client.deployGraph({ clusters, id: flags.id, name: flags.name })
30
- spinner.succeed(`Deployed graph with ID: ${graph.id}`)
31
- }
6
+ static description = 'Deploy a documents model graph';
7
+ static flags = {
8
+ cluster: Flags.string({
9
+ description: 'path of the JSON file of the cluster',
10
+ char: 'c',
11
+ required: true,
12
+ multiple: true,
13
+ }),
14
+ id: Flags.string({ description: 'graph ID' }),
15
+ name: Flags.string({ description: 'graph name', char: 'n' }),
16
+ privateKey: Flags.string({
17
+ description: 'base64-encoded private key',
18
+ char: 'k',
19
+ env: 'KUBUN_PRIVATE_KEY',
20
+ required: true,
21
+ }),
22
+ url: Flags.string({ description: 'Kubun server URL' }),
23
+ };
24
+ async run() {
25
+ const spinner = ora('Deploying graph clusters...').start();
26
+ const { flags } = await this.parse(DeployGraph);
27
+ const client = createClient(flags.privateKey, flags.url);
28
+ const clusters = await Promise.all(flags.cluster.map((path) => readJSON(path)));
29
+ const graph = await client.deployGraph({ clusters, id: flags.id, name: flags.name });
30
+ spinner.succeed(`Deployed graph with ID: ${graph.id}`);
31
+ }
32
32
  }
@@ -1,32 +1,32 @@
1
- import { Args, Command, Flags } from '@oclif/core'
2
- import ora from 'ora'
3
- import { createClient } from '../../client.js'
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import ora from 'ora';
3
+ import { createClient } from '../../client.js';
4
4
  export default class MutateGraph extends Command {
5
- static description = 'Execute a GraphQL mutation on a graph'
6
- static args = {
7
- id: Args.string({ description: 'graph ID', required: true }),
8
- text: Args.string({ description: 'mutation text', required: true }),
9
- }
10
- static flags = {
11
- privateKey: Flags.string({
12
- description: 'base64-encoded private key',
13
- char: 'k',
14
- env: 'KUBUN_PRIVATE_KEY',
15
- required: true,
16
- }),
17
- url: Flags.string({ description: 'Kubun server URL' }),
18
- variables: Flags.string({ description: 'query variables as JSON string' }),
19
- }
20
- async run() {
21
- const spinner = ora('Executing graph mutation...').start()
22
- const { args, flags } = await this.parse(MutateGraph)
23
- const client = createClient(flags.privateKey, flags.url)
24
- const result = await client.mutateGraph({
25
- id: args.id,
26
- text: args.text,
27
- variables: flags.variables ? JSON.parse(flags.variables) : {},
28
- })
29
- spinner.succeed('Graph mutation executed')
30
- this.log(JSON.stringify(result, null, 2))
31
- }
5
+ static description = 'Execute a GraphQL mutation on a graph';
6
+ static args = {
7
+ id: Args.string({ description: 'graph ID', required: true }),
8
+ text: Args.string({ description: 'mutation text', required: true }),
9
+ };
10
+ static flags = {
11
+ privateKey: Flags.string({
12
+ description: 'base64-encoded private key',
13
+ char: 'k',
14
+ env: 'KUBUN_PRIVATE_KEY',
15
+ required: true,
16
+ }),
17
+ url: Flags.string({ description: 'Kubun server URL' }),
18
+ variables: Flags.string({ description: 'query variables as JSON string' }),
19
+ };
20
+ async run() {
21
+ const spinner = ora('Executing graph mutation...').start();
22
+ const { args, flags } = await this.parse(MutateGraph);
23
+ const client = createClient(flags.privateKey, flags.url);
24
+ const result = await client.mutateGraph({
25
+ id: args.id,
26
+ text: args.text,
27
+ variables: flags.variables ? JSON.parse(flags.variables) : {},
28
+ });
29
+ spinner.succeed('Graph mutation executed');
30
+ this.log(JSON.stringify(result, null, 2));
31
+ }
32
32
  }
@@ -1,32 +1,32 @@
1
- import { Args, Command, Flags } from '@oclif/core'
2
- import ora from 'ora'
3
- import { createClient } from '../../client.js'
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import ora from 'ora';
3
+ import { createClient } from '../../client.js';
4
4
  export default class QueryGraph extends Command {
5
- static description = 'Execute a GraphQL query on a graph'
6
- static args = {
7
- id: Args.string({ description: 'graph ID', required: true }),
8
- text: Args.string({ description: 'query text', required: true }),
9
- }
10
- static flags = {
11
- privateKey: Flags.string({
12
- description: 'base64-encoded private key',
13
- char: 'k',
14
- env: 'KUBUN_PRIVATE_KEY',
15
- required: true,
16
- }),
17
- url: Flags.string({ description: 'Kubun server URL' }),
18
- variables: Flags.string({ description: 'query variables as JSON string' }),
19
- }
20
- async run() {
21
- const spinner = ora('Querying graph...').start()
22
- const { args, flags } = await this.parse(QueryGraph)
23
- const client = createClient(flags.privateKey, flags.url)
24
- const result = await client.queryGraph({
25
- id: args.id,
26
- text: args.text,
27
- variables: flags.variables ? JSON.parse(flags.variables) : {},
28
- })
29
- spinner.succeed('Graph query executed')
30
- this.log(JSON.stringify(result, null, 2))
31
- }
5
+ static description = 'Execute a GraphQL query on a graph';
6
+ static args = {
7
+ id: Args.string({ description: 'graph ID', required: true }),
8
+ text: Args.string({ description: 'query text', required: true }),
9
+ };
10
+ static flags = {
11
+ privateKey: Flags.string({
12
+ description: 'base64-encoded private key',
13
+ char: 'k',
14
+ env: 'KUBUN_PRIVATE_KEY',
15
+ required: true,
16
+ }),
17
+ url: Flags.string({ description: 'Kubun server URL' }),
18
+ variables: Flags.string({ description: 'query variables as JSON string' }),
19
+ };
20
+ async run() {
21
+ const spinner = ora('Querying graph...').start();
22
+ const { args, flags } = await this.parse(QueryGraph);
23
+ const client = createClient(flags.privateKey, flags.url);
24
+ const result = await client.queryGraph({
25
+ id: args.id,
26
+ text: args.text,
27
+ variables: flags.variables ? JSON.parse(flags.variables) : {},
28
+ });
29
+ spinner.succeed('Graph query executed');
30
+ this.log(JSON.stringify(result, null, 2));
31
+ }
32
32
  }
@@ -1,44 +1,45 @@
1
- import { createSchema } from '@kubun/graphql'
2
- import { GraphModel } from '@kubun/protocol'
3
- import { Command, Flags } from '@oclif/core'
4
- import { printSchema } from 'graphql'
5
- import ora from 'ora'
6
- import { readJSON, writeFile } from '../../fs.js'
1
+ import { createSchema } from '@kubun/graphql';
2
+ import { GraphModel } from '@kubun/protocol';
3
+ import { Command, Flags } from '@oclif/core';
4
+ import { printSchema } from 'graphql';
5
+ import ora from 'ora';
6
+ import { readJSON, writeFile } from '../../fs.js';
7
7
  export default class CreateGraphQLSchema extends Command {
8
- static description = 'Create a GraphQL schema from clusters of document models'
9
- static flags = {
10
- cluster: Flags.string({
11
- description: 'path of the JSON file of the cluster',
12
- char: 'c',
13
- required: true,
14
- multiple: true,
15
- }),
16
- output: Flags.file({
17
- description: 'output file for the GraphQL schema',
18
- char: 'o',
19
- }),
20
- // id: Flags.string({ description: 'graph ID' }),
21
- // privateKey: Flags.string({
22
- // description: 'base64-encoded private key',
23
- // char: 'k',
24
- // env: 'KUBUN_PRIVATE_KEY',
25
- // required: true,
26
- // }),
27
- // url: Flags.string({ description: 'Kubun server URL' }),
28
- }
29
- async run() {
30
- const spinner = ora('Loading clusters...').start()
31
- const { flags } = await this.parse(CreateGraphQLSchema)
32
- const clusters = await Promise.all(flags.cluster.map((path) => readJSON(path)))
33
- const model = await GraphModel.fromClusters({ clusters })
34
- const schema = printSchema(createSchema(model.record))
35
- if (flags.output == null) {
36
- spinner.succeed('GraphQL schema generated')
37
- this.log(schema)
38
- } else {
39
- await writeFile(flags.output, schema)
40
- spinner.succeed(`GraphQL schema written to ${flags.output}`)
8
+ static description = 'Create a GraphQL schema from clusters of document models';
9
+ static flags = {
10
+ cluster: Flags.string({
11
+ description: 'path of the JSON file of the cluster',
12
+ char: 'c',
13
+ required: true,
14
+ multiple: true,
15
+ }),
16
+ output: Flags.file({
17
+ description: 'output file for the GraphQL schema',
18
+ char: 'o',
19
+ }),
20
+ // id: Flags.string({ description: 'graph ID' }),
21
+ // privateKey: Flags.string({
22
+ // description: 'base64-encoded private key',
23
+ // char: 'k',
24
+ // env: 'KUBUN_PRIVATE_KEY',
25
+ // required: true,
26
+ // }),
27
+ // url: Flags.string({ description: 'Kubun server URL' }),
28
+ };
29
+ async run() {
30
+ const spinner = ora('Loading clusters...').start();
31
+ const { flags } = await this.parse(CreateGraphQLSchema);
32
+ const clusters = await Promise.all(flags.cluster.map((path) => readJSON(path)));
33
+ const model = await GraphModel.fromClusters({ clusters });
34
+ const schema = printSchema(createSchema(model.record));
35
+ if (flags.output == null) {
36
+ spinner.succeed('GraphQL schema generated');
37
+ this.log(schema);
38
+ }
39
+ else {
40
+ await writeFile(flags.output, schema);
41
+ spinner.succeed(`GraphQL schema written to ${flags.output}`);
42
+ }
43
+ return schema;
41
44
  }
42
- return schema
43
- }
44
45
  }
@@ -1,34 +1,35 @@
1
- import { ClusterBuilder } from '@kubun/protocol'
2
- import { Command, Flags } from '@oclif/core'
3
- import ora from 'ora'
4
- import { writeJSON } from '../../fs.js'
1
+ import { ClusterBuilder } from '@kubun/protocol';
2
+ import { Command, Flags } from '@oclif/core';
3
+ import ora from 'ora';
4
+ import { writeJSON } from '../../fs.js';
5
5
  export default class CreateClusterModel extends Command {
6
- static description = 'Create a documents cluster model'
7
- static flags = {
8
- model: Flags.string({
9
- description: 'document model as JSON string',
10
- char: 'm',
11
- multiple: true,
12
- required: true,
13
- }),
14
- output: Flags.file({
15
- description: 'output file for the cluster',
16
- char: 'o',
17
- }),
18
- }
19
- async run() {
20
- const spinner = ora('Creating cluster model...').start()
21
- const { flags } = await this.parse(CreateClusterModel)
22
- const builder = new ClusterBuilder()
23
- builder.addAll(flags.model.map((model) => JSON.parse(model)))
24
- const cluster = builder.build()
25
- if (flags.output == null) {
26
- spinner.succeed('Cluster model created')
27
- this.log(JSON.stringify(cluster))
28
- } else {
29
- await writeJSON(flags.output, cluster)
30
- spinner.succeed(`Cluster model written to ${flags.output}`)
6
+ static description = 'Create a documents cluster model';
7
+ static flags = {
8
+ model: Flags.string({
9
+ description: 'document model as JSON string',
10
+ char: 'm',
11
+ multiple: true,
12
+ required: true,
13
+ }),
14
+ output: Flags.file({
15
+ description: 'output file for the cluster',
16
+ char: 'o',
17
+ }),
18
+ };
19
+ async run() {
20
+ const spinner = ora('Creating cluster model...').start();
21
+ const { flags } = await this.parse(CreateClusterModel);
22
+ const builder = new ClusterBuilder();
23
+ builder.addAll(flags.model.map((model) => JSON.parse(model)));
24
+ const cluster = builder.build();
25
+ if (flags.output == null) {
26
+ spinner.succeed('Cluster model created');
27
+ this.log(JSON.stringify(cluster));
28
+ }
29
+ else {
30
+ await writeJSON(flags.output, cluster);
31
+ spinner.succeed(`Cluster model written to ${flags.output}`);
32
+ }
33
+ return cluster;
31
34
  }
32
- return cluster
33
- }
34
35
  }
@@ -1,67 +1,69 @@
1
- import { ClusterBuilder } from '@kubun/protocol'
2
- import { Args, Command, Flags } from '@oclif/core'
3
- import ora from 'ora'
4
- import { writeJSON } from '../../fs.js'
1
+ import { ClusterBuilder, } from '@kubun/protocol';
2
+ import { Args, Command, Flags } from '@oclif/core';
3
+ import ora from 'ora';
4
+ import { writeJSON } from '../../fs.js';
5
5
  export default class CreateDocumentModel extends Command {
6
- static description = 'Create a document model'
7
- static args = {
8
- name: Args.string({ description: 'document model name', required: true }),
9
- schema: Args.string({ description: 'document schema as JSON string', required: true }),
10
- }
11
- static flags = {
12
- behavior: Flags.string({
13
- description: 'behavior of the document',
14
- char: 'b',
15
- options: ['default', 'interface', 'unique'],
16
- default: 'default',
17
- }),
18
- cluster: Flags.boolean({
19
- description: 'create a cluster model instead of a document model',
20
- char: 'c',
21
- }),
22
- output: Flags.file({
23
- description: 'output file',
24
- char: 'o',
25
- }),
26
- uniqueField: Flags.string({
27
- description: 'unique field of the document when behavior is set to "unique"',
28
- char: 'u',
29
- multiple: true,
30
- }),
31
- }
32
- async run() {
33
- const spinner = ora('Creating document model...').start()
34
- const { args, flags } = await this.parse(CreateDocumentModel)
35
- const behavior = flags.behavior
36
- const model = {
37
- name: args.name,
38
- behavior,
39
- schema: JSON.parse(args.schema),
6
+ static description = 'Create a document model';
7
+ static args = {
8
+ name: Args.string({ description: 'document model name', required: true }),
9
+ schema: Args.string({ description: 'document schema as JSON string', required: true }),
10
+ };
11
+ static flags = {
12
+ behavior: Flags.string({
13
+ description: 'behavior of the document',
14
+ char: 'b',
15
+ options: ['default', 'interface', 'unique'],
16
+ default: 'default',
17
+ }),
18
+ cluster: Flags.boolean({
19
+ description: 'create a cluster model instead of a document model',
20
+ char: 'c',
21
+ }),
22
+ output: Flags.file({
23
+ description: 'output file',
24
+ char: 'o',
25
+ }),
26
+ uniqueField: Flags.string({
27
+ description: 'unique field of the document when behavior is set to "unique"',
28
+ char: 'u',
29
+ multiple: true,
30
+ }),
31
+ };
32
+ async run() {
33
+ const spinner = ora('Creating document model...').start();
34
+ const { args, flags } = await this.parse(CreateDocumentModel);
35
+ const behavior = flags.behavior;
36
+ const model = {
37
+ name: args.name,
38
+ behavior,
39
+ schema: JSON.parse(args.schema),
40
+ };
41
+ if (behavior === 'unique') {
42
+ model.uniqueFields = flags.uniqueField;
43
+ }
44
+ const builder = new ClusterBuilder();
45
+ builder.add(model);
46
+ if (flags.cluster) {
47
+ const cluster = builder.build();
48
+ if (flags.output == null) {
49
+ spinner.succeed('Cluster model created');
50
+ this.log(JSON.stringify(cluster));
51
+ }
52
+ else {
53
+ await writeJSON(flags.output, cluster);
54
+ spinner.succeed(`Cluster model written to ${flags.output}`);
55
+ }
56
+ return cluster;
57
+ }
58
+ const document = builder.cluster[0];
59
+ if (flags.output == null) {
60
+ spinner.succeed('Document model created');
61
+ this.log(JSON.stringify(document));
62
+ }
63
+ else {
64
+ await writeJSON(flags.output, document);
65
+ spinner.succeed(`Document model written to ${flags.output}`);
66
+ }
67
+ return document;
40
68
  }
41
- if (behavior === 'unique') {
42
- model.uniqueFields = flags.uniqueField
43
- }
44
- const builder = new ClusterBuilder()
45
- builder.add(model)
46
- if (flags.cluster) {
47
- const cluster = builder.build()
48
- if (flags.output == null) {
49
- spinner.succeed('Cluster model created')
50
- this.log(JSON.stringify(cluster))
51
- } else {
52
- await writeJSON(flags.output, cluster)
53
- spinner.succeed(`Cluster model written to ${flags.output}`)
54
- }
55
- return cluster
56
- }
57
- const document = builder.cluster[0]
58
- if (flags.output == null) {
59
- spinner.succeed('Document model created')
60
- this.log(JSON.stringify(document))
61
- } else {
62
- await writeJSON(flags.output, document)
63
- spinner.succeed(`Document model written to ${flags.output}`)
64
- }
65
- return document
66
- }
67
69
  }
@@ -1,75 +1,80 @@
1
- import { defer } from '@enkaku/async'
2
- import { toB64 } from '@enkaku/codec'
3
- import { ServerTransport } from '@enkaku/http-server-transport'
4
- import { serve } from '@enkaku/server'
5
- import { randomSigner, toTokenSigner } from '@enkaku/token'
6
- import { serve as serveHTTP } from '@hono/node-server'
7
- import { KubunDB } from '@kubun/db'
8
- import { PostgresAdapter } from '@kubun/db-postgres'
9
- import { SQLiteAdapter } from '@kubun/db-sqlite'
10
- import { createHandlers } from '@kubun/server'
11
- import { Command, Flags } from '@oclif/core'
12
- import getPort from 'get-port'
13
- import ora from 'ora'
14
- import { getSigner } from '../account.js'
15
- import { resolvePath } from '../fs.js'
1
+ import { defer } from '@enkaku/async';
2
+ import { toB64 } from '@enkaku/codec';
3
+ import { ServerTransport } from '@enkaku/http-server-transport';
4
+ import { serve } from '@enkaku/server';
5
+ import { randomSigner, toTokenSigner } from '@enkaku/token';
6
+ import { serve as serveHTTP } from '@hono/node-server';
7
+ import { KubunDB } from '@kubun/db';
8
+ import { PostgresAdapter } from '@kubun/db-postgres';
9
+ import { SQLiteAdapter } from '@kubun/db-sqlite';
10
+ import { createHandlers } from '@kubun/server';
11
+ import { Command, Flags } from '@oclif/core';
12
+ import getPort from 'get-port';
13
+ import ora from 'ora';
14
+ import { getSigner } from '../account.js';
15
+ import { resolvePath } from '../fs.js';
16
16
  export default class Serve extends Command {
17
- static description = 'Start a local Kubun server'
18
- static flags = {
19
- db: Flags.file({ description: 'path to the local SQLite database' }),
20
- id: Flags.string({ description: 'server ID' }),
21
- port: Flags.integer({ char: 'p', description: 'port to listen on' }),
22
- privateKey: Flags.string({
23
- char: 'k',
24
- description: 'base64-encoded private key',
25
- env: 'KUBUN_PRIVATE_KEY',
26
- exclusive: ['id'],
27
- }),
28
- }
29
- async run() {
30
- let signer
31
- const spinner = ora()
32
- const { flags } = await this.parse(Serve)
33
- let id = flags.id
34
- if (id == null) {
35
- if (flags.privateKey == null) {
36
- spinner.info('Generating a random private key for the server').start()
37
- const ownSigner = randomSigner()
38
- spinner.warn(`Generated private key: ${toB64(ownSigner.privateKey)}`)
39
- signer = toTokenSigner(ownSigner)
40
- } else {
41
- spinner.info('Using the provided private key for the server').start()
42
- signer = getSigner(flags.privateKey)
43
- }
44
- id = signer.id
17
+ static description = 'Start a local Kubun server';
18
+ static flags = {
19
+ allowedOrigin: Flags.string({ char: 'a', description: 'allowed HTTP origin', env: 'KUBUN_ALLOWED_ORIGIN', default: '*' }),
20
+ db: Flags.file({ description: 'path to the local SQLite database' }),
21
+ id: Flags.string({ description: 'server ID' }),
22
+ port: Flags.integer({ char: 'p', description: 'port to listen on' }),
23
+ privateKey: Flags.string({
24
+ char: 'k',
25
+ description: 'base64-encoded private key',
26
+ env: 'KUBUN_PRIVATE_KEY',
27
+ exclusive: ['id'],
28
+ }),
29
+ };
30
+ async run() {
31
+ let signer;
32
+ const spinner = ora();
33
+ const { flags } = await this.parse(Serve);
34
+ let id = flags.id;
35
+ if (id == null) {
36
+ if (flags.privateKey == null) {
37
+ spinner.info('Generating a random private key for the server').start();
38
+ const ownSigner = randomSigner();
39
+ spinner.warn(`Generated private key: ${toB64(ownSigner.privateKey)}`);
40
+ signer = toTokenSigner(ownSigner);
41
+ }
42
+ else {
43
+ spinner.info('Using the provided private key for the server').start();
44
+ signer = getSigner(flags.privateKey);
45
+ }
46
+ id = signer.id;
47
+ }
48
+ spinner.info(`Server DID: ${id}`);
49
+ let db;
50
+ if (flags.db == null) {
51
+ db = new KubunDB({ adapter: new SQLiteAdapter({ database: ':memory:' }) });
52
+ spinner.info('Using ephemeral (in memory) SQLite database');
53
+ }
54
+ else if (flags.db.startsWith('postgres://')) {
55
+ db = new KubunDB({ adapter: new PostgresAdapter({ url: flags.db }) });
56
+ spinner.info(`Using PostgreSQL database: ${flags.db}`);
57
+ }
58
+ else {
59
+ const database = resolvePath(flags.db);
60
+ db = new KubunDB({ adapter: new SQLiteAdapter({ database }) });
61
+ spinner.info(`Using local SQLite database: ${database}`);
62
+ }
63
+ const allowedOrigin = flags.allowedOrigin.split(',').map((origin) => origin.trim());
64
+ const transport = new ServerTransport({ allowedOrigin });
65
+ serve({ handlers: createHandlers({ db }), id, transport });
66
+ spinner.start(`Starting the server with allowed origin: ${allowedOrigin.join(', ')}`);
67
+ const port = flags.port ?? (await getPort({ port: 4321 }));
68
+ const httpServer = serveHTTP({ fetch: transport.fetch, port }, (info) => {
69
+ spinner.succeed(`HTTP server listening on port ${info.port}`);
70
+ });
71
+ const stopped = defer();
72
+ async function stop() {
73
+ httpServer.close();
74
+ stopped.resolve();
75
+ }
76
+ process.on('SIGINT', stop);
77
+ process.on('SIGTERM', stop);
78
+ return stopped.promise;
45
79
  }
46
- spinner.info(`Server DID: ${id}`)
47
- let db
48
- if (flags.db == null) {
49
- db = new KubunDB({ adapter: new SQLiteAdapter({ database: ':memory:' }) })
50
- spinner.info('Using ephemeral (in memory) SQLite database')
51
- } else if (flags.db.startsWith('postgres://')) {
52
- db = new KubunDB({ adapter: new PostgresAdapter({ url: flags.db }) })
53
- spinner.info(`Using PostgreSQL database: ${flags.db}`)
54
- } else {
55
- const database = resolvePath(flags.db)
56
- db = new KubunDB({ adapter: new SQLiteAdapter({ database }) })
57
- spinner.info(`Using local SQLite database: ${database}`)
58
- }
59
- const transport = new ServerTransport()
60
- serve({ handlers: createHandlers({ db }), id, transport })
61
- spinner.start('Starting the server')
62
- const port = flags.port ?? (await getPort({ port: 4321 }))
63
- const httpServer = serveHTTP({ fetch: transport.fetch, port }, (info) => {
64
- spinner.succeed(`HTTP server listening on port ${info.port}`)
65
- })
66
- const stopped = defer()
67
- async function stop() {
68
- httpServer.close()
69
- stopped.resolve()
70
- }
71
- process.on('SIGINT', stop)
72
- process.on('SIGTERM', stop)
73
- return stopped.promise
74
- }
75
80
  }
package/dist/fs.js CHANGED
@@ -1,14 +1,14 @@
1
- import { readFile as read, writeFile as write } from 'node:fs/promises'
2
- import { isAbsolute, resolve } from 'node:path'
1
+ import { readFile as read, writeFile as write } from 'node:fs/promises';
2
+ import { isAbsolute, resolve } from 'node:path';
3
3
  export function resolvePath(value) {
4
- return isAbsolute(value) ? value : resolve(process.cwd(), value)
4
+ return isAbsolute(value) ? value : resolve(process.cwd(), value);
5
5
  }
6
6
  export async function readJSON(path) {
7
- return JSON.parse(await read(resolvePath(path), { encoding: 'utf8' }))
7
+ return JSON.parse(await read(resolvePath(path), { encoding: 'utf8' }));
8
8
  }
9
9
  export async function writeFile(path, value) {
10
- await write(resolvePath(path), value, { encoding: 'utf8' })
10
+ await write(resolvePath(path), value, { encoding: 'utf8' });
11
11
  }
12
12
  export async function writeJSON(path, value, format = false) {
13
- await writeFile(path, format ? JSON.stringify(value, null, 2) : JSON.stringify(value))
13
+ await writeFile(path, format ? JSON.stringify(value, null, 2) : JSON.stringify(value));
14
14
  }
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export { run } from '@oclif/core'
1
+ export { run } from '@oclif/core';
@@ -5,6 +5,16 @@
5
5
  "args": {},
6
6
  "description": "Start a local Kubun server",
7
7
  "flags": {
8
+ "allowedOrigin": {
9
+ "char": "a",
10
+ "description": "allowed HTTP origin",
11
+ "env": "KUBUN_ALLOWED_ORIGIN",
12
+ "name": "allowedOrigin",
13
+ "default": "*",
14
+ "hasDynamicHelp": false,
15
+ "multiple": false,
16
+ "type": "option"
17
+ },
8
18
  "db": {
9
19
  "description": "path to the local SQLite database",
10
20
  "name": "db",
@@ -285,45 +295,6 @@
285
295
  "query.js"
286
296
  ]
287
297
  },
288
- "graphql:schema": {
289
- "aliases": [],
290
- "args": {},
291
- "description": "Create a GraphQL schema from clusters of document models",
292
- "flags": {
293
- "cluster": {
294
- "char": "c",
295
- "description": "path of the JSON file of the cluster",
296
- "name": "cluster",
297
- "required": true,
298
- "hasDynamicHelp": false,
299
- "multiple": true,
300
- "type": "option"
301
- },
302
- "output": {
303
- "char": "o",
304
- "description": "output file for the GraphQL schema",
305
- "name": "output",
306
- "hasDynamicHelp": false,
307
- "multiple": false,
308
- "type": "option"
309
- }
310
- },
311
- "hasDynamicHelp": false,
312
- "hiddenAliases": [],
313
- "id": "graphql:schema",
314
- "pluginAlias": "kubun",
315
- "pluginName": "kubun",
316
- "pluginType": "core",
317
- "strict": true,
318
- "enableJsonFlag": false,
319
- "isESM": true,
320
- "relativePath": [
321
- "dist",
322
- "commands",
323
- "graphql",
324
- "schema.js"
325
- ]
326
- },
327
298
  "model:cluster": {
328
299
  "aliases": [],
329
300
  "args": {},
@@ -433,57 +404,32 @@
433
404
  "create.js"
434
405
  ]
435
406
  },
436
- "hello": {
407
+ "graphql:schema": {
437
408
  "aliases": [],
438
- "args": {
439
- "person": {
440
- "description": "Person to say hello to",
441
- "name": "person",
442
- "required": true
443
- }
444
- },
445
- "description": "Say hello",
446
- "examples": [
447
- "<%= config.bin %> <%= command.id %> friend --from oclif\nhello friend from oclif! (./src/commands/hello/index.ts)\n"
448
- ],
409
+ "args": {},
410
+ "description": "Create a GraphQL schema from clusters of document models",
449
411
  "flags": {
450
- "from": {
451
- "char": "f",
452
- "description": "Who is saying hello",
453
- "name": "from",
412
+ "cluster": {
413
+ "char": "c",
414
+ "description": "path of the JSON file of the cluster",
415
+ "name": "cluster",
454
416
  "required": true,
455
417
  "hasDynamicHelp": false,
418
+ "multiple": true,
419
+ "type": "option"
420
+ },
421
+ "output": {
422
+ "char": "o",
423
+ "description": "output file for the GraphQL schema",
424
+ "name": "output",
425
+ "hasDynamicHelp": false,
456
426
  "multiple": false,
457
427
  "type": "option"
458
428
  }
459
429
  },
460
430
  "hasDynamicHelp": false,
461
431
  "hiddenAliases": [],
462
- "id": "hello",
463
- "pluginAlias": "kubun",
464
- "pluginName": "kubun",
465
- "pluginType": "core",
466
- "strict": true,
467
- "enableJsonFlag": false,
468
- "isESM": true,
469
- "relativePath": [
470
- "dist",
471
- "commands",
472
- "hello",
473
- "index.js"
474
- ]
475
- },
476
- "hello:world": {
477
- "aliases": [],
478
- "args": {},
479
- "description": "Say hello world",
480
- "examples": [
481
- "<%= config.bin %> <%= command.id %>\nhello world! (./src/commands/hello/world.ts)\n"
482
- ],
483
- "flags": {},
484
- "hasDynamicHelp": false,
485
- "hiddenAliases": [],
486
- "id": "hello:world",
432
+ "id": "graphql:schema",
487
433
  "pluginAlias": "kubun",
488
434
  "pluginName": "kubun",
489
435
  "pluginType": "core",
@@ -493,10 +439,10 @@
493
439
  "relativePath": [
494
440
  "dist",
495
441
  "commands",
496
- "hello",
497
- "world.js"
442
+ "graphql",
443
+ "schema.js"
498
444
  ]
499
445
  }
500
446
  },
501
- "version": "0.3.1"
447
+ "version": "0.3.3"
502
448
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kubun",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "license": "see LICENSE.md",
5
5
  "description": "Kubun CLI",
6
6
  "keywords": [],
@@ -34,33 +34,33 @@
34
34
  }
35
35
  },
36
36
  "dependencies": {
37
- "@enkaku/async": "^0.12.0",
37
+ "@enkaku/async": "^0.12.2",
38
38
  "@enkaku/codec": "^0.12.0",
39
- "@enkaku/http-server-transport": "^0.12.0",
40
- "@enkaku/server": "^0.12.0",
41
- "@enkaku/token": "^0.12.0",
42
- "@hono/node-server": "^1.13.7",
43
- "@oclif/core": "^4.0.33",
44
- "@oclif/plugin-help": "^6",
45
- "@oclif/plugin-plugins": "^5.4.19",
39
+ "@enkaku/http-server-transport": "^0.12.2",
40
+ "@enkaku/server": "^0.12.1",
41
+ "@enkaku/token": "0.12.3",
42
+ "@hono/node-server": "^1.19.6",
43
+ "@oclif/core": "^4.8.0",
44
+ "@oclif/plugin-help": "^6.2.36",
45
+ "@oclif/plugin-plugins": "^5.4.54",
46
46
  "get-port": "^7.1.0",
47
- "graphql": "^16.9.0",
48
- "ora": "^8.1.1",
49
- "@kubun/client": "^0.3.1",
50
- "@kubun/db-postgres": "^0.3.1",
51
- "@kubun/db-sqlite": "^0.3.1",
52
- "@kubun/db": "^0.3.1",
53
- "@kubun/protocol": "^0.3.1",
54
- "@kubun/graphql": "^0.3.1",
55
- "@kubun/server": "^0.3.1",
56
- "@kubun/http-client": "^0.3.0"
47
+ "graphql": "^16.12.0",
48
+ "ora": "^9.0.0",
49
+ "@kubun/client": "^0.3.7",
50
+ "@kubun/db": "^0.3.6",
51
+ "@kubun/db-postgres": "^0.3.2",
52
+ "@kubun/db-sqlite": "^0.3.3",
53
+ "@kubun/graphql": "^0.3.10",
54
+ "@kubun/http-client": "^0.3.0",
55
+ "@kubun/protocol": "^0.3.6",
56
+ "@kubun/server": "^0.3.8"
57
57
  },
58
58
  "devDependencies": {
59
- "@oclif/test": "^4.1.12",
60
- "oclif": "^4.17.42",
59
+ "@oclif/test": "^4.1.15",
60
+ "oclif": "^4.22.44",
61
61
  "shx": "^0.4.0",
62
62
  "ts-node": "^10",
63
- "typescript": "^5.8.3"
63
+ "typescript": "^5.9.3"
64
64
  },
65
65
  "scripts": {
66
66
  "kubun": "./bin/dev.js",
@@ -1,19 +0,0 @@
1
- import { Args, Command, Flags } from '@oclif/core'
2
- export default class Hello extends Command {
3
- static args = {
4
- person: Args.string({ description: 'Person to say hello to', required: true }),
5
- }
6
- static description = 'Say hello'
7
- static examples = [
8
- `<%= config.bin %> <%= command.id %> friend --from oclif
9
- hello friend from oclif! (./src/commands/hello/index.ts)
10
- `,
11
- ]
12
- static flags = {
13
- from: Flags.string({ char: 'f', description: 'Who is saying hello', required: true }),
14
- }
15
- async run() {
16
- const { args, flags } = await this.parse(Hello)
17
- this.log(`hello ${args.person} from ${flags.from}! (./src/commands/hello/index.ts)`)
18
- }
19
- }
@@ -1,12 +0,0 @@
1
- import { Command } from '@oclif/core'
2
- export default class World extends Command {
3
- static description = 'Say hello world'
4
- static examples = [
5
- `<%= config.bin %> <%= command.id %>
6
- hello world! (./src/commands/hello/world.ts)
7
- `,
8
- ]
9
- async run() {
10
- this.log('hello world! (./src/commands/hello/world.ts)')
11
- }
12
- }