@nextclaw/app-runtime 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +125 -4
  2. package/dist/bundle/app-bundle.service.d.ts +27 -0
  3. package/dist/bundle/app-bundle.service.js +133 -0
  4. package/dist/bundle/app-bundle.types.d.ts +24 -0
  5. package/dist/cli/app-runtime-cli.service.d.ts +28 -0
  6. package/dist/cli/app-runtime-cli.service.js +298 -0
  7. package/dist/cli/app-runtime-options.service.d.ts +67 -0
  8. package/dist/cli/app-runtime-options.service.js +242 -0
  9. package/dist/commands/create.controller.d.ts +14 -0
  10. package/dist/commands/grant.controller.d.ts +16 -0
  11. package/dist/commands/grant.controller.js +25 -0
  12. package/dist/commands/info.controller.d.ts +14 -0
  13. package/dist/commands/info.controller.js +27 -0
  14. package/dist/commands/install.controller.d.ts +15 -0
  15. package/dist/commands/install.controller.js +24 -0
  16. package/dist/commands/list.controller.d.ts +13 -0
  17. package/dist/commands/list.controller.js +25 -0
  18. package/dist/commands/pack.controller.d.ts +15 -0
  19. package/dist/commands/pack.controller.js +25 -0
  20. package/dist/commands/permissions.controller.d.ts +14 -0
  21. package/dist/commands/permissions.controller.js +26 -0
  22. package/dist/commands/publish.controller.d.ts +17 -0
  23. package/dist/commands/publish.controller.js +29 -0
  24. package/dist/commands/registry.controller.d.ts +16 -0
  25. package/dist/commands/registry.controller.js +27 -0
  26. package/dist/commands/revoke.controller.d.ts +15 -0
  27. package/dist/commands/revoke.controller.js +24 -0
  28. package/dist/commands/run.controller.js +14 -6
  29. package/dist/commands/uninstall.controller.d.ts +15 -0
  30. package/dist/commands/uninstall.controller.js +23 -0
  31. package/dist/commands/update.controller.d.ts +16 -0
  32. package/dist/commands/update.controller.js +29 -0
  33. package/dist/host/app-instance.service.d.ts +3 -1
  34. package/dist/host/app-instance.service.js +2 -2
  35. package/dist/index.d.ts +31 -2
  36. package/dist/index.js +28 -2
  37. package/dist/install/app-installation.service.d.ts +37 -0
  38. package/dist/install/app-installation.service.js +255 -0
  39. package/dist/install/app-installation.types.d.ts +62 -0
  40. package/dist/main.js +5 -132
  41. package/dist/package.js +1 -1
  42. package/dist/paths/app-home.service.d.ts +16 -0
  43. package/dist/paths/app-home.service.js +42 -0
  44. package/dist/permissions/app-grant.service.d.ts +22 -0
  45. package/dist/permissions/app-grant.service.js +63 -0
  46. package/dist/permissions/app-permissions.service.d.ts +3 -1
  47. package/dist/permissions/app-permissions.service.js +12 -5
  48. package/dist/permissions/app-permissions.types.d.ts +28 -1
  49. package/dist/publish/app-marketplace-client.service.d.ts +13 -0
  50. package/dist/publish/app-marketplace-client.service.js +31 -0
  51. package/dist/publish/app-marketplace-metadata.service.d.ts +27 -0
  52. package/dist/publish/app-marketplace-metadata.service.js +84 -0
  53. package/dist/publish/app-publish.service.d.ts +22 -0
  54. package/dist/publish/app-publish.service.js +74 -0
  55. package/dist/publish/app-publish.types.d.ts +66 -0
  56. package/dist/publish/app-publish.types.js +4 -0
  57. package/dist/registry/app-registry-config.service.d.ts +16 -0
  58. package/dist/registry/app-registry-config.service.js +84 -0
  59. package/dist/registry/app-registry.service.d.ts +38 -0
  60. package/dist/registry/app-registry.service.js +115 -0
  61. package/dist/registry/app-registry.types.d.ts +33 -0
  62. package/dist/registry/app-remote-registry-client.service.d.ts +28 -0
  63. package/dist/registry/app-remote-registry-client.service.js +114 -0
  64. package/dist/registry/app-remote-registry.types.d.ts +52 -0
  65. package/dist/registry/app-remote-registry.types.js +4 -0
  66. package/dist/scaffold/app-scaffold.service.d.ts +21 -0
  67. package/dist/scaffold/app-scaffold.service.js +55 -1
  68. package/package.json +4 -2
package/README.md CHANGED
@@ -2,12 +2,23 @@
2
2
 
3
3
  `@nextclaw/app-runtime` 是一个独立的微应用 runtime/CLI 包。
4
4
 
5
- 当前 MVP 提供三件事:
5
+ 当前相对完善 MVP 提供下面这些能力:
6
6
 
7
7
  - `napp create <app-dir>`:生成一个最小可跑的微应用骨架
8
8
  - `napp inspect <app-dir>`:校验应用目录与 manifest
9
- - `napp run <app-dir>`:启动本地宿主,提供 UI 静态服务和桥接 API
9
+ - `napp run <app-dir|app-id>`:启动本地宿主,支持目录运行和已安装应用运行
10
10
  - `napp dev <app-dir>`:当前等价于 `run`
11
+ - `napp pack <app-dir>`:把应用目录打成 `.napp` bundle
12
+ - `napp publish <app-dir>`:把应用目录发布到官方 apps registry
13
+ - `napp install <app-dir|bundle.napp|app-id[@version]>`:从本地或 registry 安装应用
14
+ - `napp update <app-id>`:更新已安装应用
15
+ - `napp uninstall <app-id>`:卸载已安装应用
16
+ - `napp list`:列出已安装应用
17
+ - `napp info <app-id>`:查看已安装应用详情
18
+ - `napp registry [get|set|reset]`:查看或切换 registry
19
+ - `napp permissions <app-id>`:查看应用权限状态
20
+ - `napp grant <app-id> --document scope=/path`:写入目录授权
21
+ - `napp revoke <app-id> --document scope`:撤销目录授权
11
22
 
12
23
  ## 安装
13
24
 
@@ -22,7 +33,7 @@ napp --help
22
33
  napp --version
23
34
  ```
24
35
 
25
- 第一版先聚焦“独立可运行的微应用宿主”,不接入现有 NextClaw 主产品路由、服务或传播层。
36
+ 第一版先聚焦“独立可运行的微应用宿主 + 可分发、可安装、可更新、可授权的 CLI/runtime 闭环”,不接入现有 NextClaw 主产品路由、服务或 GUI app store。
26
37
 
27
38
  ## 应用目录
28
39
 
@@ -42,18 +53,128 @@ assets/
42
53
  - 宿主桥接:`/__napp/*`
43
54
  - 权限词汇:`documentAccess`、`allowedDomains`、`storage`、`capabilities`
44
55
  - 当前 Wasm 执行底座:Node 原生 `WebAssembly`
56
+ - 分发包形态:`.napp`(底层为 zip)
57
+ - 安装目录:`~/.nextclaw/apps/packages/<app-id>/<version>/`
58
+ - 用户数据目录:`~/.nextclaw/apps/data/<app-id>/`
59
+ - 本地 registry:`~/.nextclaw/apps/registry.json`
60
+ - 本地 config:`~/.nextclaw/apps/config.json`
61
+ - 默认 registry:`https://apps-registry.nextclaw.io/api/v1/apps/registry/`
62
+
63
+ ## 当前 MVP 工作流
64
+
65
+ 开发者工作流:
66
+
67
+ ```bash
68
+ napp create ./my-first-napp
69
+ napp inspect ./my-first-napp
70
+ napp pack ./my-first-napp
71
+ napp publish ./my-first-napp
72
+ ```
73
+
74
+ 本地安装工作流:
75
+
76
+ ```bash
77
+ napp install ./my-first-napp
78
+ napp list
79
+ napp info nextclaw.my-first-napp
80
+ napp run nextclaw.my-first-napp
81
+ ```
82
+
83
+ registry 安装与更新工作流:
84
+
85
+ ```bash
86
+ napp registry set https://registry.example.com/
87
+ napp install nextclaw.hello-notes
88
+ napp permissions nextclaw.hello-notes
89
+ napp grant nextclaw.hello-notes --document notes=/absolute/path/to/notes
90
+ napp run nextclaw.hello-notes
91
+ napp update nextclaw.hello-notes
92
+ ```
93
+
94
+ 卸载与权限回收:
95
+
96
+ ```bash
97
+ napp revoke nextclaw.my-first-napp --document notes
98
+ napp uninstall nextclaw.my-first-napp
99
+ napp uninstall nextclaw.my-first-napp --purge-data
100
+ ```
45
101
 
46
102
  ## 示例
47
103
 
48
104
  ```bash
49
105
  napp create ./my-first-napp
50
106
  napp inspect ./my-first-napp
51
- napp run ./my-first-napp
107
+ napp pack ./my-first-napp
108
+ napp install ./my-first-napp
109
+ napp list
110
+ napp info nextclaw.my-first-napp
111
+ napp permissions nextclaw.my-first-napp
112
+ napp run nextclaw.my-first-napp
52
113
  ```
53
114
 
54
115
  已有示例应用:
55
116
 
56
117
  ```bash
57
118
  napp inspect ./apps/examples/hello-notes
119
+ napp pack ./apps/examples/hello-notes
120
+ napp publish ./apps/examples/hello-notes
121
+ napp install ./apps/examples/hello-notes
122
+ napp grant nextclaw.hello-notes --document notes=/absolute/path/to/notes
58
123
  napp run ./apps/examples/hello-notes --document notes=/absolute/path/to/notes
59
124
  ```
125
+
126
+ registry 示例:
127
+
128
+ ```bash
129
+ napp registry get
130
+ napp registry set https://registry.example.com/
131
+ napp install nextclaw.hello-notes
132
+ napp update nextclaw.hello-notes
133
+ ```
134
+
135
+ 官方 apps 入口:
136
+
137
+ - Web:`https://apps.nextclaw.io`
138
+ - Registry/API:`https://apps-registry.nextclaw.io`
139
+
140
+ ## Bundle 结构
141
+
142
+ `.napp` bundle 的最小结构如下:
143
+
144
+ ```text
145
+ manifest.json
146
+ main/
147
+ ui/
148
+ assets/
149
+ .napp/
150
+ bundle.json
151
+ checksums.json
152
+ ```
153
+
154
+ ## Registry Metadata 结构
155
+
156
+ registry 按 npm 风格使用一个 base URL,再按 app id 拉取 metadata 文档。metadata 的最小结构如下:
157
+
158
+ ```json
159
+ {
160
+ "name": "nextclaw.hello-notes",
161
+ "description": "Registry-hosted Hello Notes",
162
+ "dist-tags": {
163
+ "latest": "0.2.0"
164
+ },
165
+ "versions": {
166
+ "0.2.0": {
167
+ "name": "nextclaw.hello-notes",
168
+ "version": "0.2.0",
169
+ "publisher": {
170
+ "id": "nextclaw",
171
+ "name": "NextClaw Official"
172
+ },
173
+ "dist": {
174
+ "bundle": "./-/hello-notes-0.2.0.napp",
175
+ "sha256": "<sha256>"
176
+ }
177
+ }
178
+ }
179
+ }
180
+ ```
@@ -0,0 +1,27 @@
1
+ import { AppManifestService } from "../manifest/app-manifest.service.js";
2
+ import { AppBundleExtractResult, AppBundlePackResult } from "./app-bundle.types.js";
3
+
4
+ //#region src/bundle/app-bundle.service.d.ts
5
+ declare class AppBundleService {
6
+ private readonly manifestService;
7
+ constructor(manifestService?: AppManifestService);
8
+ packAppDirectory: (params: {
9
+ appDirectory: string;
10
+ outputPath?: string;
11
+ }) => Promise<AppBundlePackResult>;
12
+ extractBundle: (params: {
13
+ bundlePath: string;
14
+ targetDirectory: string;
15
+ }) => Promise<AppBundleExtractResult>;
16
+ private collectAppFiles;
17
+ private collectDirectoryPaths;
18
+ private buildMetadata;
19
+ private buildChecksums;
20
+ private computeSha256;
21
+ private normalizeBundleFileName;
22
+ private normalizeArchiveEntry;
23
+ private readJsonFile;
24
+ private verifyChecksums;
25
+ }
26
+ //#endregion
27
+ export { AppBundleService };
@@ -0,0 +1,133 @@
1
+ import { AppManifestService } from "../manifest/app-manifest.service.js";
2
+ import { mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
3
+ import { createHash } from "node:crypto";
4
+ import path from "node:path";
5
+ import { strToU8, unzipSync, zipSync } from "fflate";
6
+ //#region src/bundle/app-bundle.service.ts
7
+ var AppBundleService = class {
8
+ constructor(manifestService = new AppManifestService()) {
9
+ this.manifestService = manifestService;
10
+ }
11
+ packAppDirectory = async (params) => {
12
+ const bundle = await this.manifestService.load(params.appDirectory);
13
+ const appFiles = await this.collectAppFiles(bundle.appDirectory);
14
+ const metadata = this.buildMetadata(bundle.manifest.id, bundle.manifest.name, bundle.manifest.version);
15
+ const bundleJsonPath = ".napp/bundle.json";
16
+ const checksumsJsonPath = ".napp/checksums.json";
17
+ const bundleJsonBytes = strToU8(`${JSON.stringify(metadata, null, 2)}\n`);
18
+ const checksums = this.buildChecksums({
19
+ ...appFiles,
20
+ [bundleJsonPath]: bundleJsonBytes
21
+ });
22
+ const checksumsJsonBytes = strToU8(`${JSON.stringify(checksums, null, 2)}\n`);
23
+ const archiveBytes = zipSync({
24
+ ...appFiles,
25
+ [bundleJsonPath]: bundleJsonBytes,
26
+ [checksumsJsonPath]: checksumsJsonBytes
27
+ }, { level: 9 });
28
+ const outputPath = params.outputPath ? path.resolve(params.outputPath) : path.join(path.dirname(bundle.appDirectory), `${this.normalizeBundleFileName(bundle.manifest.id)}-${bundle.manifest.version}.napp`);
29
+ await mkdir(path.dirname(outputPath), { recursive: true });
30
+ await writeFile(outputPath, Buffer.from(archiveBytes));
31
+ return {
32
+ bundlePath: outputPath,
33
+ metadata
34
+ };
35
+ };
36
+ extractBundle = async (params) => {
37
+ const bundlePath = path.resolve(params.bundlePath);
38
+ const targetDirectory = path.resolve(params.targetDirectory);
39
+ await rm(targetDirectory, {
40
+ recursive: true,
41
+ force: true
42
+ });
43
+ await mkdir(targetDirectory, { recursive: true });
44
+ const archive = unzipSync(new Uint8Array(await readFile(bundlePath)));
45
+ const entryNames = Object.keys(archive).sort((left, right) => left.localeCompare(right));
46
+ for (const entryName of entryNames) {
47
+ const normalizedEntry = this.normalizeArchiveEntry(entryName);
48
+ const targetPath = path.join(targetDirectory, normalizedEntry);
49
+ await mkdir(path.dirname(targetPath), { recursive: true });
50
+ await writeFile(targetPath, Buffer.from(archive[entryName]));
51
+ }
52
+ const metadata = await this.readJsonFile(path.join(targetDirectory, ".napp", "bundle.json"), "bundle metadata");
53
+ const checksums = await this.readJsonFile(path.join(targetDirectory, ".napp", "checksums.json"), "bundle checksums");
54
+ await this.verifyChecksums(targetDirectory, checksums);
55
+ await this.manifestService.load(targetDirectory);
56
+ return {
57
+ appDirectory: targetDirectory,
58
+ metadata,
59
+ checksums
60
+ };
61
+ };
62
+ collectAppFiles = async (appDirectory) => {
63
+ const filePaths = new Set(["manifest.json"]);
64
+ await this.collectDirectoryPaths(path.join(appDirectory, "main"), appDirectory, filePaths);
65
+ await this.collectDirectoryPaths(path.join(appDirectory, "ui"), appDirectory, filePaths);
66
+ await this.collectDirectoryPaths(path.join(appDirectory, "assets"), appDirectory, filePaths);
67
+ const sortedPaths = Array.from(filePaths).sort((left, right) => left.localeCompare(right));
68
+ const appFiles = {};
69
+ for (const relativePath of sortedPaths) appFiles[relativePath] = new Uint8Array(await readFile(path.join(appDirectory, relativePath)));
70
+ return appFiles;
71
+ };
72
+ collectDirectoryPaths = async (directoryPath, appDirectory, filePaths) => {
73
+ try {
74
+ const entries = await readdir(directoryPath, { withFileTypes: true });
75
+ for (const entry of entries) {
76
+ const entryPath = path.join(directoryPath, entry.name);
77
+ if (entry.isDirectory()) {
78
+ await this.collectDirectoryPaths(entryPath, appDirectory, filePaths);
79
+ continue;
80
+ }
81
+ if (!entry.isFile()) continue;
82
+ filePaths.add(path.relative(appDirectory, entryPath));
83
+ }
84
+ } catch {
85
+ return;
86
+ }
87
+ };
88
+ buildMetadata = (appId, name, version) => {
89
+ return {
90
+ bundleFormatVersion: 1,
91
+ appId,
92
+ name,
93
+ version,
94
+ entryManifest: "manifest.json",
95
+ checksumsFile: ".napp/checksums.json"
96
+ };
97
+ };
98
+ buildChecksums = (files) => {
99
+ const entries = Object.entries(files).sort(([left], [right]) => left.localeCompare(right));
100
+ return {
101
+ algorithm: "sha256",
102
+ files: Object.fromEntries(entries.map(([relativePath, fileBytes]) => [relativePath, this.computeSha256(fileBytes)]))
103
+ };
104
+ };
105
+ computeSha256 = (fileBytes) => {
106
+ return createHash("sha256").update(Buffer.from(fileBytes)).digest("hex");
107
+ };
108
+ normalizeBundleFileName = (appId) => {
109
+ return appId.replace(/[^a-zA-Z0-9._-]+/g, "-");
110
+ };
111
+ normalizeArchiveEntry = (entryName) => {
112
+ const normalized = entryName.replace(/\\/g, "/");
113
+ if (!normalized || normalized.startsWith("/") || normalized.includes("../")) throw new Error(`bundle 内包含非法路径:${entryName}`);
114
+ return normalized;
115
+ };
116
+ readJsonFile = async (filePath, label) => {
117
+ try {
118
+ return JSON.parse(await readFile(filePath, "utf-8"));
119
+ } catch (error) {
120
+ throw new Error(`无法读取 ${label}:${error instanceof Error ? error.message : String(error)}`);
121
+ }
122
+ };
123
+ verifyChecksums = async (appDirectory, checksums) => {
124
+ if (checksums.algorithm !== "sha256") throw new Error("当前只支持 sha256 checksums。");
125
+ const entries = Object.entries(checksums.files).sort(([left], [right]) => left.localeCompare(right));
126
+ for (const [relativePath, expectedHash] of entries) {
127
+ const fileBytes = new Uint8Array(await readFile(path.join(appDirectory, relativePath)));
128
+ if (this.computeSha256(fileBytes) !== expectedHash) throw new Error(`bundle checksum 校验失败:${relativePath}`);
129
+ }
130
+ };
131
+ };
132
+ //#endregion
133
+ export { AppBundleService };
@@ -0,0 +1,24 @@
1
+ //#region src/bundle/app-bundle.types.d.ts
2
+ type AppBundleMetadata = {
3
+ bundleFormatVersion: 1;
4
+ appId: string;
5
+ name: string;
6
+ version: string;
7
+ entryManifest: "manifest.json";
8
+ checksumsFile: ".napp/checksums.json";
9
+ };
10
+ type AppBundleChecksums = {
11
+ algorithm: "sha256";
12
+ files: Record<string, string>;
13
+ };
14
+ type AppBundlePackResult = {
15
+ bundlePath: string;
16
+ metadata: AppBundleMetadata;
17
+ };
18
+ type AppBundleExtractResult = {
19
+ appDirectory: string;
20
+ metadata: AppBundleMetadata;
21
+ checksums: AppBundleChecksums;
22
+ };
23
+ //#endregion
24
+ export { AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult };
@@ -0,0 +1,28 @@
1
+ import { AppRuntimeOptionsService } from "./app-runtime-options.service.js";
2
+
3
+ //#region src/cli/app-runtime-cli.service.d.ts
4
+ declare class AppRuntimeCliService {
5
+ private readonly optionsService;
6
+ constructor(optionsService?: AppRuntimeOptionsService);
7
+ run: () => Promise<void>;
8
+ private dispatch;
9
+ private handleCreate;
10
+ private handleInspect;
11
+ private handleRun;
12
+ private handleDev;
13
+ private handlePack;
14
+ private handlePublish;
15
+ private handleInstall;
16
+ private handleUpdate;
17
+ private handleUninstall;
18
+ private handleList;
19
+ private handleInfo;
20
+ private handleRegistry;
21
+ private handlePermissions;
22
+ private handleGrant;
23
+ private handleRevoke;
24
+ private writeUsage;
25
+ private write;
26
+ }
27
+ //#endregion
28
+ export { AppRuntimeCliService };
@@ -0,0 +1,298 @@
1
+ import { version } from "../package.js";
2
+ import { CreateCommand } from "../commands/create.controller.js";
3
+ import { RunCommand } from "../commands/run.controller.js";
4
+ import { DevCommand } from "../commands/dev.controller.js";
5
+ import { GrantCommand } from "../commands/grant.controller.js";
6
+ import { InfoCommand } from "../commands/info.controller.js";
7
+ import { InspectCommand } from "../commands/inspect.controller.js";
8
+ import { InstallCommand } from "../commands/install.controller.js";
9
+ import { ListCommand } from "../commands/list.controller.js";
10
+ import { PackCommand } from "../commands/pack.controller.js";
11
+ import { PermissionsCommand } from "../commands/permissions.controller.js";
12
+ import { PublishCommand } from "../commands/publish.controller.js";
13
+ import { RegistryCommand } from "../commands/registry.controller.js";
14
+ import { RevokeCommand } from "../commands/revoke.controller.js";
15
+ import { UninstallCommand } from "../commands/uninstall.controller.js";
16
+ import { UpdateCommand } from "../commands/update.controller.js";
17
+ import { AppRuntimeOptionsService } from "./app-runtime-options.service.js";
18
+ //#region src/cli/app-runtime-cli.service.ts
19
+ var AppRuntimeCliService = class {
20
+ constructor(optionsService = new AppRuntimeOptionsService()) {
21
+ this.optionsService = optionsService;
22
+ }
23
+ run = async () => {
24
+ const [command, ...restArgs] = process.argv.slice(2);
25
+ if (command === "--help" || command === "help") {
26
+ this.writeUsage();
27
+ return;
28
+ }
29
+ if (command === "--version" || command === "version") {
30
+ this.write(`${version}\n`);
31
+ return;
32
+ }
33
+ if (!command) {
34
+ this.writeUsage();
35
+ process.exit(1);
36
+ }
37
+ await this.dispatch(command, restArgs);
38
+ };
39
+ dispatch = async (command, restArgs) => {
40
+ switch (command) {
41
+ case "create":
42
+ await this.handleCreate(restArgs);
43
+ return;
44
+ case "inspect":
45
+ await this.handleInspect(restArgs);
46
+ return;
47
+ case "run":
48
+ await this.handleRun(restArgs);
49
+ return;
50
+ case "dev":
51
+ await this.handleDev(restArgs);
52
+ return;
53
+ case "pack":
54
+ await this.handlePack(restArgs);
55
+ return;
56
+ case "publish":
57
+ await this.handlePublish(restArgs);
58
+ return;
59
+ case "install":
60
+ await this.handleInstall(restArgs);
61
+ return;
62
+ case "update":
63
+ await this.handleUpdate(restArgs);
64
+ return;
65
+ case "uninstall":
66
+ await this.handleUninstall(restArgs);
67
+ return;
68
+ case "list":
69
+ await this.handleList(restArgs);
70
+ return;
71
+ case "info":
72
+ await this.handleInfo(restArgs);
73
+ return;
74
+ case "registry":
75
+ await this.handleRegistry(restArgs);
76
+ return;
77
+ case "permissions":
78
+ await this.handlePermissions(restArgs);
79
+ return;
80
+ case "grant":
81
+ await this.handleGrant(restArgs);
82
+ return;
83
+ case "revoke":
84
+ await this.handleRevoke(restArgs);
85
+ return;
86
+ default:
87
+ this.writeUsage();
88
+ process.exit(1);
89
+ }
90
+ };
91
+ handleCreate = async (restArgs) => {
92
+ const { target, optionArgs } = this.optionsService.readTarget("create", restArgs);
93
+ const options = this.optionsService.readCreateOptions(optionArgs);
94
+ await new CreateCommand().run({
95
+ appDirectory: target,
96
+ json: options.json,
97
+ write: this.write
98
+ });
99
+ };
100
+ handleInspect = async (restArgs) => {
101
+ const { target, optionArgs } = this.optionsService.readTarget("inspect", restArgs);
102
+ const options = this.optionsService.readJsonOnlyOptions(optionArgs);
103
+ await new InspectCommand().run({
104
+ appDirectory: target,
105
+ json: options.json,
106
+ write: this.write
107
+ });
108
+ };
109
+ handleRun = async (restArgs) => {
110
+ const { target, optionArgs } = this.optionsService.readTarget("run", restArgs);
111
+ const options = this.optionsService.readRuntimeOptions(optionArgs);
112
+ await new RunCommand().run({
113
+ appReference: target,
114
+ host: options.host,
115
+ port: options.port,
116
+ json: options.json,
117
+ documentGrantMap: options.documentGrantMap,
118
+ write: this.write
119
+ });
120
+ };
121
+ handleDev = async (restArgs) => {
122
+ const { target, optionArgs } = this.optionsService.readTarget("dev", restArgs);
123
+ const options = this.optionsService.readRuntimeOptions(optionArgs);
124
+ await new DevCommand().run({
125
+ appReference: target,
126
+ host: options.host,
127
+ port: options.port,
128
+ json: options.json,
129
+ documentGrantMap: options.documentGrantMap,
130
+ write: this.write
131
+ });
132
+ };
133
+ handlePack = async (restArgs) => {
134
+ const { target, optionArgs } = this.optionsService.readTarget("pack", restArgs);
135
+ const options = this.optionsService.readPackOptions(optionArgs);
136
+ await new PackCommand().run({
137
+ appDirectory: target,
138
+ outputPath: options.outputPath,
139
+ json: options.json,
140
+ write: this.write
141
+ });
142
+ };
143
+ handlePublish = async (restArgs) => {
144
+ const { target, optionArgs } = this.optionsService.readTarget("publish", restArgs);
145
+ const options = this.optionsService.readPublishOptions(optionArgs);
146
+ await new PublishCommand().run({
147
+ appDirectory: target,
148
+ metadataPath: options.metadataPath,
149
+ apiBaseUrl: options.apiBaseUrl,
150
+ token: options.token,
151
+ json: options.json,
152
+ write: this.write
153
+ });
154
+ };
155
+ handleInstall = async (restArgs) => {
156
+ const { target, optionArgs } = this.optionsService.readTarget("install", restArgs);
157
+ const options = this.optionsService.readInstallOptions(optionArgs);
158
+ await new InstallCommand().run({
159
+ appSource: target,
160
+ registryUrl: options.registryUrl,
161
+ json: options.json,
162
+ write: this.write
163
+ });
164
+ };
165
+ handleUpdate = async (restArgs) => {
166
+ const { target, optionArgs } = this.optionsService.readTarget("update", restArgs);
167
+ const options = this.optionsService.readUpdateOptions(optionArgs);
168
+ await new UpdateCommand().run({
169
+ appId: target,
170
+ version: options.version,
171
+ registryUrl: options.registryUrl,
172
+ json: options.json,
173
+ write: this.write
174
+ });
175
+ };
176
+ handleUninstall = async (restArgs) => {
177
+ const { target, optionArgs } = this.optionsService.readTarget("uninstall", restArgs);
178
+ const options = this.optionsService.readUninstallOptions(optionArgs);
179
+ await new UninstallCommand().run({
180
+ appId: target,
181
+ purgeData: options.purgeData,
182
+ json: options.json,
183
+ write: this.write
184
+ });
185
+ };
186
+ handleList = async (restArgs) => {
187
+ const options = this.optionsService.readJsonOnlyOptions(restArgs);
188
+ await new ListCommand().run({
189
+ json: options.json,
190
+ write: this.write
191
+ });
192
+ };
193
+ handleInfo = async (restArgs) => {
194
+ const { target, optionArgs } = this.optionsService.readTarget("info", restArgs);
195
+ const options = this.optionsService.readJsonOnlyOptions(optionArgs);
196
+ await new InfoCommand().run({
197
+ appId: target,
198
+ json: options.json,
199
+ write: this.write
200
+ });
201
+ };
202
+ handleRegistry = async (restArgs) => {
203
+ const [actionOrUrl, ...optionArgs] = restArgs;
204
+ if (!actionOrUrl || actionOrUrl === "get") {
205
+ const options = this.optionsService.readJsonOnlyOptions(optionArgs);
206
+ await new RegistryCommand().run({
207
+ action: "get",
208
+ json: options.json,
209
+ write: this.write
210
+ });
211
+ return;
212
+ }
213
+ if (actionOrUrl === "--json") {
214
+ const options = this.optionsService.readJsonOnlyOptions([actionOrUrl, ...optionArgs]);
215
+ await new RegistryCommand().run({
216
+ action: "get",
217
+ json: options.json,
218
+ write: this.write
219
+ });
220
+ return;
221
+ }
222
+ if (actionOrUrl === "set") {
223
+ const { target, optionArgs: actionOptionArgs } = this.optionsService.readTarget("registry set", optionArgs);
224
+ const options = this.optionsService.readJsonOnlyOptions(actionOptionArgs);
225
+ await new RegistryCommand().run({
226
+ action: "set",
227
+ registryUrl: target,
228
+ json: options.json,
229
+ write: this.write
230
+ });
231
+ return;
232
+ }
233
+ if (actionOrUrl === "reset") {
234
+ const options = this.optionsService.readJsonOnlyOptions(optionArgs);
235
+ await new RegistryCommand().run({
236
+ action: "reset",
237
+ json: options.json,
238
+ write: this.write
239
+ });
240
+ return;
241
+ }
242
+ throw new Error(`未知 registry 子命令:${actionOrUrl}`);
243
+ };
244
+ handlePermissions = async (restArgs) => {
245
+ const { target, optionArgs } = this.optionsService.readTarget("permissions", restArgs);
246
+ const options = this.optionsService.readJsonOnlyOptions(optionArgs);
247
+ await new PermissionsCommand().run({
248
+ appId: target,
249
+ json: options.json,
250
+ write: this.write
251
+ });
252
+ };
253
+ handleGrant = async (restArgs) => {
254
+ const { target, optionArgs } = this.optionsService.readTarget("grant", restArgs);
255
+ const options = this.optionsService.readGrantOptions(optionArgs);
256
+ await new GrantCommand().run({
257
+ appId: target,
258
+ documentGrantMap: options.documentGrantMap,
259
+ json: options.json,
260
+ write: this.write
261
+ });
262
+ };
263
+ handleRevoke = async (restArgs) => {
264
+ const { target, optionArgs } = this.optionsService.readTarget("revoke", restArgs);
265
+ const options = this.optionsService.readRevokeOptions(optionArgs);
266
+ await new RevokeCommand().run({
267
+ appId: target,
268
+ documentScopeIds: options.documentScopeIds,
269
+ json: options.json,
270
+ write: this.write
271
+ });
272
+ };
273
+ writeUsage = () => {
274
+ this.write("Usage: napp create <app-dir> [--json]\n");
275
+ this.write(" napp inspect <app-dir> [--json]\n");
276
+ this.write(" napp <run|dev> <app-dir|app-id> [--host 127.0.0.1] [--port 3100] [--json] [--document scope=/path]\n");
277
+ this.write(" napp pack <app-dir> [--out bundle.napp] [--json]\n");
278
+ this.write(" napp publish <app-dir> [--meta marketplace.json] [--api-base <url>] [--token <token>] [--json]\n");
279
+ this.write(" napp install <app-dir|bundle.napp|app-id[@version]> [--registry <url>] [--json]\n");
280
+ this.write(" napp update <app-id> [--version <version>] [--registry <url>] [--json]\n");
281
+ this.write(" napp uninstall <app-id> [--purge-data] [--json]\n");
282
+ this.write(" napp list [--json]\n");
283
+ this.write(" napp info <app-id> [--json]\n");
284
+ this.write(" napp registry [get] [--json]\n");
285
+ this.write(" napp registry set <url> [--json]\n");
286
+ this.write(" napp registry reset [--json]\n");
287
+ this.write(" napp permissions <app-id> [--json]\n");
288
+ this.write(" napp grant <app-id> --document scope=/path [--json]\n");
289
+ this.write(" napp revoke <app-id> --document scope [--json]\n");
290
+ this.write(" napp --help\n");
291
+ this.write(" napp --version\n");
292
+ };
293
+ write = (text) => {
294
+ process.stdout.write(text);
295
+ };
296
+ };
297
+ //#endregion
298
+ export { AppRuntimeCliService };