@nextclaw/app-runtime 0.4.1 → 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 +29 -4
- package/dist/bundle/app-bundle.service.js +14 -8
- package/dist/bundle/app-bundle.types.d.ts +2 -0
- package/dist/cli/app-runtime-cli.service.d.ts +3 -0
- package/dist/cli/app-runtime-cli.service.js +70 -2
- package/dist/cli/app-runtime-options.service.d.ts +10 -1
- package/dist/cli/app-runtime-options.service.js +39 -2
- package/dist/commands/create.controller.d.ts +2 -1
- package/dist/commands/create.controller.js +3 -2
- package/dist/commands/inspect.controller.js +2 -1
- package/dist/commands/run.controller.js +25 -7
- package/dist/commands/validate-publish.controller.d.ts +15 -0
- package/dist/commands/validate-publish.controller.js +31 -0
- package/dist/host/app-host.service.d.ts +3 -1
- package/dist/host/app-host.service.js +5 -1
- package/dist/host/app-instance.service.js +1 -0
- package/dist/index.d.ts +11 -3
- package/dist/index.js +9 -1
- package/dist/install/app-installation.service.js +1 -0
- package/dist/install/app-installation.types.d.ts +1 -0
- package/dist/manifest/app-manifest.service.js +9 -3
- package/dist/manifest/app-manifest.types.d.ts +9 -3
- package/dist/package.js +1 -1
- package/dist/publish/app-publish-validation.service.d.ts +37 -0
- package/dist/publish/app-publish-validation.service.js +76 -0
- package/dist/runtime/app-build.service.d.ts +24 -0
- package/dist/runtime/app-build.service.js +55 -0
- package/dist/runtime/app-runtime-toolchain.service.d.ts +30 -0
- package/dist/runtime/app-runtime-toolchain.service.js +96 -0
- package/dist/runtime/wasm-main-runner.service.js +1 -0
- package/dist/runtime/wasmtime-wasi-http-component.service.d.ts +24 -0
- package/dist/runtime/wasmtime-wasi-http-component.service.js +129 -0
- package/dist/scaffold/app-scaffold.service.d.ts +13 -2
- package/dist/scaffold/app-scaffold.service.js +39 -2
- package/dist/scaffold/app-ts-http-lite-scaffold-template.service.d.ts +18 -0
- package/dist/scaffold/app-ts-http-lite-scaffold-template.service.js +267 -0
- package/dist/scaffold/app-ts-http-scaffold-template.service.d.ts +25 -0
- package/dist/scaffold/app-ts-http-scaffold-template.service.js +496 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,9 +6,12 @@
|
|
|
6
6
|
|
|
7
7
|
- `napp create <app-dir>`:生成一个最小可跑的微应用骨架
|
|
8
8
|
- `napp inspect <app-dir>`:校验应用目录与 manifest
|
|
9
|
+
- `napp doctor`:检查本机 NApp/WASI HTTP 开发运行环境
|
|
10
|
+
- `napp build <app-dir> --install`:安装模板依赖并构建 TS/WASI HTTP 后端
|
|
9
11
|
- `napp run <app-dir|app-id>`:启动本地宿主,支持目录运行和已安装应用运行
|
|
10
12
|
- `napp dev <app-dir>`:当前等价于 `run`
|
|
11
13
|
- `napp pack <app-dir>`:把应用目录打成 `.napp` bundle
|
|
14
|
+
- `napp validate-publish <app-dir>`:本地做发布前校验并输出体积/包内容 warning
|
|
12
15
|
- `napp publish <app-dir>`:把应用目录发布到官方 apps registry
|
|
13
16
|
- `napp install <app-dir|bundle.napp|app-id[@version]>`:从本地或 registry 安装应用
|
|
14
17
|
- `napp update <app-id>`:更新已安装应用
|
|
@@ -33,7 +36,7 @@ napp --help
|
|
|
33
36
|
napp --version
|
|
34
37
|
```
|
|
35
38
|
|
|
36
|
-
|
|
39
|
+
当前版本先聚焦“独立可运行的微应用宿主 + 可分发、可安装、可更新、可授权的 CLI/runtime 闭环”。普通用户入口推荐通过 NextClaw 的 `nextclaw-app-runtime` skill 编排这些命令。
|
|
37
40
|
|
|
38
41
|
## 应用目录
|
|
39
42
|
|
|
@@ -41,6 +44,8 @@ napp --version
|
|
|
41
44
|
manifest.json
|
|
42
45
|
main/
|
|
43
46
|
app.wasm
|
|
47
|
+
package.json # ts-http / ts-http-lite 模板存在
|
|
48
|
+
src/ # ts-http / ts-http-lite 模板存在
|
|
44
49
|
ui/
|
|
45
50
|
index.html
|
|
46
51
|
assets/
|
|
@@ -48,11 +53,12 @@ assets/
|
|
|
48
53
|
|
|
49
54
|
## 当前 MVP 范围
|
|
50
55
|
|
|
51
|
-
- `main` 执行形态:`wasm`
|
|
56
|
+
- `main` 执行形态:`wasm` 或 `wasi-http-component`
|
|
52
57
|
- UI 装载:本地静态服务
|
|
53
58
|
- 宿主桥接:`/__napp/*`
|
|
59
|
+
- WASI HTTP 业务 API:`/api/*`
|
|
54
60
|
- 权限词汇:`documentAccess`、`allowedDomains`、`storage`、`capabilities`
|
|
55
|
-
- 当前 Wasm 执行底座:Node 原生 `WebAssembly`
|
|
61
|
+
- 当前 Wasm 执行底座:Node 原生 `WebAssembly` 与 Wasmtime `serve`
|
|
56
62
|
- 分发包形态:`.napp`(底层为 zip)
|
|
57
63
|
- 安装目录:`~/.nextclaw/apps/packages/<app-id>/<version>/`
|
|
58
64
|
- 用户数据目录:`~/.nextclaw/apps/data/<app-id>/`
|
|
@@ -65,12 +71,26 @@ assets/
|
|
|
65
71
|
开发者工作流:
|
|
66
72
|
|
|
67
73
|
```bash
|
|
68
|
-
napp
|
|
74
|
+
napp doctor
|
|
75
|
+
napp create ./my-first-napp --template ts-http
|
|
76
|
+
napp build ./my-first-napp --install
|
|
69
77
|
napp inspect ./my-first-napp
|
|
78
|
+
napp validate-publish ./my-first-napp
|
|
79
|
+
napp run ./my-first-napp --data ./my-first-napp/.napp/data
|
|
70
80
|
napp pack ./my-first-napp
|
|
71
81
|
napp publish ./my-first-napp
|
|
72
82
|
```
|
|
73
83
|
|
|
84
|
+
体积优先工作流:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
napp doctor
|
|
88
|
+
napp create ./my-small-napp --template ts-http-lite
|
|
89
|
+
napp build ./my-small-napp --install
|
|
90
|
+
napp validate-publish ./my-small-napp
|
|
91
|
+
napp run ./my-small-napp --data ./my-small-napp/.napp/data
|
|
92
|
+
```
|
|
93
|
+
|
|
74
94
|
本地安装工作流:
|
|
75
95
|
|
|
76
96
|
```bash
|
|
@@ -112,6 +132,11 @@ napp permissions nextclaw.my-first-napp
|
|
|
112
132
|
napp run nextclaw.my-first-napp
|
|
113
133
|
```
|
|
114
134
|
|
|
135
|
+
模板选择建议:
|
|
136
|
+
|
|
137
|
+
- `ts-http`:默认推荐,开发体验优先,适合大多数普通前后端小应用
|
|
138
|
+
- `ts-http-lite`:体积优先,继续走官方 WASI HTTP 路线,但不使用默认 Hono 路由层
|
|
139
|
+
|
|
115
140
|
已有示例应用:
|
|
116
141
|
|
|
117
142
|
```bash
|
|
@@ -10,7 +10,7 @@ var AppBundleService = class {
|
|
|
10
10
|
}
|
|
11
11
|
packAppDirectory = async (params) => {
|
|
12
12
|
const bundle = await this.manifestService.load(params.appDirectory);
|
|
13
|
-
const appFiles = await this.collectAppFiles(bundle
|
|
13
|
+
const { appFiles, filePaths } = await this.collectAppFiles(bundle);
|
|
14
14
|
const metadata = this.buildMetadata(bundle.manifest.id, bundle.manifest.name, bundle.manifest.version);
|
|
15
15
|
const bundleJsonPath = ".napp/bundle.json";
|
|
16
16
|
const checksumsJsonPath = ".napp/checksums.json";
|
|
@@ -30,7 +30,9 @@ var AppBundleService = class {
|
|
|
30
30
|
await writeFile(outputPath, Buffer.from(archiveBytes));
|
|
31
31
|
return {
|
|
32
32
|
bundlePath: outputPath,
|
|
33
|
-
metadata
|
|
33
|
+
metadata,
|
|
34
|
+
sizeBytes: archiveBytes.byteLength,
|
|
35
|
+
filePaths
|
|
34
36
|
};
|
|
35
37
|
};
|
|
36
38
|
extractBundle = async (params) => {
|
|
@@ -59,15 +61,19 @@ var AppBundleService = class {
|
|
|
59
61
|
checksums
|
|
60
62
|
};
|
|
61
63
|
};
|
|
62
|
-
collectAppFiles = async (
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
await this.collectDirectoryPaths(
|
|
66
|
-
await this.collectDirectoryPaths(
|
|
64
|
+
collectAppFiles = async (bundle) => {
|
|
65
|
+
const appDirectory = bundle.appDirectory;
|
|
66
|
+
const filePaths = new Set([path.relative(appDirectory, bundle.manifestPath), path.relative(appDirectory, bundle.mainEntryPath)]);
|
|
67
|
+
await this.collectDirectoryPaths(bundle.uiDirectoryPath, appDirectory, filePaths);
|
|
68
|
+
await this.collectDirectoryPaths(bundle.assetsDirectoryPath, appDirectory, filePaths);
|
|
69
|
+
if (bundle.iconPath) filePaths.add(path.relative(appDirectory, bundle.iconPath));
|
|
67
70
|
const sortedPaths = Array.from(filePaths).sort((left, right) => left.localeCompare(right));
|
|
68
71
|
const appFiles = {};
|
|
69
72
|
for (const relativePath of sortedPaths) appFiles[relativePath] = new Uint8Array(await readFile(path.join(appDirectory, relativePath)));
|
|
70
|
-
return
|
|
73
|
+
return {
|
|
74
|
+
appFiles,
|
|
75
|
+
filePaths: sortedPaths
|
|
76
|
+
};
|
|
71
77
|
};
|
|
72
78
|
collectDirectoryPaths = async (directoryPath, appDirectory, filePaths) => {
|
|
73
79
|
try {
|
|
@@ -8,10 +8,13 @@ declare class AppRuntimeCliService {
|
|
|
8
8
|
private dispatch;
|
|
9
9
|
private handleCreate;
|
|
10
10
|
private handleInspect;
|
|
11
|
+
private handleBuild;
|
|
12
|
+
private handleDoctor;
|
|
11
13
|
private handleRun;
|
|
12
14
|
private handleDev;
|
|
13
15
|
private handlePack;
|
|
14
16
|
private handlePublish;
|
|
17
|
+
private handleValidatePublish;
|
|
15
18
|
private handleInstall;
|
|
16
19
|
private handleUpdate;
|
|
17
20
|
private handleUninstall;
|
|
@@ -14,6 +14,9 @@ import { RegistryCommand } from "../commands/registry.controller.js";
|
|
|
14
14
|
import { RevokeCommand } from "../commands/revoke.controller.js";
|
|
15
15
|
import { UninstallCommand } from "../commands/uninstall.controller.js";
|
|
16
16
|
import { UpdateCommand } from "../commands/update.controller.js";
|
|
17
|
+
import { ValidatePublishCommand } from "../commands/validate-publish.controller.js";
|
|
18
|
+
import { AppRuntimeToolchainService } from "../runtime/app-runtime-toolchain.service.js";
|
|
19
|
+
import { AppBuildService } from "../runtime/app-build.service.js";
|
|
17
20
|
import { AppRuntimeOptionsService } from "./app-runtime-options.service.js";
|
|
18
21
|
//#region src/cli/app-runtime-cli.service.ts
|
|
19
22
|
var AppRuntimeCliService = class {
|
|
@@ -44,6 +47,12 @@ var AppRuntimeCliService = class {
|
|
|
44
47
|
case "inspect":
|
|
45
48
|
await this.handleInspect(restArgs);
|
|
46
49
|
return;
|
|
50
|
+
case "build":
|
|
51
|
+
await this.handleBuild(restArgs);
|
|
52
|
+
return;
|
|
53
|
+
case "doctor":
|
|
54
|
+
await this.handleDoctor(restArgs);
|
|
55
|
+
return;
|
|
47
56
|
case "run":
|
|
48
57
|
await this.handleRun(restArgs);
|
|
49
58
|
return;
|
|
@@ -56,6 +65,9 @@ var AppRuntimeCliService = class {
|
|
|
56
65
|
case "publish":
|
|
57
66
|
await this.handlePublish(restArgs);
|
|
58
67
|
return;
|
|
68
|
+
case "validate-publish":
|
|
69
|
+
await this.handleValidatePublish(restArgs);
|
|
70
|
+
return;
|
|
59
71
|
case "install":
|
|
60
72
|
await this.handleInstall(restArgs);
|
|
61
73
|
return;
|
|
@@ -93,6 +105,7 @@ var AppRuntimeCliService = class {
|
|
|
93
105
|
const options = this.optionsService.readCreateOptions(optionArgs);
|
|
94
106
|
await new CreateCommand().run({
|
|
95
107
|
appDirectory: target,
|
|
108
|
+
template: options.template,
|
|
96
109
|
json: options.json,
|
|
97
110
|
write: this.write
|
|
98
111
|
});
|
|
@@ -106,6 +119,46 @@ var AppRuntimeCliService = class {
|
|
|
106
119
|
write: this.write
|
|
107
120
|
});
|
|
108
121
|
};
|
|
122
|
+
handleBuild = async (restArgs) => {
|
|
123
|
+
const { target, optionArgs } = this.optionsService.readTarget("build", restArgs);
|
|
124
|
+
const options = this.optionsService.readBuildOptions(optionArgs);
|
|
125
|
+
const result = await new AppBuildService().build({
|
|
126
|
+
appDirectory: target,
|
|
127
|
+
install: options.install
|
|
128
|
+
});
|
|
129
|
+
if (options.json) {
|
|
130
|
+
this.write(`${JSON.stringify({
|
|
131
|
+
ok: true,
|
|
132
|
+
build: result
|
|
133
|
+
}, null, 2)}\n`);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (!result.built) {
|
|
137
|
+
this.write(`Build skipped: ${result.skippedReason ?? result.mainKind}\n`);
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
this.write(`Built ${result.mainKind} app\n`);
|
|
141
|
+
this.write(`Main: ${result.mainEntryPath}\n`);
|
|
142
|
+
if (result.installedDependencies) this.write("Dependencies: installed\n");
|
|
143
|
+
};
|
|
144
|
+
handleDoctor = async (restArgs) => {
|
|
145
|
+
const options = this.optionsService.readJsonOnlyOptions(restArgs);
|
|
146
|
+
const result = await new AppRuntimeToolchainService().doctor();
|
|
147
|
+
if (options.json) {
|
|
148
|
+
this.write(`${JSON.stringify({
|
|
149
|
+
ok: result.ok,
|
|
150
|
+
doctor: result
|
|
151
|
+
}, null, 2)}\n`);
|
|
152
|
+
if (!result.ok) process.exitCode = 1;
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
this.write(`NApp runtime doctor: ${result.ok ? "ok" : "not ready"}\n`);
|
|
156
|
+
for (const tool of result.tools) {
|
|
157
|
+
this.write(`${tool.ok ? "ok" : "missing"} ${tool.name}${tool.version ? ` ${tool.version}` : ""}\n`);
|
|
158
|
+
if (!tool.ok) this.write(` ${tool.installHint}\n`);
|
|
159
|
+
}
|
|
160
|
+
if (!result.ok) process.exitCode = 1;
|
|
161
|
+
};
|
|
109
162
|
handleRun = async (restArgs) => {
|
|
110
163
|
const { target, optionArgs } = this.optionsService.readTarget("run", restArgs);
|
|
111
164
|
const options = this.optionsService.readRuntimeOptions(optionArgs);
|
|
@@ -113,6 +166,7 @@ var AppRuntimeCliService = class {
|
|
|
113
166
|
appReference: target,
|
|
114
167
|
host: options.host,
|
|
115
168
|
port: options.port,
|
|
169
|
+
dataDirectory: options.dataDirectory,
|
|
116
170
|
json: options.json,
|
|
117
171
|
documentGrantMap: options.documentGrantMap,
|
|
118
172
|
write: this.write
|
|
@@ -125,6 +179,7 @@ var AppRuntimeCliService = class {
|
|
|
125
179
|
appReference: target,
|
|
126
180
|
host: options.host,
|
|
127
181
|
port: options.port,
|
|
182
|
+
dataDirectory: options.dataDirectory,
|
|
128
183
|
json: options.json,
|
|
129
184
|
documentGrantMap: options.documentGrantMap,
|
|
130
185
|
write: this.write
|
|
@@ -152,6 +207,16 @@ var AppRuntimeCliService = class {
|
|
|
152
207
|
write: this.write
|
|
153
208
|
});
|
|
154
209
|
};
|
|
210
|
+
handleValidatePublish = async (restArgs) => {
|
|
211
|
+
const { target, optionArgs } = this.optionsService.readTarget("validate-publish", restArgs);
|
|
212
|
+
const options = this.optionsService.readPublishOptions(optionArgs);
|
|
213
|
+
await new ValidatePublishCommand().run({
|
|
214
|
+
appDirectory: target,
|
|
215
|
+
metadataPath: options.metadataPath,
|
|
216
|
+
json: options.json,
|
|
217
|
+
write: this.write
|
|
218
|
+
});
|
|
219
|
+
};
|
|
155
220
|
handleInstall = async (restArgs) => {
|
|
156
221
|
const { target, optionArgs } = this.optionsService.readTarget("install", restArgs);
|
|
157
222
|
const options = this.optionsService.readInstallOptions(optionArgs);
|
|
@@ -271,11 +336,14 @@ var AppRuntimeCliService = class {
|
|
|
271
336
|
});
|
|
272
337
|
};
|
|
273
338
|
writeUsage = () => {
|
|
274
|
-
this.write("Usage: napp create <app-dir> [--json]\n");
|
|
339
|
+
this.write("Usage: napp create <app-dir> [--template starter|ts-http|ts-http-lite] [--json]\n");
|
|
275
340
|
this.write(" napp inspect <app-dir> [--json]\n");
|
|
276
|
-
this.write(" napp
|
|
341
|
+
this.write(" napp build <app-dir> [--install] [--json]\n");
|
|
342
|
+
this.write(" napp doctor [--json]\n");
|
|
343
|
+
this.write(" napp <run|dev> <app-dir|app-id> [--host 127.0.0.1] [--port 3100] [--data /path] [--json] [--document scope=/path]\n");
|
|
277
344
|
this.write(" napp pack <app-dir> [--out bundle.napp] [--json]\n");
|
|
278
345
|
this.write(" napp publish <app-dir> [--meta marketplace.json] [--api-base <url>] [--token <token>] [--json]\n");
|
|
346
|
+
this.write(" napp validate-publish <app-dir> [--meta marketplace.json] [--json]\n");
|
|
279
347
|
this.write(" napp install <app-dir|bundle.napp|app-id[@version]> [--registry <url>] [--json]\n");
|
|
280
348
|
this.write(" napp update <app-id> [--version <version>] [--registry <url>] [--json]\n");
|
|
281
349
|
this.write(" napp uninstall <app-id> [--purge-data] [--json]\n");
|
|
@@ -1,19 +1,26 @@
|
|
|
1
1
|
import { AppDocumentGrantMap } from "../permissions/app-permissions.types.js";
|
|
2
|
+
import { AppScaffoldTemplate } from "../scaffold/app-scaffold.service.js";
|
|
2
3
|
|
|
3
4
|
//#region src/cli/app-runtime-options.service.d.ts
|
|
4
5
|
type RuntimeCliOptions = {
|
|
5
6
|
host: string;
|
|
6
7
|
port: number;
|
|
8
|
+
dataDirectory?: string;
|
|
7
9
|
json: boolean;
|
|
8
10
|
documentGrantMap: AppDocumentGrantMap;
|
|
9
11
|
};
|
|
10
12
|
type CreateCliOptions = {
|
|
11
13
|
json: boolean;
|
|
14
|
+
template: AppScaffoldTemplate;
|
|
12
15
|
};
|
|
13
16
|
type PackCliOptions = {
|
|
14
17
|
json: boolean;
|
|
15
18
|
outputPath?: string;
|
|
16
19
|
};
|
|
20
|
+
type BuildCliOptions = {
|
|
21
|
+
json: boolean;
|
|
22
|
+
install: boolean;
|
|
23
|
+
};
|
|
17
24
|
type JsonOnlyCliOptions = {
|
|
18
25
|
json: boolean;
|
|
19
26
|
};
|
|
@@ -50,7 +57,9 @@ declare class AppRuntimeOptionsService {
|
|
|
50
57
|
optionArgs: string[];
|
|
51
58
|
};
|
|
52
59
|
readCreateOptions: (rawArgs: string[]) => CreateCliOptions;
|
|
60
|
+
private readCreateTemplate;
|
|
53
61
|
readPackOptions: (rawArgs: string[]) => PackCliOptions;
|
|
62
|
+
readBuildOptions: (rawArgs: string[]) => BuildCliOptions;
|
|
54
63
|
readJsonOnlyOptions: (rawArgs: string[]) => JsonOnlyCliOptions;
|
|
55
64
|
readInstallOptions: (rawArgs: string[]) => InstallCliOptions;
|
|
56
65
|
readUpdateOptions: (rawArgs: string[]) => UpdateCliOptions;
|
|
@@ -64,4 +73,4 @@ declare class AppRuntimeOptionsService {
|
|
|
64
73
|
private requireOptionValue;
|
|
65
74
|
}
|
|
66
75
|
//#endregion
|
|
67
|
-
export { AppRuntimeOptionsService, CreateCliOptions, GrantCliOptions, InstallCliOptions, JsonOnlyCliOptions, PackCliOptions, PublishCliOptions, RevokeCliOptions, RuntimeCliOptions, UninstallCliOptions, UpdateCliOptions };
|
|
76
|
+
export { AppRuntimeOptionsService, BuildCliOptions, CreateCliOptions, GrantCliOptions, InstallCliOptions, JsonOnlyCliOptions, PackCliOptions, PublishCliOptions, RevokeCliOptions, RuntimeCliOptions, UninstallCliOptions, UpdateCliOptions };
|
|
@@ -9,18 +9,31 @@ var AppRuntimeOptionsService = class {
|
|
|
9
9
|
};
|
|
10
10
|
};
|
|
11
11
|
readCreateOptions = (rawArgs) => {
|
|
12
|
-
const options = {
|
|
13
|
-
|
|
12
|
+
const options = {
|
|
13
|
+
json: false,
|
|
14
|
+
template: "starter"
|
|
15
|
+
};
|
|
16
|
+
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
17
|
+
const current = rawArgs[index];
|
|
14
18
|
if (!current?.startsWith("--")) throw new Error(`未知参数:${current}`);
|
|
19
|
+
const nextValue = rawArgs[index + 1];
|
|
15
20
|
switch (current) {
|
|
16
21
|
case "--json":
|
|
17
22
|
options.json = true;
|
|
18
23
|
break;
|
|
24
|
+
case "--template":
|
|
25
|
+
options.template = this.readCreateTemplate(this.requireOptionValue(current, nextValue));
|
|
26
|
+
index += 1;
|
|
27
|
+
break;
|
|
19
28
|
default: throw new Error(`未知参数:${current}`);
|
|
20
29
|
}
|
|
21
30
|
}
|
|
22
31
|
return options;
|
|
23
32
|
};
|
|
33
|
+
readCreateTemplate = (rawTemplate) => {
|
|
34
|
+
if (rawTemplate === "starter" || rawTemplate === "ts-http" || rawTemplate === "ts-http-lite") return rawTemplate;
|
|
35
|
+
throw new Error("--template 只支持 starter、ts-http 或 ts-http-lite。");
|
|
36
|
+
};
|
|
24
37
|
readPackOptions = (rawArgs) => {
|
|
25
38
|
const options = { json: false };
|
|
26
39
|
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
@@ -40,6 +53,25 @@ var AppRuntimeOptionsService = class {
|
|
|
40
53
|
}
|
|
41
54
|
return options;
|
|
42
55
|
};
|
|
56
|
+
readBuildOptions = (rawArgs) => {
|
|
57
|
+
const options = {
|
|
58
|
+
json: false,
|
|
59
|
+
install: false
|
|
60
|
+
};
|
|
61
|
+
for (const current of rawArgs) {
|
|
62
|
+
if (!current?.startsWith("--")) throw new Error(`未知参数:${current}`);
|
|
63
|
+
switch (current) {
|
|
64
|
+
case "--json":
|
|
65
|
+
options.json = true;
|
|
66
|
+
break;
|
|
67
|
+
case "--install":
|
|
68
|
+
options.install = true;
|
|
69
|
+
break;
|
|
70
|
+
default: throw new Error(`未知参数:${current}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return options;
|
|
74
|
+
};
|
|
43
75
|
readJsonOnlyOptions = (rawArgs) => {
|
|
44
76
|
const options = { json: false };
|
|
45
77
|
for (const current of rawArgs) {
|
|
@@ -118,6 +150,7 @@ var AppRuntimeOptionsService = class {
|
|
|
118
150
|
const options = {
|
|
119
151
|
host: "127.0.0.1",
|
|
120
152
|
port: 3100,
|
|
153
|
+
dataDirectory: void 0,
|
|
121
154
|
json: false,
|
|
122
155
|
documentGrantMap: {}
|
|
123
156
|
};
|
|
@@ -138,6 +171,10 @@ var AppRuntimeOptionsService = class {
|
|
|
138
171
|
case "--json":
|
|
139
172
|
options.json = true;
|
|
140
173
|
break;
|
|
174
|
+
case "--data":
|
|
175
|
+
options.dataDirectory = this.requireOptionValue(current, nextValue);
|
|
176
|
+
index += 1;
|
|
177
|
+
break;
|
|
141
178
|
case "--document":
|
|
142
179
|
this.assignDocumentGrant(options.documentGrantMap, this.requireOptionValue(current, nextValue));
|
|
143
180
|
index += 1;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppScaffoldService } from "../scaffold/app-scaffold.service.js";
|
|
1
|
+
import { AppScaffoldService, AppScaffoldTemplate } from "../scaffold/app-scaffold.service.js";
|
|
2
2
|
|
|
3
3
|
//#region src/commands/create.controller.d.ts
|
|
4
4
|
declare class CreateCommand {
|
|
@@ -6,6 +6,7 @@ declare class CreateCommand {
|
|
|
6
6
|
constructor(scaffoldService?: AppScaffoldService);
|
|
7
7
|
run: (params: {
|
|
8
8
|
appDirectory: string;
|
|
9
|
+
template: AppScaffoldTemplate;
|
|
9
10
|
json: boolean;
|
|
10
11
|
write: (text: string) => void;
|
|
11
12
|
}) => Promise<void>;
|
|
@@ -5,8 +5,8 @@ var CreateCommand = class {
|
|
|
5
5
|
this.scaffoldService = scaffoldService;
|
|
6
6
|
}
|
|
7
7
|
run = async (params) => {
|
|
8
|
-
const { appDirectory, json, write } = params;
|
|
9
|
-
const result = await this.scaffoldService.scaffold(appDirectory);
|
|
8
|
+
const { appDirectory, template, json, write } = params;
|
|
9
|
+
const result = await this.scaffoldService.scaffold(appDirectory, { template });
|
|
10
10
|
if (json) {
|
|
11
11
|
write(`${JSON.stringify({
|
|
12
12
|
ok: true,
|
|
@@ -15,6 +15,7 @@ var CreateCommand = class {
|
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
17
|
write(`Created app scaffold at ${result.appDirectory}\n`);
|
|
18
|
+
write(`Template: ${result.template}\n`);
|
|
18
19
|
write(`Manifest: ${result.manifestPath}\n`);
|
|
19
20
|
write("Next: napp inspect <app-dir> && napp run <app-dir>\n");
|
|
20
21
|
};
|
|
@@ -17,7 +17,8 @@ var InspectCommand = class {
|
|
|
17
17
|
}
|
|
18
18
|
write(`App: ${summary.name} (${summary.id})\n`);
|
|
19
19
|
write(`Version: ${summary.version}\n`);
|
|
20
|
-
write(`
|
|
20
|
+
write(`Main Kind: ${summary.mainKind}\n`);
|
|
21
|
+
if (summary.action) write(`Action: ${summary.action}\n`);
|
|
21
22
|
write(`Main: ${summary.mainEntryPath}\n`);
|
|
22
23
|
write(`UI: ${summary.uiEntryPath}\n`);
|
|
23
24
|
};
|
|
@@ -2,6 +2,7 @@ import { AppManifestService } from "../manifest/app-manifest.service.js";
|
|
|
2
2
|
import { AppHostService } from "../host/app-host.service.js";
|
|
3
3
|
import { AppInstanceService } from "../host/app-instance.service.js";
|
|
4
4
|
import { AppInstallationService } from "../install/app-installation.service.js";
|
|
5
|
+
import { WasmtimeWasiHttpComponentService } from "../runtime/wasmtime-wasi-http-component.service.js";
|
|
5
6
|
//#region src/commands/run.controller.ts
|
|
6
7
|
var RunCommand = class {
|
|
7
8
|
constructor(manifestService = new AppManifestService(), installationService = new AppInstallationService()) {
|
|
@@ -9,19 +10,35 @@ var RunCommand = class {
|
|
|
9
10
|
this.installationService = installationService;
|
|
10
11
|
}
|
|
11
12
|
run = async (params) => {
|
|
12
|
-
const { appReference, host, port, json, documentGrantMap, write } = params;
|
|
13
|
+
const { appReference, host, port, dataDirectory, json, documentGrantMap, write } = params;
|
|
13
14
|
const launch = await this.installationService.resolveLaunch(appReference, documentGrantMap);
|
|
14
15
|
const bundle = await this.manifestService.load(launch.appDirectory);
|
|
15
16
|
const appInstance = new AppInstanceService(bundle);
|
|
16
17
|
await appInstance.initialize(launch.documentGrantMap, { appId: launch.appId });
|
|
17
18
|
await this.installationService.persistGrants(launch.appId, launch.documentGrantMap);
|
|
18
|
-
const
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const wasiHttpComponentService = bundle.manifest.main.kind === "wasi-http-component" ? new WasmtimeWasiHttpComponentService() : void 0;
|
|
20
|
+
const effectiveDataDirectory = dataDirectory ?? launch.dataDirectory;
|
|
21
|
+
if (wasiHttpComponentService) {
|
|
22
|
+
if (!effectiveDataDirectory) throw new Error("wasi-http-component 应用需要通过 --data /path 指定后端数据目录。");
|
|
23
|
+
await wasiHttpComponentService.start({
|
|
24
|
+
wasmPath: bundle.mainEntryPath,
|
|
25
|
+
dataDirectory: effectiveDataDirectory
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
const appHost = new AppHostService(appInstance, wasiHttpComponentService);
|
|
29
|
+
let hostHandle;
|
|
30
|
+
try {
|
|
31
|
+
hostHandle = await appHost.start({
|
|
32
|
+
host,
|
|
33
|
+
port
|
|
34
|
+
});
|
|
35
|
+
} catch (error) {
|
|
36
|
+
await wasiHttpComponentService?.stop();
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
23
39
|
const shutdown = async () => {
|
|
24
40
|
await appHost.stop();
|
|
41
|
+
await wasiHttpComponentService?.stop();
|
|
25
42
|
process.exit(0);
|
|
26
43
|
};
|
|
27
44
|
process.once("SIGINT", () => {
|
|
@@ -36,7 +53,8 @@ var RunCommand = class {
|
|
|
36
53
|
host: hostHandle,
|
|
37
54
|
app: {
|
|
38
55
|
appId: launch.appId ?? bundle.manifest.id,
|
|
39
|
-
appDirectory: launch.appDirectory
|
|
56
|
+
appDirectory: launch.appDirectory,
|
|
57
|
+
dataDirectory: effectiveDataDirectory
|
|
40
58
|
}
|
|
41
59
|
}, null, 2)}\n`);
|
|
42
60
|
return;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { AppPublishValidationService } from "../publish/app-publish-validation.service.js";
|
|
2
|
+
|
|
3
|
+
//#region src/commands/validate-publish.controller.d.ts
|
|
4
|
+
declare class ValidatePublishCommand {
|
|
5
|
+
private readonly validationService;
|
|
6
|
+
constructor(validationService?: AppPublishValidationService);
|
|
7
|
+
run: (params: {
|
|
8
|
+
appDirectory: string;
|
|
9
|
+
metadataPath?: string;
|
|
10
|
+
json: boolean;
|
|
11
|
+
write: (text: string) => void;
|
|
12
|
+
}) => Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
//#endregion
|
|
15
|
+
export { ValidatePublishCommand };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AppPublishValidationService } from "../publish/app-publish-validation.service.js";
|
|
2
|
+
//#region src/commands/validate-publish.controller.ts
|
|
3
|
+
var ValidatePublishCommand = class {
|
|
4
|
+
constructor(validationService = new AppPublishValidationService()) {
|
|
5
|
+
this.validationService = validationService;
|
|
6
|
+
}
|
|
7
|
+
run = async (params) => {
|
|
8
|
+
const { appDirectory, metadataPath, json, write } = params;
|
|
9
|
+
const result = await this.validationService.validate({
|
|
10
|
+
appDirectory,
|
|
11
|
+
metadataPath
|
|
12
|
+
});
|
|
13
|
+
if (json) {
|
|
14
|
+
write(`${JSON.stringify({
|
|
15
|
+
ok: true,
|
|
16
|
+
validation: result
|
|
17
|
+
}, null, 2)}\n`);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
write(`Publish validation ok for ${result.appId}@${result.version}\n`);
|
|
21
|
+
write(`Main kind: ${result.mainKind}\n`);
|
|
22
|
+
write(`Main: ${result.mainEntryPath}\n`);
|
|
23
|
+
write(`Metadata: ${result.metadataPath}\n`);
|
|
24
|
+
write(`Bundle size: ${result.bundleSizeBytes} bytes\n`);
|
|
25
|
+
write(`Main entry size: ${result.mainEntrySizeBytes} bytes\n`);
|
|
26
|
+
write(`Bundle files (${result.bundleFilePaths.length}): ${result.bundleFilePaths.join(", ")}\n`);
|
|
27
|
+
if (result.warnings.length > 0) for (const warning of result.warnings) write(`Warning [${warning.code}]: ${warning.message}\n`);
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
//#endregion
|
|
31
|
+
export { ValidatePublishCommand };
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AppInstanceService } from "./app-instance.service.js";
|
|
2
|
+
import { WasmtimeWasiHttpComponentService } from "../runtime/wasmtime-wasi-http-component.service.js";
|
|
2
3
|
|
|
3
4
|
//#region src/host/app-host.service.d.ts
|
|
4
5
|
type AppHostStartOptions = {
|
|
@@ -13,10 +14,11 @@ type AppHostHandle = {
|
|
|
13
14
|
};
|
|
14
15
|
declare class AppHostService {
|
|
15
16
|
private readonly appInstance;
|
|
17
|
+
private readonly wasiHttpComponentService?;
|
|
16
18
|
private server?;
|
|
17
19
|
private readonly bridgeServer;
|
|
18
20
|
private readonly uiServer;
|
|
19
|
-
constructor(appInstance: AppInstanceService);
|
|
21
|
+
constructor(appInstance: AppInstanceService, wasiHttpComponentService?: WasmtimeWasiHttpComponentService | undefined);
|
|
20
22
|
start: (options: AppHostStartOptions) => Promise<AppHostHandle>;
|
|
21
23
|
stop: () => Promise<void>;
|
|
22
24
|
private handleRequest;
|
|
@@ -6,8 +6,9 @@ var AppHostService = class {
|
|
|
6
6
|
server;
|
|
7
7
|
bridgeServer;
|
|
8
8
|
uiServer;
|
|
9
|
-
constructor(appInstance) {
|
|
9
|
+
constructor(appInstance, wasiHttpComponentService) {
|
|
10
10
|
this.appInstance = appInstance;
|
|
11
|
+
this.wasiHttpComponentService = wasiHttpComponentService;
|
|
11
12
|
this.bridgeServer = new HostBridgeServer(appInstance);
|
|
12
13
|
this.uiServer = new UiServerService(appInstance.bundle);
|
|
13
14
|
}
|
|
@@ -48,6 +49,9 @@ var AppHostService = class {
|
|
|
48
49
|
};
|
|
49
50
|
handleRequest = async (request, response) => {
|
|
50
51
|
try {
|
|
52
|
+
if (this.wasiHttpComponentService) {
|
|
53
|
+
if (await this.wasiHttpComponentService.handleRequest(request, response)) return;
|
|
54
|
+
}
|
|
51
55
|
if (await this.bridgeServer.handle(request, response)) return;
|
|
52
56
|
await this.uiServer.handle(request, response);
|
|
53
57
|
} catch (error) {
|
|
@@ -22,6 +22,7 @@ var AppInstanceService = class {
|
|
|
22
22
|
return this.permissionsService.summarize(this.bundle, this.getPermissions());
|
|
23
23
|
};
|
|
24
24
|
runAction = async (action) => {
|
|
25
|
+
if (this.bundle.manifest.main.kind !== "wasm") throw new Error("当前应用不支持 __napp/run action,请通过 /api/* 调用 WASI HTTP 后端。");
|
|
25
26
|
const expectedAction = this.bundle.manifest.main.action;
|
|
26
27
|
if (action && action !== expectedAction) throw new Error(`当前应用只支持动作 ${expectedAction}。`);
|
|
27
28
|
const input = await this.collectDocumentSummaryInput();
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AppDocumentAccessMode, AppDocumentAccessScope, AppMainManifest, AppManifest, AppManifestBundle, AppManifestSummary, AppPermissions, AppUiManifest } from "./manifest/app-manifest.types.js";
|
|
1
|
+
import { AppCoreWasmMainManifest, AppDocumentAccessMode, AppDocumentAccessScope, AppMainManifest, AppManifest, AppManifestBundle, AppManifestSummary, AppPermissions, AppUiManifest, AppWasiHttpComponentMainManifest } from "./manifest/app-manifest.types.js";
|
|
2
2
|
import { AppManifestService } from "./manifest/app-manifest.service.js";
|
|
3
3
|
import { AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult } from "./bundle/app-bundle.types.js";
|
|
4
4
|
import { AppBundleService } from "./bundle/app-bundle.service.js";
|
|
@@ -10,7 +10,10 @@ import { WasmSidecarClientService } from "./sidecar/wasm-sidecar-client.service.
|
|
|
10
10
|
import { WasmMainRunnerService } from "./runtime/wasm-main-runner.service.js";
|
|
11
11
|
import { AppInstanceService, AppRunResult } from "./host/app-instance.service.js";
|
|
12
12
|
import { HostBridgeServer } from "./bridge/host-bridge.service.js";
|
|
13
|
-
import {
|
|
13
|
+
import { AppScaffoldFile, AppTsHttpScaffoldTemplateService } from "./scaffold/app-ts-http-scaffold-template.service.js";
|
|
14
|
+
import { AppTsHttpLiteScaffoldTemplateService } from "./scaffold/app-ts-http-lite-scaffold-template.service.js";
|
|
15
|
+
import { AppScaffoldResult, AppScaffoldService, AppScaffoldTemplate } from "./scaffold/app-scaffold.service.js";
|
|
16
|
+
import { AppRuntimeOptionsService, BuildCliOptions, CreateCliOptions, GrantCliOptions, InstallCliOptions, JsonOnlyCliOptions, PackCliOptions, PublishCliOptions, RevokeCliOptions, RuntimeCliOptions, UninstallCliOptions, UpdateCliOptions } from "./cli/app-runtime-options.service.js";
|
|
14
17
|
import { AppRuntimeCliService } from "./cli/app-runtime-cli.service.js";
|
|
15
18
|
import { CreateCommand } from "./commands/create.controller.js";
|
|
16
19
|
import { AppHomeService } from "./paths/app-home.service.js";
|
|
@@ -38,6 +41,11 @@ import { RegistryCommand } from "./commands/registry.controller.js";
|
|
|
38
41
|
import { RevokeCommand } from "./commands/revoke.controller.js";
|
|
39
42
|
import { UpdateCommand } from "./commands/update.controller.js";
|
|
40
43
|
import { UninstallCommand } from "./commands/uninstall.controller.js";
|
|
44
|
+
import { AppPublishValidationResult, AppPublishValidationService, AppPublishValidationWarning, AppPublishValidationWarningCode } from "./publish/app-publish-validation.service.js";
|
|
45
|
+
import { ValidatePublishCommand } from "./commands/validate-publish.controller.js";
|
|
46
|
+
import { WasmtimeWasiHttpComponentHandle, WasmtimeWasiHttpComponentService, WasmtimeWasiHttpComponentStartOptions } from "./runtime/wasmtime-wasi-http-component.service.js";
|
|
41
47
|
import { AppHostHandle, AppHostService, AppHostStartOptions } from "./host/app-host.service.js";
|
|
48
|
+
import { AppRuntimeCommandResult, AppRuntimeDoctorResult, AppRuntimeToolStatus, AppRuntimeToolchainService } from "./runtime/app-runtime-toolchain.service.js";
|
|
49
|
+
import { AppBuildResult, AppBuildService } from "./runtime/app-build.service.js";
|
|
42
50
|
import { UiServerService } from "./ui/ui-server.service.js";
|
|
43
|
-
export { AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult, AppBundleService, AppDocumentAccessMode, AppDocumentAccessScope, AppDocumentGrantMap, AppDocumentGrantMutationResult, AppDocumentGrantState, AppGrantService, AppHomeService, AppHostHandle, AppHostService, AppHostStartOptions, AppInfoResult, AppInstallResult, AppInstallSourceKind, AppInstallationService, AppInstalledPermissionState, AppInstanceService, AppLaunchResolution, AppMainManifest, AppManifest, AppManifestBundle, AppManifestService, AppManifestSummary, AppMarketplaceClientService, AppMarketplaceMetadata, AppMarketplaceMetadataService, AppPermissionSummary, AppPermissions, AppPermissionsService, AppPublishFile, AppPublishPayload, AppPublishResult, AppPublishService, AppPublisher, AppRegistry, AppRegistryAppRecord, AppRegistryConfig, AppRegistryConfigService, AppRegistryConfigSnapshot, AppRegistryInstalledVersion, AppRegistryService, AppRemoteRegistryClientService, AppRemoteRegistryDocument, AppRemoteRegistryResolution, AppRemoteRegistryVersion, AppRunResult, AppRuntimeCliService, AppRuntimeOptionsService, AppUiManifest, AppUninstallResult, AppUpdateResult, CreateCliOptions, CreateCommand, DEFAULT_APP_MARKETPLACE_API_BASE, DEFAULT_APP_REGISTRY_URL, GrantCliOptions, GrantCommand, HostBridgeServer, InfoCommand, InstallCliOptions, InstallCommand, InstalledAppListItem, JsonOnlyCliOptions, ListCommand, MainRunRequest, MainRunResult, MainRunnerService, PackCliOptions, PackCommand, PermissionsCommand, PlatformAuthStateService, PlatformPublishAuthState, PublishCliOptions, PublishCommand, RegistryCommand, ResolvedDocumentGrant, ResolvedPermissions, RevokeCliOptions, RevokeCommand, RuntimeCliOptions, UiServerService, UninstallCliOptions, UninstallCommand, UpdateCliOptions, UpdateCommand, WasmDocumentSummaryInput, WasmMainRunnerService, WasmSidecarClientService };
|
|
51
|
+
export { AppBuildResult, AppBuildService, AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult, AppBundleService, AppCoreWasmMainManifest, AppDocumentAccessMode, AppDocumentAccessScope, AppDocumentGrantMap, AppDocumentGrantMutationResult, AppDocumentGrantState, AppGrantService, AppHomeService, AppHostHandle, AppHostService, AppHostStartOptions, AppInfoResult, AppInstallResult, AppInstallSourceKind, AppInstallationService, AppInstalledPermissionState, AppInstanceService, AppLaunchResolution, AppMainManifest, AppManifest, AppManifestBundle, AppManifestService, AppManifestSummary, AppMarketplaceClientService, AppMarketplaceMetadata, AppMarketplaceMetadataService, AppPermissionSummary, AppPermissions, AppPermissionsService, AppPublishFile, AppPublishPayload, AppPublishResult, AppPublishService, AppPublishValidationResult, AppPublishValidationService, AppPublishValidationWarning, AppPublishValidationWarningCode, AppPublisher, AppRegistry, AppRegistryAppRecord, AppRegistryConfig, AppRegistryConfigService, AppRegistryConfigSnapshot, AppRegistryInstalledVersion, AppRegistryService, AppRemoteRegistryClientService, AppRemoteRegistryDocument, AppRemoteRegistryResolution, AppRemoteRegistryVersion, AppRunResult, AppRuntimeCliService, AppRuntimeCommandResult, AppRuntimeDoctorResult, AppRuntimeOptionsService, AppRuntimeToolStatus, AppRuntimeToolchainService, AppScaffoldFile, AppScaffoldResult, AppScaffoldService, AppScaffoldTemplate, AppTsHttpLiteScaffoldTemplateService, AppTsHttpScaffoldTemplateService, AppUiManifest, AppUninstallResult, AppUpdateResult, AppWasiHttpComponentMainManifest, BuildCliOptions, CreateCliOptions, CreateCommand, DEFAULT_APP_MARKETPLACE_API_BASE, DEFAULT_APP_REGISTRY_URL, GrantCliOptions, GrantCommand, HostBridgeServer, InfoCommand, InstallCliOptions, InstallCommand, InstalledAppListItem, JsonOnlyCliOptions, ListCommand, MainRunRequest, MainRunResult, MainRunnerService, PackCliOptions, PackCommand, PermissionsCommand, PlatformAuthStateService, PlatformPublishAuthState, PublishCliOptions, PublishCommand, RegistryCommand, ResolvedDocumentGrant, ResolvedPermissions, RevokeCliOptions, RevokeCommand, RuntimeCliOptions, UiServerService, UninstallCliOptions, UninstallCommand, UpdateCliOptions, UpdateCommand, ValidatePublishCommand, WasmDocumentSummaryInput, WasmMainRunnerService, WasmSidecarClientService, WasmtimeWasiHttpComponentHandle, WasmtimeWasiHttpComponentService, WasmtimeWasiHttpComponentStartOptions };
|