@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.
Files changed (35) hide show
  1. package/README.md +39 -5
  2. package/dist/bundle/app-bundle.service.d.ts +7 -2
  3. package/dist/bundle/app-bundle.service.js +77 -16
  4. package/dist/bundle/app-bundle.types.d.ts +5 -1
  5. package/dist/cli/app-runtime-cli.service.d.ts +1 -0
  6. package/dist/cli/app-runtime-cli.service.js +23 -5
  7. package/dist/cli/app-runtime-options.service.d.ts +4 -0
  8. package/dist/cli/app-runtime-options.service.js +22 -4
  9. package/dist/commands/pack.controller.d.ts +1 -0
  10. package/dist/commands/pack.controller.js +4 -3
  11. package/dist/commands/publish.controller.d.ts +1 -0
  12. package/dist/commands/publish.controller.js +4 -3
  13. package/dist/commands/validate-publish.controller.d.ts +16 -0
  14. package/dist/commands/validate-publish.controller.js +33 -0
  15. package/dist/index.d.ts +7 -4
  16. package/dist/index.js +6 -3
  17. package/dist/install/app-installation.service.d.ts +4 -1
  18. package/dist/install/app-installation.service.js +21 -3
  19. package/dist/install/app-installation.types.d.ts +4 -0
  20. package/dist/package.js +1 -1
  21. package/dist/publish/app-publish-validation.service.d.ts +40 -0
  22. package/dist/publish/app-publish-validation.service.js +80 -0
  23. package/dist/publish/app-publish.service.d.ts +2 -0
  24. package/dist/publish/app-publish.service.js +9 -3
  25. package/dist/publish/app-publish.types.d.ts +4 -1
  26. package/dist/registry/app-registry.service.d.ts +1 -0
  27. package/dist/registry/app-registry.service.js +2 -1
  28. package/dist/registry/app-registry.types.d.ts +2 -0
  29. package/dist/registry/app-remote-registry-client.service.js +5 -1
  30. package/dist/registry/app-remote-registry.types.d.ts +5 -0
  31. package/dist/scaffold/app-scaffold.service.d.ts +4 -2
  32. package/dist/scaffold/app-scaffold.service.js +14 -1
  33. package/dist/scaffold/app-ts-http-lite-scaffold-template.service.d.ts +18 -0
  34. package/dist/scaffold/app-ts-http-lite-scaffold-template.service.js +267 -0
  35. 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` bundle
14
- - `napp publish <app-dir>`:把应用目录发布到官方 apps registry
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 collectAppFiles;
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 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);
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 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));
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: outputPath,
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 metadata = await this.readJsonFile(path.join(targetDirectory, ".napp", "bundle.json"), "bundle metadata");
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
- 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
+ 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 appFiles;
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
- buildMetadata = (appId, name, version) => {
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 };
@@ -14,6 +14,7 @@ declare class AppRuntimeCliService {
14
14
  private handleDev;
15
15
  private handlePack;
16
16
  private handlePublish;
17
+ private handleValidatePublish;
17
18
  private handleInstall;
18
19
  private handleUpdate;
19
20
  private handleUninstall;
@@ -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 { AppRuntimeToolchainService } from "../runtime/app-runtime-toolchain.service.js";
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 = { json: false };
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 = { json: false };
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 格式。");
@@ -7,6 +7,7 @@ declare class PackCommand {
7
7
  run: (params: {
8
8
  appDirectory: string;
9
9
  outputPath?: string;
10
+ mode: "source" | "bundle";
10
11
  json: boolean;
11
12
  write: (text: string) => void;
12
13
  }) => Promise<void>;
@@ -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
  };
@@ -9,6 +9,7 @@ declare class PublishCommand {
9
9
  metadataPath?: string;
10
10
  apiBaseUrl?: string;
11
11
  token?: string;
12
+ mode: "source" | "bundle";
12
13
  json: boolean;
13
14
  write: (text: string) => void;
14
15
  }) => Promise<void>;
@@ -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(`Bundle: ${result.bundle.path}\n`);
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 };