@asterai/cli 0.4.0 → 0.6.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.
- package/README.md +43 -58
- package/dist/commands/deploy.d.ts +4 -6
- package/dist/commands/deploy.js +41 -64
- package/dist/commands/init.d.ts +8 -1
- package/dist/commands/init.js +37 -5
- package/dist/commands/pkg.d.ts +27 -0
- package/dist/commands/pkg.js +98 -0
- package/dist/const.d.ts +2 -0
- package/dist/const.js +2 -0
- package/init/rust/Cargo.toml +25 -0
- package/init/rust/build.sh +5 -0
- package/init/rust/deploy.sh +7 -0
- package/init/rust/plugin.wit +10 -0
- package/init/rust/src/bindings.rs +685 -0
- package/init/rust/src/lib.rs +16 -0
- package/init/typescript/package.json +26 -0
- package/init/typescript/plugin.ts +11 -0
- package/init/typescript/plugin.wit +12 -0
- package/init/typescript/tsconfig.json +11 -0
- package/oclif.manifest.json +79 -115
- package/package.json +4 -2
- package/asterai-init-plugin/package.json +0 -23
- package/asterai-init-plugin/plugin.asterai.proto +0 -22
- package/asterai-init-plugin/plugin.ts +0 -35
- package/asterai-init-plugin/tsconfig.json +0 -4
- package/dist/commands/build.d.ts +0 -23
- package/dist/commands/build.js +0 -139
- package/dist/commands/codegen.d.ts +0 -22
- package/dist/commands/codegen.js +0 -149
- package/dist/compile.d.ts +0 -7
- package/dist/compile.js +0 -25
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ $ npm install -g @asterai/cli
|
|
|
20
20
|
$ asterai COMMAND
|
|
21
21
|
running command...
|
|
22
22
|
$ asterai (--version)
|
|
23
|
-
@asterai/cli/0.
|
|
23
|
+
@asterai/cli/0.6.0 darwin-arm64 node-v20.12.2
|
|
24
24
|
$ asterai --help [COMMAND]
|
|
25
25
|
USAGE
|
|
26
26
|
$ asterai COMMAND
|
|
@@ -32,11 +32,10 @@ USAGE
|
|
|
32
32
|
|
|
33
33
|
<!-- commands -->
|
|
34
34
|
* [`asterai auth KEY`](#asterai-auth-key)
|
|
35
|
-
* [`asterai
|
|
36
|
-
* [`asterai codegen`](#asterai-codegen)
|
|
37
|
-
* [`asterai deploy [INPUT]`](#asterai-deploy-input)
|
|
35
|
+
* [`asterai deploy`](#asterai-deploy)
|
|
38
36
|
* [`asterai help [COMMAND]`](#asterai-help-command)
|
|
39
37
|
* [`asterai init [OUTDIR]`](#asterai-init-outdir)
|
|
38
|
+
* [`asterai pkg [INPUT]`](#asterai-pkg-input)
|
|
40
39
|
* [`asterai query`](#asterai-query)
|
|
41
40
|
|
|
42
41
|
## `asterai auth KEY`
|
|
@@ -54,111 +53,97 @@ EXAMPLES
|
|
|
54
53
|
$ asterai auth
|
|
55
54
|
```
|
|
56
55
|
|
|
57
|
-
_See code: [src/commands/auth.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.
|
|
56
|
+
_See code: [src/commands/auth.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.6.0/src/commands/auth.ts)_
|
|
58
57
|
|
|
59
|
-
## `asterai
|
|
58
|
+
## `asterai deploy`
|
|
60
59
|
|
|
61
|
-
|
|
60
|
+
uploads a plugin to asterai
|
|
62
61
|
|
|
63
62
|
```
|
|
64
63
|
USAGE
|
|
65
|
-
$ asterai
|
|
64
|
+
$ asterai deploy [-a <value>] [-e <value>] [-s] [--plugin <value>] [--pkg <value>]
|
|
66
65
|
|
|
67
66
|
FLAGS
|
|
68
|
-
-
|
|
67
|
+
-a, --agent=<value> agent ID to immediately activate this plugin for
|
|
68
|
+
-e, --endpoint=<value> [default: https://api.asterai.io]
|
|
69
|
+
-s, --staging
|
|
70
|
+
--pkg=<value> [default: package.wasm] package WASM path
|
|
71
|
+
--plugin=<value> [default: plugin.wasm] plugin WASM path
|
|
69
72
|
|
|
70
73
|
DESCRIPTION
|
|
71
|
-
|
|
74
|
+
uploads a plugin to asterai
|
|
72
75
|
|
|
73
76
|
EXAMPLES
|
|
74
|
-
$ asterai
|
|
77
|
+
$ asterai deploy --app 66a46b12-b1a7-4b72-a64a-0e4fe21902b6
|
|
75
78
|
```
|
|
76
79
|
|
|
77
|
-
_See code: [src/commands/
|
|
80
|
+
_See code: [src/commands/deploy.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.6.0/src/commands/deploy.ts)_
|
|
78
81
|
|
|
79
|
-
## `asterai
|
|
82
|
+
## `asterai help [COMMAND]`
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
Display help for asterai.
|
|
82
85
|
|
|
83
86
|
```
|
|
84
87
|
USAGE
|
|
85
|
-
$ asterai
|
|
88
|
+
$ asterai help [COMMAND...] [-n]
|
|
89
|
+
|
|
90
|
+
ARGUMENTS
|
|
91
|
+
COMMAND... Command to show help for.
|
|
86
92
|
|
|
87
93
|
FLAGS
|
|
88
|
-
-
|
|
89
|
-
-l, --language=<value> [default: js] language of generated typings
|
|
90
|
-
-m, --manifest=<value> [default: plugin.asterai.proto] manifest path
|
|
91
|
-
-o, --outputDir=<value> [default: generated] output directory
|
|
92
|
-
-s, --staging use staging endpoint
|
|
94
|
+
-n, --nested-commands Include all nested commands in the output.
|
|
93
95
|
|
|
94
96
|
DESCRIPTION
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
EXAMPLES
|
|
98
|
-
$ asterai codegen
|
|
97
|
+
Display help for asterai.
|
|
99
98
|
```
|
|
100
99
|
|
|
101
|
-
_See code: [
|
|
100
|
+
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.0/src/commands/help.ts)_
|
|
102
101
|
|
|
103
|
-
## `asterai
|
|
102
|
+
## `asterai init [OUTDIR]`
|
|
104
103
|
|
|
105
|
-
|
|
104
|
+
Initialise a new plugin project
|
|
106
105
|
|
|
107
106
|
```
|
|
108
107
|
USAGE
|
|
109
|
-
$ asterai
|
|
108
|
+
$ asterai init [OUTDIR] [--typescript] [--rust]
|
|
110
109
|
|
|
111
110
|
FLAGS
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
-m, --manifest=<value> [default: plugin.asterai.proto] manifest path
|
|
115
|
-
-s, --staging
|
|
111
|
+
--rust init a the plugin project in rust
|
|
112
|
+
--typescript init a the plugin project in typescript
|
|
116
113
|
|
|
117
114
|
DESCRIPTION
|
|
118
|
-
|
|
115
|
+
Initialise a new plugin project
|
|
119
116
|
|
|
120
117
|
EXAMPLES
|
|
121
|
-
$ asterai
|
|
118
|
+
$ asterai init project-name
|
|
122
119
|
```
|
|
123
120
|
|
|
124
|
-
_See code: [src/commands/
|
|
121
|
+
_See code: [src/commands/init.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.6.0/src/commands/init.ts)_
|
|
125
122
|
|
|
126
|
-
## `asterai
|
|
123
|
+
## `asterai pkg [INPUT]`
|
|
127
124
|
|
|
128
|
-
|
|
125
|
+
bundles the WIT into a binary WASM package
|
|
129
126
|
|
|
130
127
|
```
|
|
131
128
|
USAGE
|
|
132
|
-
$ asterai
|
|
129
|
+
$ asterai pkg [INPUT] [-o <value>] [-w <value>] [-e <value>]
|
|
133
130
|
|
|
134
131
|
ARGUMENTS
|
|
135
|
-
|
|
132
|
+
INPUT [default: plugin.wit] path to the plugin's WIT file
|
|
136
133
|
|
|
137
134
|
FLAGS
|
|
138
|
-
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
Display help for asterai.
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.0.22/src/commands/help.ts)_
|
|
145
|
-
|
|
146
|
-
## `asterai init [OUTDIR]`
|
|
147
|
-
|
|
148
|
-
Initialise a new plugin project
|
|
149
|
-
|
|
150
|
-
```
|
|
151
|
-
USAGE
|
|
152
|
-
$ asterai init [OUTDIR]
|
|
135
|
+
-e, --endpoint=<value> [default: https://api.asterai.io]
|
|
136
|
+
-o, --output=<value> [default: package.wasm] output file name for the binary WASM package
|
|
137
|
+
-w, --wit=<value> [default: package.wit] output package converted to the WIT format
|
|
153
138
|
|
|
154
139
|
DESCRIPTION
|
|
155
|
-
|
|
140
|
+
bundles the WIT into a binary WASM package
|
|
156
141
|
|
|
157
142
|
EXAMPLES
|
|
158
|
-
$ asterai
|
|
143
|
+
$ asterai pkg
|
|
159
144
|
```
|
|
160
145
|
|
|
161
|
-
_See code: [src/commands/
|
|
146
|
+
_See code: [src/commands/pkg.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.6.0/src/commands/pkg.ts)_
|
|
162
147
|
|
|
163
148
|
## `asterai query`
|
|
164
149
|
|
|
@@ -181,5 +166,5 @@ EXAMPLES
|
|
|
181
166
|
$ asterai query
|
|
182
167
|
```
|
|
183
168
|
|
|
184
|
-
_See code: [src/commands/query.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.
|
|
169
|
+
_See code: [src/commands/query.ts](https://github.com/asterai-io/asterai-sdk/blob/v0.6.0/src/commands/query.ts)_
|
|
185
170
|
<!-- commandsstop -->
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
2
|
export default class Deploy extends Command {
|
|
3
|
-
static args: {
|
|
4
|
-
input: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
5
|
-
};
|
|
3
|
+
static args: {};
|
|
6
4
|
static description: string;
|
|
7
5
|
static examples: string[];
|
|
8
6
|
static flags: {
|
|
9
|
-
|
|
10
|
-
manifest: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
7
|
+
agent: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
8
|
endpoint: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
12
9
|
staging: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
|
+
plugin: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
+
pkg: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
13
12
|
};
|
|
14
13
|
run(): Promise<void>;
|
|
15
14
|
}
|
|
16
|
-
export declare const mergeProtoImports: (proto: string, protoPath: string, excludeSdk?: boolean, excludeSyntaxDefinition?: boolean, n?: number) => string;
|
package/dist/commands/deploy.js
CHANGED
|
@@ -1,59 +1,57 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Command, Flags } from "@oclif/core";
|
|
2
2
|
import fs from "fs";
|
|
3
|
-
import path from "path";
|
|
4
3
|
import FormData from "form-data";
|
|
5
4
|
import axios from "axios";
|
|
6
5
|
import { getConfigValue } from "../config.js";
|
|
7
|
-
import {
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
import { BASE_API_URL, BASE_API_URL_STAGING } from "../const.js";
|
|
7
|
+
import path from "path";
|
|
8
|
+
// If the input file doesn't exist, try looking into this dir.
|
|
9
|
+
const RETRY_FIND_FILE_DIR = "build/";
|
|
10
10
|
export default class Deploy extends Command {
|
|
11
|
-
static args = {
|
|
12
|
-
|
|
13
|
-
default: "plugin.ts",
|
|
14
|
-
}),
|
|
15
|
-
};
|
|
16
|
-
static description = "compiles and uploads the plugin to asterai";
|
|
11
|
+
static args = {};
|
|
12
|
+
static description = "uploads a plugin to asterai";
|
|
17
13
|
static examples = [
|
|
18
14
|
`<%= config.bin %> <%= command.id %> --app 66a46b12-b1a7-4b72-a64a-0e4fe21902b6`,
|
|
19
15
|
];
|
|
20
16
|
static flags = {
|
|
21
|
-
|
|
17
|
+
agent: Flags.string({
|
|
22
18
|
char: "a",
|
|
23
|
-
description: "
|
|
24
|
-
required:
|
|
25
|
-
}),
|
|
26
|
-
manifest: Flags.string({
|
|
27
|
-
char: "m",
|
|
28
|
-
description: "manifest path",
|
|
29
|
-
default: "plugin.asterai.proto",
|
|
19
|
+
description: "agent ID to immediately activate this plugin for",
|
|
20
|
+
required: false,
|
|
30
21
|
}),
|
|
31
22
|
endpoint: Flags.string({
|
|
32
23
|
char: "e",
|
|
33
|
-
default:
|
|
24
|
+
default: BASE_API_URL,
|
|
34
25
|
}),
|
|
35
26
|
staging: Flags.boolean({
|
|
36
27
|
char: "s",
|
|
37
28
|
}),
|
|
29
|
+
plugin: Flags.string({
|
|
30
|
+
description: "plugin WASM path",
|
|
31
|
+
default: "plugin.wasm",
|
|
32
|
+
}),
|
|
33
|
+
pkg: Flags.string({
|
|
34
|
+
description: "package WASM path",
|
|
35
|
+
default: "package.wasm",
|
|
36
|
+
}),
|
|
38
37
|
};
|
|
39
38
|
async run() {
|
|
40
|
-
const {
|
|
41
|
-
|
|
42
|
-
await deploy(output, flags);
|
|
39
|
+
const { flags } = await this.parse(Deploy);
|
|
40
|
+
await deploy(flags);
|
|
43
41
|
}
|
|
44
42
|
}
|
|
45
|
-
const deploy = async (
|
|
43
|
+
const deploy = async (flags) => {
|
|
46
44
|
const form = new FormData();
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
form.append("
|
|
54
|
-
const
|
|
45
|
+
if (flags.agent) {
|
|
46
|
+
form.append("agent_id", flags.agent);
|
|
47
|
+
}
|
|
48
|
+
const plugin = readFile(flags.plugin);
|
|
49
|
+
const pkg = readFile(flags.pkg);
|
|
50
|
+
form.append("plugin.wasm", plugin);
|
|
51
|
+
form.append("package.wasm", pkg);
|
|
52
|
+
const baseApiUrl = flags.staging ? BASE_API_URL_STAGING : flags.endpoint;
|
|
55
53
|
await axios({
|
|
56
|
-
url
|
|
54
|
+
url: `${baseApiUrl}/v1/plugin`,
|
|
57
55
|
method: "put",
|
|
58
56
|
data: form,
|
|
59
57
|
headers: {
|
|
@@ -64,38 +62,17 @@ const deploy = async (args, flags) => {
|
|
|
64
62
|
.then(() => console.log("done"))
|
|
65
63
|
.catch(logRequestError);
|
|
66
64
|
};
|
|
67
|
-
export const mergeProtoImports = (proto, protoPath, excludeSdk = true, excludeSyntaxDefinition = true, n = 0) => {
|
|
68
|
-
let mergedManifestString = "";
|
|
69
|
-
const lines = proto.split("\n");
|
|
70
|
-
for (let line of lines) {
|
|
71
|
-
line = line.trim();
|
|
72
|
-
const isSyntaxLine = line.startsWith("syntax");
|
|
73
|
-
if (isSyntaxLine && (excludeSyntaxDefinition || n > 1)) {
|
|
74
|
-
continue;
|
|
75
|
-
}
|
|
76
|
-
const isImportLine = line.startsWith("import");
|
|
77
|
-
if (!isImportLine) {
|
|
78
|
-
mergedManifestString = `${mergedManifestString}\n${line}`;
|
|
79
|
-
continue;
|
|
80
|
-
}
|
|
81
|
-
const importLine = line.replaceAll("'", '"');
|
|
82
|
-
const pathStart = importLine.indexOf('"') + 1;
|
|
83
|
-
const pathEnd = importLine.lastIndexOf('"');
|
|
84
|
-
const pathRelative = importLine.substring(pathStart, pathEnd);
|
|
85
|
-
const isSdkImport = pathRelative.startsWith("node_modules/@asterai/sdk");
|
|
86
|
-
if (isSdkImport && excludeSdk) {
|
|
87
|
-
// Asterai protobuf definitions should not be uploaded
|
|
88
|
-
// as part of the plugin manifest.
|
|
89
|
-
continue;
|
|
90
|
-
}
|
|
91
|
-
const pathAbsolute = path.join(path.dirname(protoPath), pathRelative);
|
|
92
|
-
const importProto = fs.readFileSync(pathAbsolute, { encoding: "utf8" });
|
|
93
|
-
const importProtoMerged = mergeProtoImports(importProto, pathAbsolute, excludeSdk, excludeSyntaxDefinition, n + 1);
|
|
94
|
-
mergedManifestString = `${mergedManifestString}\n${importProtoMerged}`;
|
|
95
|
-
}
|
|
96
|
-
return mergedManifestString.trim();
|
|
97
|
-
};
|
|
98
65
|
const logRequestError = (e) => {
|
|
99
66
|
const info = e.response?.data ?? e;
|
|
100
67
|
console.log("request error:", info);
|
|
101
68
|
};
|
|
69
|
+
const readFile = (relativePath) => {
|
|
70
|
+
if (fs.existsSync(relativePath)) {
|
|
71
|
+
return fs.readFileSync(relativePath);
|
|
72
|
+
}
|
|
73
|
+
const retryPath = path.join(RETRY_FIND_FILE_DIR, relativePath);
|
|
74
|
+
if (fs.existsSync(retryPath)) {
|
|
75
|
+
return fs.readFileSync(retryPath);
|
|
76
|
+
}
|
|
77
|
+
throw new Error(`file not found: ${relativePath}`);
|
|
78
|
+
};
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { Command } from "@oclif/core";
|
|
2
|
+
export type InitFlags = {
|
|
3
|
+
rust?: boolean;
|
|
4
|
+
typescript?: boolean;
|
|
5
|
+
};
|
|
2
6
|
export default class Codegen extends Command {
|
|
3
7
|
static args: {
|
|
4
8
|
outDir: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
5
9
|
};
|
|
6
10
|
static description: string;
|
|
7
11
|
static examples: string[];
|
|
8
|
-
static flags: {
|
|
12
|
+
static flags: {
|
|
13
|
+
typescript: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
14
|
+
rust: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
15
|
+
};
|
|
9
16
|
run(): Promise<void>;
|
|
10
17
|
}
|
package/dist/commands/init.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { Args, Command } from "@oclif/core";
|
|
1
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
2
2
|
import path from "path";
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import url from "url";
|
|
5
5
|
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
|
|
6
|
-
const
|
|
6
|
+
const SOURCE_DIR_TYPESCRIPT = path.join(__dirname, "../../init/typescript");
|
|
7
|
+
const SOURCE_DIR_RUST = path.join(__dirname, "../../init/rust");
|
|
7
8
|
export default class Codegen extends Command {
|
|
8
9
|
static args = {
|
|
9
10
|
outDir: Args.string({
|
|
@@ -12,10 +13,41 @@ export default class Codegen extends Command {
|
|
|
12
13
|
};
|
|
13
14
|
static description = "Initialise a new plugin project";
|
|
14
15
|
static examples = [`<%= config.bin %> <%= command.id %> project-name`];
|
|
15
|
-
static flags = {
|
|
16
|
+
static flags = {
|
|
17
|
+
typescript: Flags.boolean({
|
|
18
|
+
default: undefined,
|
|
19
|
+
description: "init a the plugin project in typescript",
|
|
20
|
+
}),
|
|
21
|
+
rust: Flags.boolean({
|
|
22
|
+
default: false,
|
|
23
|
+
description: "init a the plugin project in rust",
|
|
24
|
+
}),
|
|
25
|
+
};
|
|
16
26
|
async run() {
|
|
17
|
-
const { args } = await this.parse(Codegen);
|
|
27
|
+
const { args, flags } = await this.parse(Codegen);
|
|
28
|
+
assertOneLanguageFlag([flags.typescript, flags.rust]);
|
|
18
29
|
const outDir = path.resolve(args.outDir);
|
|
19
|
-
|
|
30
|
+
const sourceDir = getSourceDirByFlag(flags);
|
|
31
|
+
fs.cpSync(sourceDir, outDir, { recursive: true });
|
|
20
32
|
}
|
|
21
33
|
}
|
|
34
|
+
const assertOneLanguageFlag = (flags) => {
|
|
35
|
+
const undefinedCount = flags.reduce((acc, curr) => (curr === undefined ? acc + 1 : acc), 0);
|
|
36
|
+
const trueCount = flags.reduce((acc, curr) => (curr ? acc + 1 : acc), 0);
|
|
37
|
+
if (trueCount === 0 && undefinedCount !== 1) {
|
|
38
|
+
throw new Error("one language flag must be set");
|
|
39
|
+
}
|
|
40
|
+
if (trueCount > 1) {
|
|
41
|
+
throw new Error("only one language flag can be set");
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const getSourceDirByFlag = (flags) => {
|
|
45
|
+
if (flags.rust) {
|
|
46
|
+
return SOURCE_DIR_RUST;
|
|
47
|
+
}
|
|
48
|
+
// Typescript is the default option.
|
|
49
|
+
if (flags.typescript === true || flags.typescript === undefined) {
|
|
50
|
+
return SOURCE_DIR_TYPESCRIPT;
|
|
51
|
+
}
|
|
52
|
+
throw new Error("Invalid flags configuration.");
|
|
53
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
export type PkgArgs = {
|
|
3
|
+
input: string;
|
|
4
|
+
};
|
|
5
|
+
export type PkgFlags = {
|
|
6
|
+
endpoint: string;
|
|
7
|
+
output: string;
|
|
8
|
+
wit?: string;
|
|
9
|
+
};
|
|
10
|
+
export type PkgOutput = {
|
|
11
|
+
outputFile: string;
|
|
12
|
+
witPath: string;
|
|
13
|
+
};
|
|
14
|
+
export default class Pkg extends Command {
|
|
15
|
+
static args: {
|
|
16
|
+
input: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
|
17
|
+
};
|
|
18
|
+
static flags: {
|
|
19
|
+
output: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
20
|
+
wit: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
21
|
+
endpoint: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
22
|
+
};
|
|
23
|
+
static description: string;
|
|
24
|
+
static examples: string[];
|
|
25
|
+
run(): Promise<void>;
|
|
26
|
+
}
|
|
27
|
+
export declare const pkg: (args: PkgArgs, flags: PkgFlags) => Promise<PkgOutput>;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Args, Command, Flags } from "@oclif/core";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import fs from "fs/promises";
|
|
4
|
+
import fsSync from "fs";
|
|
5
|
+
import { BASE_API_URL } from "../const.js";
|
|
6
|
+
import axios from "axios";
|
|
7
|
+
import FormData from "form-data";
|
|
8
|
+
import { getConfigValue } from "../config.js";
|
|
9
|
+
export default class Pkg extends Command {
|
|
10
|
+
static args = {
|
|
11
|
+
input: Args.string({
|
|
12
|
+
default: "plugin.wit",
|
|
13
|
+
description: "path to the plugin's WIT file",
|
|
14
|
+
}),
|
|
15
|
+
};
|
|
16
|
+
static flags = {
|
|
17
|
+
output: Flags.string({
|
|
18
|
+
char: "o",
|
|
19
|
+
default: "package.wasm",
|
|
20
|
+
description: "output file name for the binary WASM package",
|
|
21
|
+
}),
|
|
22
|
+
wit: Flags.string({
|
|
23
|
+
char: "w",
|
|
24
|
+
default: "package.wit",
|
|
25
|
+
description: "output package converted to the WIT format",
|
|
26
|
+
}),
|
|
27
|
+
endpoint: Flags.string({
|
|
28
|
+
char: "e",
|
|
29
|
+
default: BASE_API_URL,
|
|
30
|
+
}),
|
|
31
|
+
};
|
|
32
|
+
static description = "bundles the WIT into a binary WASM package";
|
|
33
|
+
static examples = [`<%= config.bin %> <%= command.id %>`];
|
|
34
|
+
async run() {
|
|
35
|
+
const { args, flags } = await this.parse(Pkg);
|
|
36
|
+
await pkg(args, flags);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export const pkg = async (args, flags) => {
|
|
40
|
+
const witPath = path.resolve(args.input);
|
|
41
|
+
if (!fsSync.existsSync(witPath)) {
|
|
42
|
+
throw new Error(`WIT file not found at ${witPath}`);
|
|
43
|
+
}
|
|
44
|
+
const baseDir = path.dirname(witPath);
|
|
45
|
+
const outputFile = path.join(baseDir, flags.output);
|
|
46
|
+
const form = new FormData();
|
|
47
|
+
form.append("package.wit", await fs.readFile(witPath));
|
|
48
|
+
const response = await axios({
|
|
49
|
+
url: `${flags.endpoint}/v1/pkg`,
|
|
50
|
+
method: "post",
|
|
51
|
+
data: form,
|
|
52
|
+
headers: {
|
|
53
|
+
Authorization: getConfigValue("key"),
|
|
54
|
+
...form.getHeaders(),
|
|
55
|
+
},
|
|
56
|
+
responseType: "arraybuffer",
|
|
57
|
+
}).catch(catchAxiosError);
|
|
58
|
+
validateResponseStatus(response.status);
|
|
59
|
+
await fs.writeFile(outputFile, Buffer.from(response.data), {
|
|
60
|
+
encoding: "binary",
|
|
61
|
+
});
|
|
62
|
+
if (flags.wit) {
|
|
63
|
+
await wasm2wit(flags.endpoint, outputFile, path.join(baseDir, flags.wit));
|
|
64
|
+
}
|
|
65
|
+
return {
|
|
66
|
+
outputFile,
|
|
67
|
+
witPath,
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
const wasm2wit = async (endpoint, inputFilePath, outputFilePath) => {
|
|
71
|
+
const form = new FormData();
|
|
72
|
+
form.append("package.wasm", await fs.readFile(inputFilePath));
|
|
73
|
+
const response = await axios({
|
|
74
|
+
url: `${endpoint}/v1/wasm2wit`,
|
|
75
|
+
method: "post",
|
|
76
|
+
data: form,
|
|
77
|
+
headers: {
|
|
78
|
+
Authorization: getConfigValue("key"),
|
|
79
|
+
...form.getHeaders(),
|
|
80
|
+
},
|
|
81
|
+
responseType: "text",
|
|
82
|
+
});
|
|
83
|
+
validateResponseStatus(response.status);
|
|
84
|
+
await fs.writeFile(outputFilePath, response.data, { encoding: "utf8" });
|
|
85
|
+
};
|
|
86
|
+
const validateResponseStatus = (status) => {
|
|
87
|
+
if (status < 200 || status >= 300) {
|
|
88
|
+
throw new Error("request failed");
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
const catchAxiosError = (error) => {
|
|
92
|
+
const data = error.response?.data?.toString() ?? "";
|
|
93
|
+
if (axios.isAxiosError(error) && data.length > 0) {
|
|
94
|
+
const errorMessage = data.replace(/\\n/g, "\n");
|
|
95
|
+
throw new Error(`Request failed: ${errorMessage}`);
|
|
96
|
+
}
|
|
97
|
+
throw new Error("Request failed");
|
|
98
|
+
};
|
package/dist/const.d.ts
ADDED
package/dist/const.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "plugin"
|
|
3
|
+
# Note that this version does not matter for the plugin,
|
|
4
|
+
# only the one in plugin.wit is used.
|
|
5
|
+
version = "0.0.0"
|
|
6
|
+
edition = "2021"
|
|
7
|
+
publish = false
|
|
8
|
+
|
|
9
|
+
[dependencies]
|
|
10
|
+
wit-bindgen-rt = { version = "0.39.0", features = ["bitflags"] }
|
|
11
|
+
|
|
12
|
+
[lib]
|
|
13
|
+
crate-type = ["cdylib"]
|
|
14
|
+
|
|
15
|
+
[profile.release]
|
|
16
|
+
codegen-units = 1
|
|
17
|
+
opt-level = "s"
|
|
18
|
+
debug = false
|
|
19
|
+
strip = true
|
|
20
|
+
lto = true
|
|
21
|
+
|
|
22
|
+
[package.metadata.component]
|
|
23
|
+
package = "your-username:plugin"
|
|
24
|
+
|
|
25
|
+
[package.metadata.component.dependencies]
|