@nextclaw/app-runtime 0.6.0 → 0.7.1-beta.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 (30) hide show
  1. package/README.md +20 -3
  2. package/dist/bundle/app-bundle.service.d.ts +7 -2
  3. package/dist/bundle/app-bundle.service.js +65 -10
  4. package/dist/bundle/app-bundle.types.d.ts +3 -1
  5. package/dist/cli/app-runtime-cli.service.js +8 -5
  6. package/dist/cli/app-runtime-options.service.d.ts +4 -0
  7. package/dist/cli/app-runtime-options.service.js +20 -2
  8. package/dist/commands/pack.controller.d.ts +1 -0
  9. package/dist/commands/pack.controller.js +4 -3
  10. package/dist/commands/publish.controller.d.ts +1 -0
  11. package/dist/commands/publish.controller.js +4 -3
  12. package/dist/commands/validate-publish.controller.d.ts +1 -0
  13. package/dist/commands/validate-publish.controller.js +4 -2
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +2 -2
  16. package/dist/install/app-installation.service.d.ts +4 -1
  17. package/dist/install/app-installation.service.js +21 -3
  18. package/dist/install/app-installation.types.d.ts +4 -0
  19. package/dist/package.js +1 -1
  20. package/dist/publish/app-publish-validation.service.d.ts +3 -0
  21. package/dist/publish/app-publish-validation.service.js +7 -3
  22. package/dist/publish/app-publish.service.d.ts +2 -0
  23. package/dist/publish/app-publish.service.js +9 -3
  24. package/dist/publish/app-publish.types.d.ts +4 -1
  25. package/dist/registry/app-registry.service.d.ts +1 -0
  26. package/dist/registry/app-registry.service.js +2 -1
  27. package/dist/registry/app-registry.types.d.ts +2 -0
  28. package/dist/registry/app-remote-registry-client.service.js +5 -1
  29. package/dist/registry/app-remote-registry.types.d.ts +5 -0
  30. package/package.json +1 -1
package/README.md CHANGED
@@ -10,9 +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
13
+ - `napp pack <app-dir>`:把应用目录打成 `.napp` 分发包,默认使用轻量 `source` 模式
14
14
  - `napp validate-publish <app-dir>`:本地做发布前校验并输出体积/包内容 warning
15
- - `napp publish <app-dir>`:把应用目录发布到官方 apps registry
15
+ - `napp publish <app-dir>`:把应用目录发布到官方 apps registry,默认发布轻量 `source` 分发包
16
16
  - `napp install <app-dir|bundle.napp|app-id[@version]>`:从本地或 registry 安装应用
17
17
  - `napp update <app-id>`:更新已安装应用
18
18
  - `napp uninstall <app-id>`:卸载已安装应用
@@ -59,7 +59,7 @@ assets/
59
59
  - WASI HTTP 业务 API:`/api/*`
60
60
  - 权限词汇:`documentAccess`、`allowedDomains`、`storage`、`capabilities`
61
61
  - 当前 Wasm 执行底座:Node 原生 `WebAssembly` 与 Wasmtime `serve`
62
- - 分发包形态:`.napp`(底层为 zip
62
+ - 分发包形态:`.napp`(底层为 zip,支持 `source` / `bundle` 双模式)
63
63
  - 安装目录:`~/.nextclaw/apps/packages/<app-id>/<version>/`
64
64
  - 用户数据目录:`~/.nextclaw/apps/data/<app-id>/`
65
65
  - 本地 registry:`~/.nextclaw/apps/registry.json`
@@ -176,6 +176,22 @@ assets/
176
176
  checksums.json
177
177
  ```
178
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
+
179
195
  ## Registry Metadata 结构
180
196
 
181
197
  registry 按 npm 风格使用一个 base URL,再按 app id 拉取 metadata 文档。metadata 的最小结构如下:
@@ -196,6 +212,7 @@ registry 按 npm 风格使用一个 base URL,再按 app id 拉取 metadata 文
196
212
  "name": "NextClaw Official"
197
213
  },
198
214
  "dist": {
215
+ "kind": "source",
199
216
  "bundle": "./-/hello-notes-0.2.0.napp",
200
217
  "sha256": "<sha256>"
201
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, filePaths } = await this.collectAppFiles(bundle);
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,11 +27,11 @@ 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,
34
+ bundlePath: resolvedOutputPath,
33
35
  metadata,
34
36
  sizeBytes: archiveBytes.byteLength,
35
37
  filePaths
@@ -51,7 +53,8 @@ var AppBundleService = class {
51
53
  await mkdir(path.dirname(targetPath), { recursive: true });
52
54
  await writeFile(targetPath, Buffer.from(archive[entryName]));
53
55
  }
54
- 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);
55
58
  const checksums = await this.readJsonFile(path.join(targetDirectory, ".napp", "checksums.json"), "bundle checksums");
56
59
  await this.verifyChecksums(targetDirectory, checksums);
57
60
  await this.manifestService.load(targetDirectory);
@@ -61,7 +64,7 @@ var AppBundleService = class {
61
64
  checksums
62
65
  };
63
66
  };
64
- collectAppFiles = async (bundle) => {
67
+ collectRuntimeFiles = async (bundle) => {
65
68
  const appDirectory = bundle.appDirectory;
66
69
  const filePaths = new Set([path.relative(appDirectory, bundle.manifestPath), path.relative(appDirectory, bundle.mainEntryPath)]);
67
70
  await this.collectDirectoryPaths(bundle.uiDirectoryPath, appDirectory, filePaths);
@@ -75,6 +78,23 @@ var AppBundleService = class {
75
78
  filePaths: sortedPaths
76
79
  };
77
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
+ };
97
+ };
78
98
  collectDirectoryPaths = async (directoryPath, appDirectory, filePaths) => {
79
99
  try {
80
100
  const entries = await readdir(directoryPath, { withFileTypes: true });
@@ -91,9 +111,32 @@ var AppBundleService = class {
91
111
  return;
92
112
  }
93
113
  };
94
- 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) => {
95
137
  return {
96
138
  bundleFormatVersion: 1,
139
+ distributionMode,
97
140
  appId,
98
141
  name,
99
142
  version,
@@ -101,6 +144,17 @@ var AppBundleService = class {
101
144
  checksumsFile: ".napp/checksums.json"
102
145
  };
103
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
+ };
104
158
  buildChecksums = (files) => {
105
159
  const entries = Object.entries(files).sort(([left], [right]) => left.localeCompare(right));
106
160
  return {
@@ -135,5 +189,6 @@ var AppBundleService = class {
135
189
  }
136
190
  };
137
191
  };
192
+ const SOURCE_WASM_PLACEHOLDER_BYTES = Uint8Array.from(Buffer.from("AGFzbQEAAAABBwFgAn9/AX8DAgEABxMBD3N1bW1hcml6ZV9ub3RlcwAACg0BCwAgACABakHIAWoL", "base64"));
138
193
  //#endregion
139
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;
@@ -23,4 +25,4 @@ type AppBundleExtractResult = {
23
25
  checksums: AppBundleChecksums;
24
26
  };
25
27
  //#endregion
26
- 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";
@@ -15,8 +17,6 @@ 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
19
  import { ValidatePublishCommand } from "../commands/validate-publish.controller.js";
18
- import { AppRuntimeToolchainService } from "../runtime/app-runtime-toolchain.service.js";
19
- import { AppBuildService } from "../runtime/app-build.service.js";
20
20
  import { AppRuntimeOptionsService } from "./app-runtime-options.service.js";
21
21
  //#region src/cli/app-runtime-cli.service.ts
22
22
  var AppRuntimeCliService = class {
@@ -191,6 +191,7 @@ var AppRuntimeCliService = class {
191
191
  await new PackCommand().run({
192
192
  appDirectory: target,
193
193
  outputPath: options.outputPath,
194
+ mode: options.mode,
194
195
  json: options.json,
195
196
  write: this.write
196
197
  });
@@ -203,6 +204,7 @@ var AppRuntimeCliService = class {
203
204
  metadataPath: options.metadataPath,
204
205
  apiBaseUrl: options.apiBaseUrl,
205
206
  token: options.token,
207
+ mode: options.mode,
206
208
  json: options.json,
207
209
  write: this.write
208
210
  });
@@ -213,6 +215,7 @@ var AppRuntimeCliService = class {
213
215
  await new ValidatePublishCommand().run({
214
216
  appDirectory: target,
215
217
  metadataPath: options.metadataPath,
218
+ mode: options.mode,
216
219
  json: options.json,
217
220
  write: this.write
218
221
  });
@@ -341,9 +344,9 @@ var AppRuntimeCliService = class {
341
344
  this.write(" napp build <app-dir> [--install] [--json]\n");
342
345
  this.write(" napp doctor [--json]\n");
343
346
  this.write(" napp <run|dev> <app-dir|app-id> [--host 127.0.0.1] [--port 3100] [--data /path] [--json] [--document scope=/path]\n");
344
- this.write(" napp pack <app-dir> [--out bundle.napp] [--json]\n");
345
- this.write(" napp publish <app-dir> [--meta marketplace.json] [--api-base <url>] [--token <token>] [--json]\n");
346
- this.write(" napp validate-publish <app-dir> [--meta marketplace.json] [--json]\n");
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");
347
350
  this.write(" napp install <app-dir|bundle.napp|app-id[@version]> [--registry <url>] [--json]\n");
348
351
  this.write(" napp update <app-id> [--version <version>] [--registry <url>] [--json]\n");
349
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;
@@ -35,7 +35,10 @@ var AppRuntimeOptionsService = class {
35
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
  };
@@ -7,6 +7,7 @@ declare class ValidatePublishCommand {
7
7
  run: (params: {
8
8
  appDirectory: string;
9
9
  metadataPath?: string;
10
+ mode: "source" | "bundle";
10
11
  json: boolean;
11
12
  write: (text: string) => void;
12
13
  }) => Promise<void>;
@@ -5,10 +5,11 @@ var ValidatePublishCommand = class {
5
5
  this.validationService = validationService;
6
6
  }
7
7
  run = async (params) => {
8
- const { appDirectory, metadataPath, json, write } = params;
8
+ const { appDirectory, metadataPath, mode, json, write } = params;
9
9
  const result = await this.validationService.validate({
10
10
  appDirectory,
11
- metadataPath
11
+ metadataPath,
12
+ mode
12
13
  });
13
14
  if (json) {
14
15
  write(`${JSON.stringify({
@@ -18,6 +19,7 @@ var ValidatePublishCommand = class {
18
19
  return;
19
20
  }
20
21
  write(`Publish validation ok for ${result.appId}@${result.version}\n`);
22
+ write(`Distribution mode: ${result.distributionMode}\n`);
21
23
  write(`Main kind: ${result.mainKind}\n`);
22
24
  write(`Main: ${result.mainEntryPath}\n`);
23
25
  write(`Metadata: ${result.metadataPath}\n`);
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";
@@ -22,6 +22,8 @@ import { AppInstallSourceKind, AppRegistry, AppRegistryAppRecord, AppRegistryIns
22
22
  import { AppRegistryService } from "./registry/app-registry.service.js";
23
23
  import { AppGrantService } from "./permissions/app-grant.service.js";
24
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";
25
27
  import { AppRegistryConfigService } from "./registry/app-registry-config.service.js";
26
28
  import { AppRemoteRegistryClientService } from "./registry/app-remote-registry-client.service.js";
27
29
  import { AppInfoResult, AppInstallResult, AppLaunchResolution, AppUninstallResult, AppUpdateResult, InstalledAppListItem } from "./install/app-installation.types.js";
@@ -45,7 +47,5 @@ import { AppPublishValidationResult, AppPublishValidationService, AppPublishVali
45
47
  import { ValidatePublishCommand } from "./commands/validate-publish.controller.js";
46
48
  import { WasmtimeWasiHttpComponentHandle, WasmtimeWasiHttpComponentService, WasmtimeWasiHttpComponentStartOptions } from "./runtime/wasmtime-wasi-http-component.service.js";
47
49
  import { AppHostHandle, AppHostService, AppHostStartOptions } from "./host/app-host.service.js";
48
- import { AppRuntimeCommandResult, AppRuntimeDoctorResult, AppRuntimeToolStatus, AppRuntimeToolchainService } from "./runtime/app-runtime-toolchain.service.js";
49
- import { AppBuildResult, AppBuildService } from "./runtime/app-build.service.js";
50
50
  import { UiServerService } from "./ui/ui-server.service.js";
51
- export { AppBuildResult, AppBuildService, AppBundleChecksums, AppBundleExtractResult, AppBundleMetadata, AppBundlePackResult, AppBundleService, AppCoreWasmMainManifest, AppDocumentAccessMode, AppDocumentAccessScope, AppDocumentGrantMap, AppDocumentGrantMutationResult, AppDocumentGrantState, AppGrantService, AppHomeService, AppHostHandle, AppHostService, AppHostStartOptions, AppInfoResult, AppInstallResult, AppInstallSourceKind, AppInstallationService, AppInstalledPermissionState, AppInstanceService, AppLaunchResolution, AppMainManifest, AppManifest, AppManifestBundle, AppManifestService, AppManifestSummary, AppMarketplaceClientService, AppMarketplaceMetadata, AppMarketplaceMetadataService, AppPermissionSummary, AppPermissions, AppPermissionsService, AppPublishFile, AppPublishPayload, AppPublishResult, AppPublishService, AppPublishValidationResult, AppPublishValidationService, AppPublishValidationWarning, AppPublishValidationWarningCode, AppPublisher, AppRegistry, AppRegistryAppRecord, AppRegistryConfig, AppRegistryConfigService, AppRegistryConfigSnapshot, AppRegistryInstalledVersion, AppRegistryService, AppRemoteRegistryClientService, AppRemoteRegistryDocument, AppRemoteRegistryResolution, AppRemoteRegistryVersion, AppRunResult, AppRuntimeCliService, AppRuntimeCommandResult, AppRuntimeDoctorResult, AppRuntimeOptionsService, AppRuntimeToolStatus, AppRuntimeToolchainService, AppScaffoldFile, AppScaffoldResult, AppScaffoldService, AppScaffoldTemplate, AppTsHttpLiteScaffoldTemplateService, AppTsHttpScaffoldTemplateService, AppUiManifest, AppUninstallResult, AppUpdateResult, AppWasiHttpComponentMainManifest, BuildCliOptions, CreateCliOptions, CreateCommand, DEFAULT_APP_MARKETPLACE_API_BASE, DEFAULT_APP_REGISTRY_URL, GrantCliOptions, GrantCommand, HostBridgeServer, InfoCommand, InstallCliOptions, InstallCommand, InstalledAppListItem, JsonOnlyCliOptions, ListCommand, MainRunRequest, MainRunResult, MainRunnerService, PackCliOptions, PackCommand, PermissionsCommand, PlatformAuthStateService, PlatformPublishAuthState, PublishCliOptions, PublishCommand, RegistryCommand, ResolvedDocumentGrant, ResolvedPermissions, RevokeCliOptions, RevokeCommand, RuntimeCliOptions, UiServerService, UninstallCliOptions, UninstallCommand, UpdateCliOptions, UpdateCommand, ValidatePublishCommand, WasmDocumentSummaryInput, WasmMainRunnerService, WasmSidecarClientService, WasmtimeWasiHttpComponentHandle, WasmtimeWasiHttpComponentService, WasmtimeWasiHttpComponentStartOptions };
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 };
package/dist/index.js CHANGED
@@ -13,6 +13,8 @@ import { WasmSidecarClientService } from "./sidecar/wasm-sidecar-client.service.
13
13
  import { WasmMainRunnerService } from "./runtime/wasm-main-runner.service.js";
14
14
  import { AppInstanceService } from "./host/app-instance.service.js";
15
15
  import { AppHomeService } from "./paths/app-home.service.js";
16
+ import { AppRuntimeToolchainService } from "./runtime/app-runtime-toolchain.service.js";
17
+ import { AppBuildService } from "./runtime/app-build.service.js";
16
18
  import { DEFAULT_APP_REGISTRY_URL } from "./registry/app-remote-registry.types.js";
17
19
  import { AppRegistryConfigService } from "./registry/app-registry-config.service.js";
18
20
  import { AppRemoteRegistryClientService } from "./registry/app-remote-registry-client.service.js";
@@ -38,8 +40,6 @@ import { UninstallCommand } from "./commands/uninstall.controller.js";
38
40
  import { UpdateCommand } from "./commands/update.controller.js";
39
41
  import { AppPublishValidationService } from "./publish/app-publish-validation.service.js";
40
42
  import { ValidatePublishCommand } from "./commands/validate-publish.controller.js";
41
- import { AppRuntimeToolchainService } from "./runtime/app-runtime-toolchain.service.js";
42
- import { AppBuildService } from "./runtime/app-build.service.js";
43
43
  import { AppRuntimeOptionsService } from "./cli/app-runtime-options.service.js";
44
44
  import { AppRuntimeCliService } from "./cli/app-runtime-cli.service.js";
45
45
  export { AppBuildService, AppBundleService, AppGrantService, AppHomeService, AppHostService, AppInstallationService, AppInstanceService, AppManifestService, AppMarketplaceClientService, AppMarketplaceMetadataService, AppPermissionsService, AppPublishService, AppPublishValidationService, AppRegistryConfigService, AppRegistryService, AppRemoteRegistryClientService, AppRuntimeCliService, AppRuntimeOptionsService, AppRuntimeToolchainService, AppScaffoldService, AppTsHttpLiteScaffoldTemplateService, AppTsHttpScaffoldTemplateService, CreateCommand, DEFAULT_APP_MARKETPLACE_API_BASE, DEFAULT_APP_REGISTRY_URL, GrantCommand, HostBridgeServer, InfoCommand, InstallCommand, ListCommand, MainRunnerService, PackCommand, PermissionsCommand, PlatformAuthStateService, PublishCommand, RegistryCommand, RevokeCommand, UiServerService, UninstallCommand, UpdateCommand, ValidatePublishCommand, WasmMainRunnerService, WasmSidecarClientService, WasmtimeWasiHttpComponentService };
@@ -3,6 +3,7 @@ import { AppBundleService } from "../bundle/app-bundle.service.js";
3
3
  import { AppDocumentGrantMap } from "../permissions/app-permissions.types.js";
4
4
  import { AppHomeService } from "../paths/app-home.service.js";
5
5
  import { AppRegistryService } from "../registry/app-registry.service.js";
6
+ import { AppBuildService } from "../runtime/app-build.service.js";
6
7
  import { AppRegistryConfigService } from "../registry/app-registry-config.service.js";
7
8
  import { AppRemoteRegistryClientService } from "../registry/app-remote-registry-client.service.js";
8
9
  import { AppInfoResult, AppInstallResult, AppLaunchResolution, AppUninstallResult, AppUpdateResult, InstalledAppListItem } from "./app-installation.types.js";
@@ -12,10 +13,11 @@ declare class AppInstallationService {
12
13
  private readonly appHomeService;
13
14
  private readonly bundleService;
14
15
  private readonly manifestService;
16
+ private readonly buildService;
15
17
  private readonly registryService;
16
18
  private readonly registryConfigService;
17
19
  private readonly remoteRegistryClient;
18
- constructor(appHomeService?: AppHomeService, bundleService?: AppBundleService, manifestService?: AppManifestService, registryService?: AppRegistryService, registryConfigService?: AppRegistryConfigService, remoteRegistryClient?: AppRemoteRegistryClientService);
20
+ constructor(appHomeService?: AppHomeService, bundleService?: AppBundleService, manifestService?: AppManifestService, buildService?: AppBuildService, registryService?: AppRegistryService, registryConfigService?: AppRegistryConfigService, remoteRegistryClient?: AppRemoteRegistryClientService);
19
21
  install: (appSource: string, options?: {
20
22
  registryUrl?: string;
21
23
  }) => Promise<AppInstallResult>;
@@ -32,6 +34,7 @@ declare class AppInstallationService {
32
34
  private detectLocalSourceType;
33
35
  private parseRegistrySpec;
34
36
  private looksLikePath;
37
+ private materializeDistribution;
35
38
  }
36
39
  //#endregion
37
40
  export { AppInstallationService };
@@ -1,6 +1,7 @@
1
1
  import { AppManifestService } from "../manifest/app-manifest.service.js";
2
2
  import { AppBundleService } from "../bundle/app-bundle.service.js";
3
3
  import { AppHomeService } from "../paths/app-home.service.js";
4
+ import { AppBuildService } from "../runtime/app-build.service.js";
4
5
  import { AppRegistryConfigService } from "../registry/app-registry-config.service.js";
5
6
  import { AppRemoteRegistryClientService } from "../registry/app-remote-registry-client.service.js";
6
7
  import { AppRegistryService } from "../registry/app-registry.service.js";
@@ -8,10 +9,11 @@ import { access, cp, mkdir, rm } from "node:fs/promises";
8
9
  import path from "node:path";
9
10
  //#region src/install/app-installation.service.ts
10
11
  var AppInstallationService = class {
11
- constructor(appHomeService = new AppHomeService(), bundleService = new AppBundleService(), manifestService = new AppManifestService(), registryService = new AppRegistryService(appHomeService), registryConfigService = new AppRegistryConfigService(appHomeService), remoteRegistryClient = new AppRemoteRegistryClientService(new AppRegistryConfigService(appHomeService))) {
12
+ constructor(appHomeService = new AppHomeService(), bundleService = new AppBundleService(), manifestService = new AppManifestService(), buildService = new AppBuildService(), registryService = new AppRegistryService(appHomeService), registryConfigService = new AppRegistryConfigService(appHomeService), remoteRegistryClient = new AppRemoteRegistryClientService(new AppRegistryConfigService(appHomeService))) {
12
13
  this.appHomeService = appHomeService;
13
14
  this.bundleService = bundleService;
14
15
  this.manifestService = manifestService;
16
+ this.buildService = buildService;
15
17
  this.registryService = registryService;
16
18
  this.registryConfigService = registryConfigService;
17
19
  this.remoteRegistryClient = remoteRegistryClient;
@@ -28,10 +30,14 @@ var AppInstallationService = class {
28
30
  targetDirectory: tempDirectory
29
31
  })).bundlePath;
30
32
  const extractedDirectory = path.join(tempDirectory, "bundle");
31
- await this.bundleService.extractBundle({
33
+ const extractedMetadata = await this.bundleService.extractBundle({
32
34
  bundlePath,
33
35
  targetDirectory: extractedDirectory
34
36
  });
37
+ await this.materializeDistribution({
38
+ appDirectory: extractedDirectory,
39
+ distributionMode: extractedMetadata.metadata.distributionMode
40
+ });
35
41
  const manifestBundle = await this.manifestService.load(extractedDirectory);
36
42
  const installDirectory = this.appHomeService.getInstallDirectory(manifestBundle.manifest.id, manifestBundle.manifest.version);
37
43
  if (source.kind === "registry" && manifestBundle.manifest.id !== source.registryResolution.appId) throw new Error(`bundle manifest.appId 与 registry 请求不一致:期望 ${source.registryResolution.appId},实际 ${manifestBundle.manifest.id}`);
@@ -51,6 +57,7 @@ var AppInstallationService = class {
51
57
  installDirectory,
52
58
  dataDirectory,
53
59
  sourceKind: source.kind,
60
+ distributionMode: source.kind === "registry" ? source.registryResolution.distributionMode : extractedMetadata.metadata.distributionMode,
54
61
  sourceRef: source.sourceRef,
55
62
  installedAt: (/* @__PURE__ */ new Date()).toISOString(),
56
63
  permissions: manifestBundle.manifest.permissions ?? {},
@@ -67,6 +74,7 @@ var AppInstallationService = class {
67
74
  dataDirectory,
68
75
  sourceKind: source.kind,
69
76
  sourceRef: source.sourceRef,
77
+ distributionMode: registryRecord.installedVersions[registryRecord.activeVersion]?.distributionMode,
70
78
  permissions: registryRecord.installedVersions[registryRecord.activeVersion]?.permissions ?? {},
71
79
  registryUrl: registryRecord.installedVersions[registryRecord.activeVersion]?.registryUrl,
72
80
  bundleUrl: registryRecord.installedVersions[registryRecord.activeVersion]?.bundleUrl,
@@ -138,7 +146,8 @@ var AppInstallationService = class {
138
146
  appId: appRecord.appId,
139
147
  name: appRecord.name,
140
148
  activeVersion: appRecord.activeVersion,
141
- sourceKind: appRecord.installedVersions[appRecord.activeVersion]?.sourceKind ?? "directory"
149
+ sourceKind: appRecord.installedVersions[appRecord.activeVersion]?.sourceKind ?? "directory",
150
+ distributionMode: appRecord.installedVersions[appRecord.activeVersion]?.distributionMode
142
151
  }));
143
152
  };
144
153
  info = async (appId) => {
@@ -155,6 +164,7 @@ var AppInstallationService = class {
155
164
  version: versionRecord.version,
156
165
  installDirectory: versionRecord.installDirectory,
157
166
  sourceKind: versionRecord.sourceKind,
167
+ distributionMode: versionRecord.distributionMode,
158
168
  sourceRef: versionRecord.sourceRef,
159
169
  installedAt: versionRecord.installedAt,
160
170
  permissions: versionRecord.permissions,
@@ -251,6 +261,14 @@ var AppInstallationService = class {
251
261
  looksLikePath = (appSource) => {
252
262
  return appSource.startsWith(".") || appSource.startsWith("/") || appSource.includes(path.sep);
253
263
  };
264
+ materializeDistribution = async (params) => {
265
+ if (params.distributionMode !== "source") return;
266
+ if ((await this.manifestService.load(params.appDirectory)).manifest.main.kind !== "wasi-http-component") return;
267
+ await this.buildService.build({
268
+ appDirectory: params.appDirectory,
269
+ install: true
270
+ });
271
+ };
254
272
  };
255
273
  //#endregion
256
274
  export { AppInstallationService };
@@ -1,4 +1,5 @@
1
1
  import { AppPermissions } from "../manifest/app-manifest.types.js";
2
+ import { AppDistributionMode } from "../bundle/app-bundle.types.js";
2
3
  import { AppDocumentGrantMap } from "../permissions/app-permissions.types.js";
3
4
  import { AppPublisher } from "../registry/app-remote-registry.types.js";
4
5
  import { AppInstallSourceKind } from "../registry/app-registry.types.js";
@@ -11,6 +12,7 @@ type AppInstallResult = {
11
12
  installDirectory: string;
12
13
  dataDirectory: string;
13
14
  sourceKind: AppInstallSourceKind;
15
+ distributionMode?: AppDistributionMode;
14
16
  sourceRef: string;
15
17
  permissions: AppPermissions;
16
18
  registryUrl?: string;
@@ -28,6 +30,7 @@ type AppInfoResult = {
28
30
  version: string;
29
31
  installDirectory: string;
30
32
  sourceKind: AppInstallSourceKind;
33
+ distributionMode?: AppDistributionMode;
31
34
  sourceRef: string;
32
35
  installedAt: string;
33
36
  permissions: AppPermissions;
@@ -43,6 +46,7 @@ type InstalledAppListItem = {
43
46
  name: string;
44
47
  activeVersion: string;
45
48
  sourceKind: AppInstallSourceKind;
49
+ distributionMode?: AppDistributionMode;
46
50
  };
47
51
  type AppUninstallResult = {
48
52
  appId: string;
package/dist/package.js CHANGED
@@ -1,4 +1,4 @@
1
1
  //#region package.json
2
- var version = "0.6.0";
2
+ var version = "0.7.1-beta.0";
3
3
  //#endregion
4
4
  export { version };
@@ -1,4 +1,5 @@
1
1
  import { AppManifestService } from "../manifest/app-manifest.service.js";
2
+ import { AppDistributionMode } from "../bundle/app-bundle.types.js";
2
3
  import { AppBundleService } from "../bundle/app-bundle.service.js";
3
4
  import { AppMarketplaceMetadataService } from "./app-marketplace-metadata.service.js";
4
5
 
@@ -14,6 +15,7 @@ type AppPublishValidationResult = {
14
15
  metadataPath: string;
15
16
  appId: string;
16
17
  version: string;
18
+ distributionMode: AppDistributionMode;
17
19
  mainKind: string;
18
20
  mainEntryPath: string;
19
21
  mainEntrySizeBytes: number;
@@ -29,6 +31,7 @@ declare class AppPublishValidationService {
29
31
  validate: (params: {
30
32
  appDirectory: string;
31
33
  metadataPath?: string;
34
+ mode?: AppDistributionMode;
32
35
  }) => Promise<AppPublishValidationResult>;
33
36
  private buildWarnings;
34
37
  private formatBytes;
@@ -14,9 +14,11 @@ var AppPublishValidationService = class {
14
14
  this.bundleService = bundleService;
15
15
  }
16
16
  validate = async (params) => {
17
- const appDirectory = path.resolve(params.appDirectory);
17
+ const { appDirectory: inputAppDirectory, metadataPath: inputMetadataPath, mode } = params;
18
+ const appDirectory = path.resolve(inputAppDirectory);
19
+ const distributionMode = mode ?? "source";
18
20
  const bundle = await this.manifestService.load(appDirectory);
19
- const metadataPath = params.metadataPath ? path.resolve(params.metadataPath) : path.join(appDirectory, "marketplace.json");
21
+ const metadataPath = inputMetadataPath ? path.resolve(inputMetadataPath) : path.join(appDirectory, "marketplace.json");
20
22
  await this.metadataService.load({
21
23
  appDirectory,
22
24
  manifest: bundle.manifest,
@@ -26,7 +28,8 @@ var AppPublishValidationService = class {
26
28
  try {
27
29
  const packResult = await this.bundleService.packAppDirectory({
28
30
  appDirectory,
29
- outputPath: path.join(tempDirectory, `${bundle.manifest.id}-${bundle.manifest.version}.napp`)
31
+ outputPath: path.join(tempDirectory, `${bundle.manifest.id}-${bundle.manifest.version}.napp`),
32
+ mode: distributionMode
30
33
  });
31
34
  const mainEntryStats = await stat(bundle.mainEntryPath);
32
35
  const warnings = this.buildWarnings({
@@ -39,6 +42,7 @@ var AppPublishValidationService = class {
39
42
  metadataPath,
40
43
  appId: bundle.manifest.id,
41
44
  version: bundle.manifest.version,
45
+ distributionMode,
42
46
  mainKind: bundle.manifest.main.kind,
43
47
  mainEntryPath: bundle.mainEntryPath,
44
48
  mainEntrySizeBytes: mainEntryStats.size,
@@ -1,4 +1,5 @@
1
1
  import { AppManifestService } from "../manifest/app-manifest.service.js";
2
+ import { AppDistributionMode } from "../bundle/app-bundle.types.js";
2
3
  import { AppBundleService } from "../bundle/app-bundle.service.js";
3
4
  import { AppPublishResult } from "./app-publish.types.js";
4
5
  import { AppMarketplaceClientService } from "./app-marketplace-client.service.js";
@@ -18,6 +19,7 @@ declare class AppPublishService {
18
19
  metadataPath?: string;
19
20
  apiBaseUrl?: string;
20
21
  token?: string;
22
+ mode?: AppDistributionMode;
21
23
  }) => Promise<AppPublishResult>;
22
24
  private resolvePublishActor;
23
25
  private fetchCurrentPlatformUser;
@@ -18,6 +18,7 @@ var AppPublishService = class {
18
18
  }
19
19
  publish = async (params) => {
20
20
  const { appDirectory: inputAppDirectory, metadataPath, apiBaseUrl, token } = params;
21
+ const distributionMode = params.mode ?? "source";
21
22
  const appDirectory = path.resolve(inputAppDirectory);
22
23
  const manifestBundle = await this.manifestService.load(appDirectory);
23
24
  const metadata = await this.metadataService.load({
@@ -30,7 +31,10 @@ var AppPublishService = class {
30
31
  explicitToken: token,
31
32
  appId: manifestBundle.manifest.id
32
33
  });
33
- const bundle = await this.bundleService.packAppDirectory({ appDirectory });
34
+ const bundle = await this.bundleService.packAppDirectory({
35
+ appDirectory,
36
+ mode: distributionMode
37
+ });
34
38
  const bundleBytes = Buffer.from(await readFile(bundle.bundlePath));
35
39
  const bundleSha256 = createHash("sha256").update(bundleBytes).digest("hex");
36
40
  const publishFiles = await this.metadataService.collectPublishFiles({
@@ -52,6 +56,7 @@ var AppPublishService = class {
52
56
  homepage: metadata.homepage,
53
57
  featured: metadata.featured ?? false,
54
58
  publisher: actor.publisher,
59
+ distributionMode,
55
60
  manifest: manifestBundle.manifest,
56
61
  permissions: manifestBundle.manifest.permissions ?? {},
57
62
  bundleBase64: bundleBytes.toString("base64"),
@@ -67,9 +72,10 @@ var AppPublishService = class {
67
72
  apiBaseUrl,
68
73
  token: actor.token
69
74
  }),
70
- bundle: {
75
+ distribution: {
71
76
  path: bundle.bundlePath,
72
- sha256: bundleSha256
77
+ sha256: bundleSha256,
78
+ mode: distributionMode
73
79
  }
74
80
  };
75
81
  };
@@ -1,4 +1,5 @@
1
1
  import { AppManifest, AppPermissions } from "../manifest/app-manifest.types.js";
2
+ import { AppDistributionMode } from "../bundle/app-bundle.types.js";
2
3
  import { AppPublisher } from "../registry/app-remote-registry.types.js";
3
4
 
4
5
  //#region src/publish/app-publish.types.d.ts
@@ -35,6 +36,7 @@ type AppPublishPayload = {
35
36
  homepage?: string;
36
37
  featured: boolean;
37
38
  publisher: AppPublisher;
39
+ distributionMode: AppDistributionMode;
38
40
  manifest: AppManifest;
39
41
  permissions: AppPermissions;
40
42
  bundleBase64: string;
@@ -56,9 +58,10 @@ type AppPublishResult = {
56
58
  registry: string;
57
59
  };
58
60
  };
59
- bundle: {
61
+ distribution: {
60
62
  path: string;
61
63
  sha256: string;
64
+ mode: AppDistributionMode;
62
65
  };
63
66
  fileCount: number;
64
67
  };
@@ -22,6 +22,7 @@ declare class AppRegistryService {
22
22
  sourceKind: AppInstallSourceKind;
23
23
  sourceRef: string;
24
24
  installedAt: string;
25
+ distributionMode?: AppRegistryInstalledVersion["distributionMode"];
25
26
  permissions: AppPermissions;
26
27
  registryUrl?: string;
27
28
  bundleUrl?: string;
@@ -36,7 +36,7 @@ var AppRegistryService = class {
36
36
  return appRecord.installedVersions[appRecord.activeVersion];
37
37
  };
38
38
  upsertInstallation = async (params) => {
39
- const { appId, name, description, version, installDirectory, dataDirectory, sourceKind, sourceRef, installedAt, permissions, registryUrl, bundleUrl, sha256, publisher } = params;
39
+ const { appId, name, description, version, installDirectory, dataDirectory, sourceKind, sourceRef, installedAt, distributionMode, permissions, registryUrl, bundleUrl, sha256, publisher } = params;
40
40
  const registry = await this.load();
41
41
  const currentRecord = registry.apps[appId];
42
42
  const nextRecord = {
@@ -53,6 +53,7 @@ var AppRegistryService = class {
53
53
  sourceKind,
54
54
  sourceRef,
55
55
  installedAt,
56
+ distributionMode,
56
57
  permissions,
57
58
  registryUrl,
58
59
  bundleUrl,
@@ -1,4 +1,5 @@
1
1
  import { AppPermissions } from "../manifest/app-manifest.types.js";
2
+ import { AppDistributionMode } from "../bundle/app-bundle.types.js";
2
3
  import { AppDocumentGrantMap } from "../permissions/app-permissions.types.js";
3
4
  import { AppPublisher } from "./app-remote-registry.types.js";
4
5
 
@@ -10,6 +11,7 @@ type AppRegistryInstalledVersion = {
10
11
  sourceKind: AppInstallSourceKind;
11
12
  sourceRef: string;
12
13
  installedAt: string;
14
+ distributionMode?: AppDistributionMode;
13
15
  permissions: AppPermissions;
14
16
  registryUrl?: string;
15
17
  bundleUrl?: string;
@@ -25,7 +25,8 @@ var AppRemoteRegistryClientService = class {
25
25
  description: versionRecord.description ?? document.description,
26
26
  publisher: versionRecord.publisher,
27
27
  permissions: versionRecord.permissions,
28
- bundleUrl: new URL(versionRecord.dist.bundle, metadataUrl).toString(),
28
+ distributionMode: versionRecord.dist.kind === "source" ? "source" : "bundle",
29
+ bundleUrl: new URL(versionRecord.dist.artifact ?? versionRecord.dist.source ?? versionRecord.dist.bundle, metadataUrl).toString(),
29
30
  sha256: versionRecord.dist.sha256
30
31
  };
31
32
  };
@@ -72,7 +73,10 @@ var AppRemoteRegistryClientService = class {
72
73
  publisher: this.parsePublisher(candidate.publisher, version),
73
74
  permissions: candidate.permissions,
74
75
  dist: {
76
+ kind: distCandidate.kind === "source" || distCandidate.kind === "bundle" ? distCandidate.kind : void 0,
77
+ artifact: this.readOptionalString(distCandidate.artifact, `versions.${version}.dist.artifact`),
75
78
  bundle: this.readRequiredString(distCandidate.bundle, `versions.${version}.dist.bundle`),
79
+ source: this.readOptionalString(distCandidate.source, `versions.${version}.dist.source`),
76
80
  sha256: this.readRequiredString(distCandidate.sha256, `versions.${version}.dist.sha256`)
77
81
  }
78
82
  };
@@ -1,4 +1,5 @@
1
1
  import { AppPermissions } from "../manifest/app-manifest.types.js";
2
+ import { AppDistributionMode } from "../bundle/app-bundle.types.js";
2
3
 
3
4
  //#region src/registry/app-remote-registry.types.d.ts
4
5
  declare const DEFAULT_APP_REGISTRY_URL = "https://apps-registry.nextclaw.io/api/v1/apps/registry/";
@@ -25,7 +26,10 @@ type AppRemoteRegistryVersion = {
25
26
  publisher?: AppPublisher;
26
27
  permissions?: AppPermissions;
27
28
  dist: {
29
+ kind?: AppDistributionMode;
30
+ artifact?: string;
28
31
  bundle: string;
32
+ source?: string;
29
33
  sha256: string;
30
34
  };
31
35
  };
@@ -45,6 +49,7 @@ type AppRemoteRegistryResolution = {
45
49
  description?: string;
46
50
  publisher?: AppPublisher;
47
51
  permissions?: AppPermissions;
52
+ distributionMode: AppDistributionMode;
48
53
  bundleUrl: string;
49
54
  sha256: string;
50
55
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nextclaw/app-runtime",
3
- "version": "0.6.0",
3
+ "version": "0.7.1-beta.0",
4
4
  "private": false,
5
5
  "description": "Standalone micro app runtime and CLI for NextClaw apps.",
6
6
  "type": "module",