@nextclaw/app-runtime 0.5.0 → 0.7.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 +39 -5
- package/dist/bundle/app-bundle.service.d.ts +7 -2
- package/dist/bundle/app-bundle.service.js +77 -16
- package/dist/bundle/app-bundle.types.d.ts +5 -1
- package/dist/cli/app-runtime-cli.service.d.ts +1 -0
- package/dist/cli/app-runtime-cli.service.js +23 -5
- package/dist/cli/app-runtime-options.service.d.ts +4 -0
- package/dist/cli/app-runtime-options.service.js +22 -4
- package/dist/commands/pack.controller.d.ts +1 -0
- package/dist/commands/pack.controller.js +4 -3
- package/dist/commands/publish.controller.d.ts +1 -0
- package/dist/commands/publish.controller.js +4 -3
- package/dist/commands/validate-publish.controller.d.ts +16 -0
- package/dist/commands/validate-publish.controller.js +33 -0
- package/dist/index.d.ts +7 -4
- package/dist/index.js +6 -3
- package/dist/install/app-installation.service.d.ts +4 -1
- package/dist/install/app-installation.service.js +21 -3
- package/dist/install/app-installation.types.d.ts +4 -0
- package/dist/package.js +1 -1
- package/dist/publish/app-publish-validation.service.d.ts +40 -0
- package/dist/publish/app-publish-validation.service.js +80 -0
- package/dist/publish/app-publish.service.d.ts +2 -0
- package/dist/publish/app-publish.service.js +9 -3
- package/dist/publish/app-publish.types.d.ts +4 -1
- package/dist/registry/app-registry.service.d.ts +1 -0
- package/dist/registry/app-registry.service.js +2 -1
- package/dist/registry/app-registry.types.d.ts +2 -0
- package/dist/registry/app-remote-registry-client.service.js +5 -1
- package/dist/registry/app-remote-registry.types.d.ts +5 -0
- package/dist/scaffold/app-scaffold.service.d.ts +4 -2
- package/dist/scaffold/app-scaffold.service.js +14 -1
- 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/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,8 +10,9 @@
|
|
|
10
10
|
- `napp build <app-dir> --install`:安装模板依赖并构建 TS/WASI HTTP 后端
|
|
11
11
|
- `napp run <app-dir|app-id>`:启动本地宿主,支持目录运行和已安装应用运行
|
|
12
12
|
- `napp dev <app-dir>`:当前等价于 `run`
|
|
13
|
-
- `napp pack <app-dir>`:把应用目录打成 `.napp`
|
|
14
|
-
- `napp publish <app-dir
|
|
13
|
+
- `napp pack <app-dir>`:把应用目录打成 `.napp` 分发包,默认使用轻量 `source` 模式
|
|
14
|
+
- `napp validate-publish <app-dir>`:本地做发布前校验并输出体积/包内容 warning
|
|
15
|
+
- `napp publish <app-dir>`:把应用目录发布到官方 apps registry,默认发布轻量 `source` 分发包
|
|
15
16
|
- `napp install <app-dir|bundle.napp|app-id[@version]>`:从本地或 registry 安装应用
|
|
16
17
|
- `napp update <app-id>`:更新已安装应用
|
|
17
18
|
- `napp uninstall <app-id>`:卸载已安装应用
|
|
@@ -43,8 +44,8 @@ napp --version
|
|
|
43
44
|
manifest.json
|
|
44
45
|
main/
|
|
45
46
|
app.wasm
|
|
46
|
-
package.json # ts-http 模板存在
|
|
47
|
-
src/ # ts-http 模板存在
|
|
47
|
+
package.json # ts-http / ts-http-lite 模板存在
|
|
48
|
+
src/ # ts-http / ts-http-lite 模板存在
|
|
48
49
|
ui/
|
|
49
50
|
index.html
|
|
50
51
|
assets/
|
|
@@ -58,7 +59,7 @@ assets/
|
|
|
58
59
|
- WASI HTTP 业务 API:`/api/*`
|
|
59
60
|
- 权限词汇:`documentAccess`、`allowedDomains`、`storage`、`capabilities`
|
|
60
61
|
- 当前 Wasm 执行底座:Node 原生 `WebAssembly` 与 Wasmtime `serve`
|
|
61
|
-
- 分发包形态:`.napp`(底层为 zip
|
|
62
|
+
- 分发包形态:`.napp`(底层为 zip,支持 `source` / `bundle` 双模式)
|
|
62
63
|
- 安装目录:`~/.nextclaw/apps/packages/<app-id>/<version>/`
|
|
63
64
|
- 用户数据目录:`~/.nextclaw/apps/data/<app-id>/`
|
|
64
65
|
- 本地 registry:`~/.nextclaw/apps/registry.json`
|
|
@@ -74,11 +75,22 @@ napp doctor
|
|
|
74
75
|
napp create ./my-first-napp --template ts-http
|
|
75
76
|
napp build ./my-first-napp --install
|
|
76
77
|
napp inspect ./my-first-napp
|
|
78
|
+
napp validate-publish ./my-first-napp
|
|
77
79
|
napp run ./my-first-napp --data ./my-first-napp/.napp/data
|
|
78
80
|
napp pack ./my-first-napp
|
|
79
81
|
napp publish ./my-first-napp
|
|
80
82
|
```
|
|
81
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
|
+
|
|
82
94
|
本地安装工作流:
|
|
83
95
|
|
|
84
96
|
```bash
|
|
@@ -120,6 +132,11 @@ napp permissions nextclaw.my-first-napp
|
|
|
120
132
|
napp run nextclaw.my-first-napp
|
|
121
133
|
```
|
|
122
134
|
|
|
135
|
+
模板选择建议:
|
|
136
|
+
|
|
137
|
+
- `ts-http`:默认推荐,开发体验优先,适合大多数普通前后端小应用
|
|
138
|
+
- `ts-http-lite`:体积优先,继续走官方 WASI HTTP 路线,但不使用默认 Hono 路由层
|
|
139
|
+
|
|
123
140
|
已有示例应用:
|
|
124
141
|
|
|
125
142
|
```bash
|
|
@@ -159,6 +176,22 @@ assets/
|
|
|
159
176
|
checksums.json
|
|
160
177
|
```
|
|
161
178
|
|
|
179
|
+
## 分发模式
|
|
180
|
+
|
|
181
|
+
`.napp` 仍然是统一容器,但现在支持两种分发模式:
|
|
182
|
+
|
|
183
|
+
- `source`:默认模式。包里主要是用户源码、UI、资源和 manifest;安装时本地物化成运行态,适合轻量分发。
|
|
184
|
+
- `bundle`:显式模式。包里直接带运行态 `main/app.wasm`,适合高级用户、确定性发布或离线场景。
|
|
185
|
+
|
|
186
|
+
命令示例:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
napp validate-publish ./my-first-napp --mode source
|
|
190
|
+
napp pack ./my-first-napp --mode source
|
|
191
|
+
napp publish ./my-first-napp --mode source
|
|
192
|
+
napp pack ./my-first-napp --mode bundle
|
|
193
|
+
```
|
|
194
|
+
|
|
162
195
|
## Registry Metadata 结构
|
|
163
196
|
|
|
164
197
|
registry 按 npm 风格使用一个 base URL,再按 app id 拉取 metadata 文档。metadata 的最小结构如下:
|
|
@@ -179,6 +212,7 @@ registry 按 npm 风格使用一个 base URL,再按 app id 拉取 metadata 文
|
|
|
179
212
|
"name": "NextClaw Official"
|
|
180
213
|
},
|
|
181
214
|
"dist": {
|
|
215
|
+
"kind": "source",
|
|
182
216
|
"bundle": "./-/hello-notes-0.2.0.napp",
|
|
183
217
|
"sha256": "<sha256>"
|
|
184
218
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AppManifestService } from "../manifest/app-manifest.service.js";
|
|
2
|
-
import { AppBundleExtractResult, AppBundlePackResult } from "./app-bundle.types.js";
|
|
2
|
+
import { AppBundleExtractResult, AppBundlePackResult, AppDistributionMode } from "./app-bundle.types.js";
|
|
3
3
|
|
|
4
4
|
//#region src/bundle/app-bundle.service.d.ts
|
|
5
5
|
declare class AppBundleService {
|
|
@@ -8,14 +8,19 @@ declare class AppBundleService {
|
|
|
8
8
|
packAppDirectory: (params: {
|
|
9
9
|
appDirectory: string;
|
|
10
10
|
outputPath?: string;
|
|
11
|
+
mode?: AppDistributionMode;
|
|
11
12
|
}) => Promise<AppBundlePackResult>;
|
|
12
13
|
extractBundle: (params: {
|
|
13
14
|
bundlePath: string;
|
|
14
15
|
targetDirectory: string;
|
|
15
16
|
}) => Promise<AppBundleExtractResult>;
|
|
16
|
-
private
|
|
17
|
+
private collectRuntimeFiles;
|
|
18
|
+
private collectSourceFiles;
|
|
17
19
|
private collectDirectoryPaths;
|
|
20
|
+
private collectSourceDirectoryPaths;
|
|
21
|
+
private shouldExcludeSourcePath;
|
|
18
22
|
private buildMetadata;
|
|
23
|
+
private normalizeMetadata;
|
|
19
24
|
private buildChecksums;
|
|
20
25
|
private computeSha256;
|
|
21
26
|
private normalizeBundleFileName;
|
|
@@ -9,9 +9,11 @@ var AppBundleService = class {
|
|
|
9
9
|
this.manifestService = manifestService;
|
|
10
10
|
}
|
|
11
11
|
packAppDirectory = async (params) => {
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
const
|
|
12
|
+
const { appDirectory, outputPath, mode: requestedMode } = params;
|
|
13
|
+
const bundle = await this.manifestService.load(appDirectory);
|
|
14
|
+
const mode = requestedMode ?? "bundle";
|
|
15
|
+
const { appFiles, filePaths } = mode === "source" ? await this.collectSourceFiles(bundle) : await this.collectRuntimeFiles(bundle);
|
|
16
|
+
const metadata = this.buildMetadata(bundle.manifest.id, bundle.manifest.name, bundle.manifest.version, mode);
|
|
15
17
|
const bundleJsonPath = ".napp/bundle.json";
|
|
16
18
|
const checksumsJsonPath = ".napp/checksums.json";
|
|
17
19
|
const bundleJsonBytes = strToU8(`${JSON.stringify(metadata, null, 2)}\n`);
|
|
@@ -25,12 +27,14 @@ var AppBundleService = class {
|
|
|
25
27
|
[bundleJsonPath]: bundleJsonBytes,
|
|
26
28
|
[checksumsJsonPath]: checksumsJsonBytes
|
|
27
29
|
}, { level: 9 });
|
|
28
|
-
const
|
|
29
|
-
await mkdir(path.dirname(
|
|
30
|
-
await writeFile(
|
|
30
|
+
const resolvedOutputPath = outputPath ? path.resolve(outputPath) : path.join(path.dirname(bundle.appDirectory), `${this.normalizeBundleFileName(bundle.manifest.id)}-${bundle.manifest.version}.napp`);
|
|
31
|
+
await mkdir(path.dirname(resolvedOutputPath), { recursive: true });
|
|
32
|
+
await writeFile(resolvedOutputPath, Buffer.from(archiveBytes));
|
|
31
33
|
return {
|
|
32
|
-
bundlePath:
|
|
33
|
-
metadata
|
|
34
|
+
bundlePath: resolvedOutputPath,
|
|
35
|
+
metadata,
|
|
36
|
+
sizeBytes: archiveBytes.byteLength,
|
|
37
|
+
filePaths
|
|
34
38
|
};
|
|
35
39
|
};
|
|
36
40
|
extractBundle = async (params) => {
|
|
@@ -49,7 +53,8 @@ var AppBundleService = class {
|
|
|
49
53
|
await mkdir(path.dirname(targetPath), { recursive: true });
|
|
50
54
|
await writeFile(targetPath, Buffer.from(archive[entryName]));
|
|
51
55
|
}
|
|
52
|
-
const
|
|
56
|
+
const rawMetadata = await this.readJsonFile(path.join(targetDirectory, ".napp", "bundle.json"), "bundle metadata");
|
|
57
|
+
const metadata = this.normalizeMetadata(rawMetadata);
|
|
53
58
|
const checksums = await this.readJsonFile(path.join(targetDirectory, ".napp", "checksums.json"), "bundle checksums");
|
|
54
59
|
await this.verifyChecksums(targetDirectory, checksums);
|
|
55
60
|
await this.manifestService.load(targetDirectory);
|
|
@@ -59,15 +64,36 @@ var AppBundleService = class {
|
|
|
59
64
|
checksums
|
|
60
65
|
};
|
|
61
66
|
};
|
|
62
|
-
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
await this.collectDirectoryPaths(
|
|
66
|
-
await this.collectDirectoryPaths(
|
|
67
|
+
collectRuntimeFiles = async (bundle) => {
|
|
68
|
+
const appDirectory = bundle.appDirectory;
|
|
69
|
+
const filePaths = new Set([path.relative(appDirectory, bundle.manifestPath), path.relative(appDirectory, bundle.mainEntryPath)]);
|
|
70
|
+
await this.collectDirectoryPaths(bundle.uiDirectoryPath, appDirectory, filePaths);
|
|
71
|
+
await this.collectDirectoryPaths(bundle.assetsDirectoryPath, appDirectory, filePaths);
|
|
72
|
+
if (bundle.iconPath) filePaths.add(path.relative(appDirectory, bundle.iconPath));
|
|
67
73
|
const sortedPaths = Array.from(filePaths).sort((left, right) => left.localeCompare(right));
|
|
68
74
|
const appFiles = {};
|
|
69
75
|
for (const relativePath of sortedPaths) appFiles[relativePath] = new Uint8Array(await readFile(path.join(appDirectory, relativePath)));
|
|
70
|
-
return
|
|
76
|
+
return {
|
|
77
|
+
appFiles,
|
|
78
|
+
filePaths: sortedPaths
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
collectSourceFiles = async (bundle) => {
|
|
82
|
+
const filePaths = /* @__PURE__ */ new Set();
|
|
83
|
+
await this.collectSourceDirectoryPaths(bundle.appDirectory, bundle.appDirectory, filePaths);
|
|
84
|
+
const sortedPaths = Array.from(filePaths).sort((left, right) => left.localeCompare(right));
|
|
85
|
+
const appFiles = {};
|
|
86
|
+
for (const relativePath of sortedPaths) {
|
|
87
|
+
if (bundle.manifest.main.kind === "wasi-http-component" && relativePath === bundle.manifest.main.entry) {
|
|
88
|
+
appFiles[relativePath] = SOURCE_WASM_PLACEHOLDER_BYTES;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
appFiles[relativePath] = new Uint8Array(await readFile(path.join(bundle.appDirectory, relativePath)));
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
appFiles,
|
|
95
|
+
filePaths: sortedPaths
|
|
96
|
+
};
|
|
71
97
|
};
|
|
72
98
|
collectDirectoryPaths = async (directoryPath, appDirectory, filePaths) => {
|
|
73
99
|
try {
|
|
@@ -85,9 +111,32 @@ var AppBundleService = class {
|
|
|
85
111
|
return;
|
|
86
112
|
}
|
|
87
113
|
};
|
|
88
|
-
|
|
114
|
+
collectSourceDirectoryPaths = async (directoryPath, appDirectory, filePaths) => {
|
|
115
|
+
try {
|
|
116
|
+
const entries = await readdir(directoryPath, { withFileTypes: true });
|
|
117
|
+
for (const entry of entries) {
|
|
118
|
+
const entryPath = path.join(directoryPath, entry.name);
|
|
119
|
+
const relativePath = path.relative(appDirectory, entryPath).replace(/\\/g, "/");
|
|
120
|
+
if (entry.isDirectory()) {
|
|
121
|
+
if (this.shouldExcludeSourcePath(relativePath)) continue;
|
|
122
|
+
await this.collectSourceDirectoryPaths(entryPath, appDirectory, filePaths);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (!entry.isFile()) continue;
|
|
126
|
+
if (this.shouldExcludeSourcePath(relativePath)) continue;
|
|
127
|
+
filePaths.add(relativePath);
|
|
128
|
+
}
|
|
129
|
+
} catch {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
shouldExcludeSourcePath = (relativePath) => {
|
|
134
|
+
return relativePath === ".napp" || relativePath.startsWith(".napp/") || relativePath === "main/node_modules" || relativePath.startsWith("main/node_modules/") || relativePath === "main/dist" || relativePath.startsWith("main/dist/") || relativePath === "main/generated" || relativePath.startsWith("main/generated/");
|
|
135
|
+
};
|
|
136
|
+
buildMetadata = (appId, name, version, distributionMode) => {
|
|
89
137
|
return {
|
|
90
138
|
bundleFormatVersion: 1,
|
|
139
|
+
distributionMode,
|
|
91
140
|
appId,
|
|
92
141
|
name,
|
|
93
142
|
version,
|
|
@@ -95,6 +144,17 @@ var AppBundleService = class {
|
|
|
95
144
|
checksumsFile: ".napp/checksums.json"
|
|
96
145
|
};
|
|
97
146
|
};
|
|
147
|
+
normalizeMetadata = (rawMetadata) => {
|
|
148
|
+
return {
|
|
149
|
+
bundleFormatVersion: 1,
|
|
150
|
+
distributionMode: rawMetadata.distributionMode === "source" ? "source" : "bundle",
|
|
151
|
+
appId: String(rawMetadata.appId ?? ""),
|
|
152
|
+
name: String(rawMetadata.name ?? ""),
|
|
153
|
+
version: String(rawMetadata.version ?? ""),
|
|
154
|
+
entryManifest: "manifest.json",
|
|
155
|
+
checksumsFile: ".napp/checksums.json"
|
|
156
|
+
};
|
|
157
|
+
};
|
|
98
158
|
buildChecksums = (files) => {
|
|
99
159
|
const entries = Object.entries(files).sort(([left], [right]) => left.localeCompare(right));
|
|
100
160
|
return {
|
|
@@ -129,5 +189,6 @@ var AppBundleService = class {
|
|
|
129
189
|
}
|
|
130
190
|
};
|
|
131
191
|
};
|
|
192
|
+
const SOURCE_WASM_PLACEHOLDER_BYTES = Uint8Array.from(Buffer.from("AGFzbQEAAAABBwFgAn9/AX8DAgEABxMBD3N1bW1hcml6ZV9ub3RlcwAACg0BCwAgACABakHIAWoL", "base64"));
|
|
132
193
|
//#endregion
|
|
133
194
|
export { AppBundleService };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
//#region src/bundle/app-bundle.types.d.ts
|
|
2
|
+
type AppDistributionMode = "bundle" | "source";
|
|
2
3
|
type AppBundleMetadata = {
|
|
3
4
|
bundleFormatVersion: 1;
|
|
5
|
+
distributionMode: AppDistributionMode;
|
|
4
6
|
appId: string;
|
|
5
7
|
name: string;
|
|
6
8
|
version: string;
|
|
@@ -14,6 +16,8 @@ type AppBundleChecksums = {
|
|
|
14
16
|
type AppBundlePackResult = {
|
|
15
17
|
bundlePath: string;
|
|
16
18
|
metadata: AppBundleMetadata;
|
|
19
|
+
sizeBytes: number;
|
|
20
|
+
filePaths: string[];
|
|
17
21
|
};
|
|
18
22
|
type AppBundleExtractResult = {
|
|
19
23
|
appDirectory: string;
|
|
@@ -21,4 +25,4 @@ type AppBundleExtractResult = {
|
|
|
21
25
|
checksums: AppBundleChecksums;
|
|
22
26
|
};
|
|
23
27
|
//#endregion
|
|
24
|
-
export { AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult };
|
|
28
|
+
export { AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult, AppDistributionMode };
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { version } from "../package.js";
|
|
2
2
|
import { CreateCommand } from "../commands/create.controller.js";
|
|
3
|
+
import { AppRuntimeToolchainService } from "../runtime/app-runtime-toolchain.service.js";
|
|
4
|
+
import { AppBuildService } from "../runtime/app-build.service.js";
|
|
3
5
|
import { RunCommand } from "../commands/run.controller.js";
|
|
4
6
|
import { DevCommand } from "../commands/dev.controller.js";
|
|
5
7
|
import { GrantCommand } from "../commands/grant.controller.js";
|
|
@@ -14,8 +16,7 @@ import { RegistryCommand } from "../commands/registry.controller.js";
|
|
|
14
16
|
import { RevokeCommand } from "../commands/revoke.controller.js";
|
|
15
17
|
import { UninstallCommand } from "../commands/uninstall.controller.js";
|
|
16
18
|
import { UpdateCommand } from "../commands/update.controller.js";
|
|
17
|
-
import {
|
|
18
|
-
import { AppBuildService } from "../runtime/app-build.service.js";
|
|
19
|
+
import { ValidatePublishCommand } from "../commands/validate-publish.controller.js";
|
|
19
20
|
import { AppRuntimeOptionsService } from "./app-runtime-options.service.js";
|
|
20
21
|
//#region src/cli/app-runtime-cli.service.ts
|
|
21
22
|
var AppRuntimeCliService = class {
|
|
@@ -64,6 +65,9 @@ var AppRuntimeCliService = class {
|
|
|
64
65
|
case "publish":
|
|
65
66
|
await this.handlePublish(restArgs);
|
|
66
67
|
return;
|
|
68
|
+
case "validate-publish":
|
|
69
|
+
await this.handleValidatePublish(restArgs);
|
|
70
|
+
return;
|
|
67
71
|
case "install":
|
|
68
72
|
await this.handleInstall(restArgs);
|
|
69
73
|
return;
|
|
@@ -187,6 +191,7 @@ var AppRuntimeCliService = class {
|
|
|
187
191
|
await new PackCommand().run({
|
|
188
192
|
appDirectory: target,
|
|
189
193
|
outputPath: options.outputPath,
|
|
194
|
+
mode: options.mode,
|
|
190
195
|
json: options.json,
|
|
191
196
|
write: this.write
|
|
192
197
|
});
|
|
@@ -199,6 +204,18 @@ var AppRuntimeCliService = class {
|
|
|
199
204
|
metadataPath: options.metadataPath,
|
|
200
205
|
apiBaseUrl: options.apiBaseUrl,
|
|
201
206
|
token: options.token,
|
|
207
|
+
mode: options.mode,
|
|
208
|
+
json: options.json,
|
|
209
|
+
write: this.write
|
|
210
|
+
});
|
|
211
|
+
};
|
|
212
|
+
handleValidatePublish = async (restArgs) => {
|
|
213
|
+
const { target, optionArgs } = this.optionsService.readTarget("validate-publish", restArgs);
|
|
214
|
+
const options = this.optionsService.readPublishOptions(optionArgs);
|
|
215
|
+
await new ValidatePublishCommand().run({
|
|
216
|
+
appDirectory: target,
|
|
217
|
+
metadataPath: options.metadataPath,
|
|
218
|
+
mode: options.mode,
|
|
202
219
|
json: options.json,
|
|
203
220
|
write: this.write
|
|
204
221
|
});
|
|
@@ -322,13 +339,14 @@ var AppRuntimeCliService = class {
|
|
|
322
339
|
});
|
|
323
340
|
};
|
|
324
341
|
writeUsage = () => {
|
|
325
|
-
this.write("Usage: napp create <app-dir> [--template starter|ts-http] [--json]\n");
|
|
342
|
+
this.write("Usage: napp create <app-dir> [--template starter|ts-http|ts-http-lite] [--json]\n");
|
|
326
343
|
this.write(" napp inspect <app-dir> [--json]\n");
|
|
327
344
|
this.write(" napp build <app-dir> [--install] [--json]\n");
|
|
328
345
|
this.write(" napp doctor [--json]\n");
|
|
329
346
|
this.write(" napp <run|dev> <app-dir|app-id> [--host 127.0.0.1] [--port 3100] [--data /path] [--json] [--document scope=/path]\n");
|
|
330
|
-
this.write(" napp pack <app-dir> [--out bundle.napp] [--json]\n");
|
|
331
|
-
this.write(" napp publish <app-dir> [--meta marketplace.json] [--api-base <url>] [--token <token>] [--json]\n");
|
|
347
|
+
this.write(" napp pack <app-dir> [--mode source|bundle] [--out bundle.napp] [--json]\n");
|
|
348
|
+
this.write(" napp publish <app-dir> [--mode source|bundle] [--meta marketplace.json] [--api-base <url>] [--token <token>] [--json]\n");
|
|
349
|
+
this.write(" napp validate-publish <app-dir> [--mode source|bundle] [--meta marketplace.json] [--json]\n");
|
|
332
350
|
this.write(" napp install <app-dir|bundle.napp|app-id[@version]> [--registry <url>] [--json]\n");
|
|
333
351
|
this.write(" napp update <app-id> [--version <version>] [--registry <url>] [--json]\n");
|
|
334
352
|
this.write(" napp uninstall <app-id> [--purge-data] [--json]\n");
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AppDistributionMode } from "../bundle/app-bundle.types.js";
|
|
1
2
|
import { AppDocumentGrantMap } from "../permissions/app-permissions.types.js";
|
|
2
3
|
import { AppScaffoldTemplate } from "../scaffold/app-scaffold.service.js";
|
|
3
4
|
|
|
@@ -16,6 +17,7 @@ type CreateCliOptions = {
|
|
|
16
17
|
type PackCliOptions = {
|
|
17
18
|
json: boolean;
|
|
18
19
|
outputPath?: string;
|
|
20
|
+
mode: AppDistributionMode;
|
|
19
21
|
};
|
|
20
22
|
type BuildCliOptions = {
|
|
21
23
|
json: boolean;
|
|
@@ -50,6 +52,7 @@ type PublishCliOptions = {
|
|
|
50
52
|
metadataPath?: string;
|
|
51
53
|
apiBaseUrl?: string;
|
|
52
54
|
token?: string;
|
|
55
|
+
mode: AppDistributionMode;
|
|
53
56
|
};
|
|
54
57
|
declare class AppRuntimeOptionsService {
|
|
55
58
|
readTarget: (command: string, rawArgs: string[]) => {
|
|
@@ -68,6 +71,7 @@ declare class AppRuntimeOptionsService {
|
|
|
68
71
|
readGrantOptions: (rawArgs: string[]) => GrantCliOptions;
|
|
69
72
|
readRevokeOptions: (rawArgs: string[]) => RevokeCliOptions;
|
|
70
73
|
readPublishOptions: (rawArgs: string[]) => PublishCliOptions;
|
|
74
|
+
private readDistributionMode;
|
|
71
75
|
private assignDocumentGrant;
|
|
72
76
|
private readDocumentScopeId;
|
|
73
77
|
private requireOptionValue;
|
|
@@ -31,11 +31,14 @@ var AppRuntimeOptionsService = class {
|
|
|
31
31
|
return options;
|
|
32
32
|
};
|
|
33
33
|
readCreateTemplate = (rawTemplate) => {
|
|
34
|
-
if (rawTemplate === "starter" || rawTemplate === "ts-http") return rawTemplate;
|
|
35
|
-
throw new Error("--template 只支持 starter 或 ts-http。");
|
|
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
36
|
};
|
|
37
37
|
readPackOptions = (rawArgs) => {
|
|
38
|
-
const options = {
|
|
38
|
+
const options = {
|
|
39
|
+
json: false,
|
|
40
|
+
mode: "source"
|
|
41
|
+
};
|
|
39
42
|
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
40
43
|
const current = rawArgs[index];
|
|
41
44
|
if (!current?.startsWith("--")) throw new Error(`未知参数:${current}`);
|
|
@@ -48,6 +51,10 @@ var AppRuntimeOptionsService = class {
|
|
|
48
51
|
options.outputPath = this.requireOptionValue(current, nextValue);
|
|
49
52
|
index += 1;
|
|
50
53
|
break;
|
|
54
|
+
case "--mode":
|
|
55
|
+
options.mode = this.readDistributionMode(this.requireOptionValue(current, nextValue));
|
|
56
|
+
index += 1;
|
|
57
|
+
break;
|
|
51
58
|
default: throw new Error(`未知参数:${current}`);
|
|
52
59
|
}
|
|
53
60
|
}
|
|
@@ -231,7 +238,10 @@ var AppRuntimeOptionsService = class {
|
|
|
231
238
|
return options;
|
|
232
239
|
};
|
|
233
240
|
readPublishOptions = (rawArgs) => {
|
|
234
|
-
const options = {
|
|
241
|
+
const options = {
|
|
242
|
+
json: false,
|
|
243
|
+
mode: "source"
|
|
244
|
+
};
|
|
235
245
|
for (let index = 0; index < rawArgs.length; index += 1) {
|
|
236
246
|
const current = rawArgs[index];
|
|
237
247
|
if (!current?.startsWith("--")) throw new Error(`未知参数:${current}`);
|
|
@@ -252,11 +262,19 @@ var AppRuntimeOptionsService = class {
|
|
|
252
262
|
options.token = this.requireOptionValue(current, nextValue);
|
|
253
263
|
index += 1;
|
|
254
264
|
break;
|
|
265
|
+
case "--mode":
|
|
266
|
+
options.mode = this.readDistributionMode(this.requireOptionValue(current, nextValue));
|
|
267
|
+
index += 1;
|
|
268
|
+
break;
|
|
255
269
|
default: throw new Error(`未知参数:${current}`);
|
|
256
270
|
}
|
|
257
271
|
}
|
|
258
272
|
return options;
|
|
259
273
|
};
|
|
274
|
+
readDistributionMode = (rawMode) => {
|
|
275
|
+
if (rawMode === "source" || rawMode === "bundle") return rawMode;
|
|
276
|
+
throw new Error("--mode 只支持 source 或 bundle。");
|
|
277
|
+
};
|
|
260
278
|
assignDocumentGrant = (documentGrantMap, rawGrant) => {
|
|
261
279
|
const delimiterIndex = rawGrant.indexOf("=");
|
|
262
280
|
if (delimiterIndex < 1) throw new Error("--document 必须使用 scopeId=/absolute/or/relative/path 格式。");
|
|
@@ -5,10 +5,11 @@ var PackCommand = class {
|
|
|
5
5
|
this.bundleService = bundleService;
|
|
6
6
|
}
|
|
7
7
|
run = async (params) => {
|
|
8
|
-
const { appDirectory, outputPath, json, write } = params;
|
|
8
|
+
const { appDirectory, outputPath, mode, json, write } = params;
|
|
9
9
|
const result = await this.bundleService.packAppDirectory({
|
|
10
10
|
appDirectory,
|
|
11
|
-
outputPath
|
|
11
|
+
outputPath,
|
|
12
|
+
mode
|
|
12
13
|
});
|
|
13
14
|
if (json) {
|
|
14
15
|
write(`${JSON.stringify({
|
|
@@ -17,7 +18,7 @@ var PackCommand = class {
|
|
|
17
18
|
}, null, 2)}\n`);
|
|
18
19
|
return;
|
|
19
20
|
}
|
|
20
|
-
write(`Packed ${result.metadata.name} ${result.metadata.version}\n`);
|
|
21
|
+
write(`Packed ${result.metadata.name} ${result.metadata.version} (${result.metadata.distributionMode})\n`);
|
|
21
22
|
write(`Bundle: ${result.bundlePath}\n`);
|
|
22
23
|
};
|
|
23
24
|
};
|
|
@@ -5,12 +5,13 @@ var PublishCommand = class {
|
|
|
5
5
|
this.publishService = publishService;
|
|
6
6
|
}
|
|
7
7
|
run = async (params) => {
|
|
8
|
-
const { appDirectory, metadataPath, apiBaseUrl, token, json, write } = params;
|
|
8
|
+
const { appDirectory, metadataPath, apiBaseUrl, token, mode, json, write } = params;
|
|
9
9
|
const result = await this.publishService.publish({
|
|
10
10
|
appDirectory,
|
|
11
11
|
metadataPath,
|
|
12
12
|
apiBaseUrl,
|
|
13
|
-
token
|
|
13
|
+
token,
|
|
14
|
+
mode
|
|
14
15
|
});
|
|
15
16
|
if (json) {
|
|
16
17
|
write(`${JSON.stringify({
|
|
@@ -20,7 +21,7 @@ var PublishCommand = class {
|
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
23
|
write(`${result.created ? "Published" : "Updated"} ${result.item.name} (${result.item.appId}) ${result.item.latestVersion}\n`);
|
|
23
|
-
write(`
|
|
24
|
+
write(`Distribution: ${result.distribution.path} (${result.distribution.mode})\n`);
|
|
24
25
|
if (result.item.webUrl) write(`Details: ${result.item.webUrl}\n`);
|
|
25
26
|
write(`Install: ${result.item.install.command}\n`);
|
|
26
27
|
};
|
|
@@ -0,0 +1,16 @@
|
|
|
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
|
+
mode: "source" | "bundle";
|
|
11
|
+
json: boolean;
|
|
12
|
+
write: (text: string) => void;
|
|
13
|
+
}) => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
//#endregion
|
|
16
|
+
export { ValidatePublishCommand };
|
|
@@ -0,0 +1,33 @@
|
|
|
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, mode, json, write } = params;
|
|
9
|
+
const result = await this.validationService.validate({
|
|
10
|
+
appDirectory,
|
|
11
|
+
metadataPath,
|
|
12
|
+
mode
|
|
13
|
+
});
|
|
14
|
+
if (json) {
|
|
15
|
+
write(`${JSON.stringify({
|
|
16
|
+
ok: true,
|
|
17
|
+
validation: result
|
|
18
|
+
}, null, 2)}\n`);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
write(`Publish validation ok for ${result.appId}@${result.version}\n`);
|
|
22
|
+
write(`Distribution mode: ${result.distributionMode}\n`);
|
|
23
|
+
write(`Main kind: ${result.mainKind}\n`);
|
|
24
|
+
write(`Main: ${result.mainEntryPath}\n`);
|
|
25
|
+
write(`Metadata: ${result.metadataPath}\n`);
|
|
26
|
+
write(`Bundle size: ${result.bundleSizeBytes} bytes\n`);
|
|
27
|
+
write(`Main entry size: ${result.mainEntrySizeBytes} bytes\n`);
|
|
28
|
+
write(`Bundle files (${result.bundleFilePaths.length}): ${result.bundleFilePaths.join(", ")}\n`);
|
|
29
|
+
if (result.warnings.length > 0) for (const warning of result.warnings) write(`Warning [${warning.code}]: ${warning.message}\n`);
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
33
|
+
export { ValidatePublishCommand };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
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
|
-
import { AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult } from "./bundle/app-bundle.types.js";
|
|
3
|
+
import { AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult, AppDistributionMode } from "./bundle/app-bundle.types.js";
|
|
4
4
|
import { AppBundleService } from "./bundle/app-bundle.service.js";
|
|
5
5
|
import { AppDocumentGrantMap, AppDocumentGrantMutationResult, AppDocumentGrantState, AppInstalledPermissionState, AppPermissionSummary, ResolvedDocumentGrant, ResolvedPermissions } from "./permissions/app-permissions.types.js";
|
|
6
6
|
import { AppPermissionsService } from "./permissions/app-permissions.service.js";
|
|
@@ -11,6 +11,7 @@ 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
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";
|
|
14
15
|
import { AppScaffoldResult, AppScaffoldService, AppScaffoldTemplate } from "./scaffold/app-scaffold.service.js";
|
|
15
16
|
import { AppRuntimeOptionsService, BuildCliOptions, CreateCliOptions, GrantCliOptions, InstallCliOptions, JsonOnlyCliOptions, PackCliOptions, PublishCliOptions, RevokeCliOptions, RuntimeCliOptions, UninstallCliOptions, UpdateCliOptions } from "./cli/app-runtime-options.service.js";
|
|
16
17
|
import { AppRuntimeCliService } from "./cli/app-runtime-cli.service.js";
|
|
@@ -21,6 +22,8 @@ import { AppInstallSourceKind, AppRegistry, AppRegistryAppRecord, AppRegistryIns
|
|
|
21
22
|
import { AppRegistryService } from "./registry/app-registry.service.js";
|
|
22
23
|
import { AppGrantService } from "./permissions/app-grant.service.js";
|
|
23
24
|
import { GrantCommand } from "./commands/grant.controller.js";
|
|
25
|
+
import { AppRuntimeCommandResult, AppRuntimeDoctorResult, AppRuntimeToolStatus, AppRuntimeToolchainService } from "./runtime/app-runtime-toolchain.service.js";
|
|
26
|
+
import { AppBuildResult, AppBuildService } from "./runtime/app-build.service.js";
|
|
24
27
|
import { AppRegistryConfigService } from "./registry/app-registry-config.service.js";
|
|
25
28
|
import { AppRemoteRegistryClientService } from "./registry/app-remote-registry-client.service.js";
|
|
26
29
|
import { AppInfoResult, AppInstallResult, AppLaunchResolution, AppUninstallResult, AppUpdateResult, InstalledAppListItem } from "./install/app-installation.types.js";
|
|
@@ -40,9 +43,9 @@ import { RegistryCommand } from "./commands/registry.controller.js";
|
|
|
40
43
|
import { RevokeCommand } from "./commands/revoke.controller.js";
|
|
41
44
|
import { UpdateCommand } from "./commands/update.controller.js";
|
|
42
45
|
import { UninstallCommand } from "./commands/uninstall.controller.js";
|
|
46
|
+
import { AppPublishValidationResult, AppPublishValidationService, AppPublishValidationWarning, AppPublishValidationWarningCode } from "./publish/app-publish-validation.service.js";
|
|
47
|
+
import { ValidatePublishCommand } from "./commands/validate-publish.controller.js";
|
|
43
48
|
import { WasmtimeWasiHttpComponentHandle, WasmtimeWasiHttpComponentService, WasmtimeWasiHttpComponentStartOptions } from "./runtime/wasmtime-wasi-http-component.service.js";
|
|
44
49
|
import { AppHostHandle, AppHostService, AppHostStartOptions } from "./host/app-host.service.js";
|
|
45
|
-
import { AppRuntimeCommandResult, AppRuntimeDoctorResult, AppRuntimeToolStatus, AppRuntimeToolchainService } from "./runtime/app-runtime-toolchain.service.js";
|
|
46
|
-
import { AppBuildResult, AppBuildService } from "./runtime/app-build.service.js";
|
|
47
50
|
import { UiServerService } from "./ui/ui-server.service.js";
|
|
48
|
-
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, AppPublisher, AppRegistry, AppRegistryAppRecord, AppRegistryConfig, AppRegistryConfigService, AppRegistryConfigSnapshot, AppRegistryInstalledVersion, AppRegistryService, AppRemoteRegistryClientService, AppRemoteRegistryDocument, AppRemoteRegistryResolution, AppRemoteRegistryVersion, AppRunResult, AppRuntimeCliService, AppRuntimeCommandResult, AppRuntimeDoctorResult, AppRuntimeOptionsService, AppRuntimeToolStatus, AppRuntimeToolchainService, AppScaffoldFile, AppScaffoldResult, AppScaffoldService, AppScaffoldTemplate, 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, WasmDocumentSummaryInput, WasmMainRunnerService, WasmSidecarClientService, WasmtimeWasiHttpComponentHandle, WasmtimeWasiHttpComponentService, WasmtimeWasiHttpComponentStartOptions };
|
|
51
|
+
export { AppBuildResult, AppBuildService, AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult, AppBundleService, AppCoreWasmMainManifest, AppDistributionMode, 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 };
|