@heybox/hb-sdk 0.6.6-alpha.3 → 0.6.6-alpha.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -598,7 +598,9 @@ export default defineConfig({
598
598
 
599
599
  工坊小程序构建产物只能在兼容的小黑盒 Runtime 中启动。普通浏览器直接打开时不会执行标准业务脚本,并会提示在小黑盒 APP 内打开。项目应使用标准 Vite module 入口。
600
600
 
601
- 插件只接受单页应用:输出目录只能存在入口 `index.html`。build 会用结构化 HTML parser 校验入口,并把平台 CSP 插入 `<head>` 首位;已有 CSP 会原样保留,两份策略按浏览器交集生效。正式策略禁止 `fetch`、XHR、WebSocket、EventSource、Beacon、Worker、iframe、表单和对象加载等浏览器原生出口;业务网络请求应使用 `network.request()`。dev 使用相同策略,只额外放行当前 Vite 的精确 HMR WebSocket 地址。
601
+ 插件只接受单页应用:输出目录只能存在入口 `index.html`。`hb-sdk dev` `hb-sdk remote deploy` 会读取绑定小程序的远端 Runtime 权限;仅当 `network.request` 已启用且 `useOfficialDomain=true` 时跳过平台 CSP,否则 build 会把平台 CSP 插入 `<head>` 首位。直接运行 `vite build`、匿名 dev、非法快照或远端权限读取失败时均继续注入。已有 CSP 始终原样保留;注入平台 CSP 时,两份策略按浏览器交集生效。
602
+
603
+ 平台 CSP 会禁止 `fetch`、XHR、WebSocket、EventSource、Beacon、Worker、iframe、表单和对象加载等浏览器原生出口;dev 只额外放行当前 Vite 的精确 HMR WebSocket 地址。跳过平台 CSP 时,这些能力不再由 SDK 构建产物统一限制,但需要宿主授权的业务网络请求仍应使用 `network.request()`。本地 Mock 权限覆盖不会改变构建 CSP,构建判定始终以远端权限快照为准。
602
604
 
603
605
  meta refresh、外部 anchor、`dns-prefetch`、`preconnect`、`prerender`、外部资源 URL 和额外 HTML 会使 build 失败。内联 script/style 允许,但 `unsafe-eval` 不允许。`dev`、`hb-sdk build` 和手动 Vite build 都不请求远端最低 SDK 版本;构建仍会把当前 `sdkVersion` 写入 Manifest,`hb-sdk remote deploy` 仍校验 Manifest 结构并经过服务端 precheck / submit-audit 策略。
604
606
 
@@ -3,10 +3,11 @@
3
3
  var fs$1 = require('node:fs');
4
4
  var fs = require('node:fs/promises');
5
5
  var path = require('node:path');
6
- var index$1 = require('./index-BQm5XmMC.cjs');
7
- var runtimeGate = require('./runtime-gate-B2MQf1vc.cjs');
8
- var index = require('./index-QAkYgxPI.cjs');
9
- var projectVite = require('./project-vite-VcJMyz1l.cjs');
6
+ var runtimePermissionEnv = require('./runtime-permission-env-BSs4uCNa.cjs');
7
+ var runtimeGate = require('./runtime-gate--rPXjiG6.cjs');
8
+ var index = require('./index-19i3Dr5H.cjs');
9
+ var projectVite = require('./project-vite-Dl3OoQjL.cjs');
10
+ require('node:async_hooks');
10
11
  require('node:module');
11
12
  require('path');
12
13
  require('os');
@@ -23,26 +24,30 @@ async function runBuildCommand(_options = {}, runtime = {}) {
23
24
  const logger = runtime.logger ?? index.createCliLogger();
24
25
  const projectRoot = projectVite.findProjectRoot(runtime.cwd ?? process.cwd());
25
26
  const distDir = path.join(projectRoot, 'dist');
26
- const mode = (runtime.env ?? process.env).HB_SDK_ENV?.trim() || undefined;
27
+ const env = runtime.env ?? process.env;
28
+ const mode = env.HB_SDK_ENV?.trim() || undefined;
29
+ const skipPlatformCsp = runtimePermissionEnv.shouldSkipMiniappPlatformCspFromEnv(env);
27
30
  await fs.rm(distDir, { force: true, recursive: true });
28
31
  try {
29
- const vite = await logger.task('正在加载项目 Vite', () => projectVite.loadProjectVite(projectRoot), {
30
- successText: '已加载项目 Vite',
31
- });
32
- await logger.task('正在构建小程序', () => vite.build({
33
- root: projectRoot,
34
- ...(mode ? { mode } : {}),
35
- plugins: [createFixedBuildOutputPlugin(projectRoot)],
36
- build: {
37
- outDir: 'dist',
38
- emptyOutDir: true,
39
- watch: null,
40
- write: true,
41
- },
42
- }), { successText: 'Vite 构建完成' });
43
- const result = await validateBuildOutput(projectRoot, logger);
44
- logger.success(`构建完成: dist/ | manifest version ${result.version} | sdkVersion ${result.sdkVersion} | 待上传文件 ${result.fileCount} 个 | ${formatSize(result.totalBytes)}`);
45
- return result;
32
+ return await runtimePermissionEnv.withMiniappPlatformCspEnv(skipPlatformCsp, async () => {
33
+ const vite = await logger.task('正在加载项目 Vite', () => projectVite.loadProjectVite(projectRoot), {
34
+ successText: '已加载项目 Vite',
35
+ });
36
+ await logger.task('正在构建小程序', () => vite.build({
37
+ root: projectRoot,
38
+ ...(mode ? { mode } : {}),
39
+ plugins: [createFixedBuildOutputPlugin(projectRoot)],
40
+ build: {
41
+ outDir: 'dist',
42
+ emptyOutDir: true,
43
+ watch: null,
44
+ write: true,
45
+ },
46
+ }), { successText: 'Vite 构建完成' });
47
+ const result = await validateBuildOutput(projectRoot, logger);
48
+ logger.success(`构建完成: dist/ | manifest version ${result.version} | sdkVersion ${result.sdkVersion} | 待上传文件 ${result.fileCount} 个 | ${formatSize(result.totalBytes)}`);
49
+ return result;
50
+ }, env);
46
51
  }
47
52
  catch (error) {
48
53
  await fs.rm(distDir, { force: true, recursive: true });
@@ -88,8 +93,8 @@ async function validateBuildOutput(projectRoot, logger) {
88
93
  }
89
94
  const { sdkVersion, version } = runtimeGate.validateMiniappManifestForDeploy(manifest);
90
95
  const allFiles = await walkDistFiles(distDir);
91
- const uploadFiles = allFiles.filter((file) => index$1.shouldUploadDistFile(file.relativePath));
92
- const sizeError = index$1.validateUploadTotalSize(uploadFiles);
96
+ const uploadFiles = allFiles.filter((file) => runtimePermissionEnv.shouldUploadDistFile(file.relativePath));
97
+ const sizeError = runtimePermissionEnv.validateUploadTotalSize(uploadFiles);
93
98
  if (sizeError) {
94
99
  throw new Error(sizeError.replace('重新 deploy', '重新 build'));
95
100
  }
@@ -109,12 +114,12 @@ async function walkDistFiles(distDir) {
109
114
  const entries = await fs.readdir(absDir, { withFileTypes: true });
110
115
  for (const entry of entries) {
111
116
  const absPath = path.join(absDir, entry.name);
112
- const relPath = index$1.normalizeRelativePath(relDir ? `${relDir}/${entry.name}` : entry.name);
117
+ const relPath = runtimePermissionEnv.normalizeRelativePath(relDir ? `${relDir}/${entry.name}` : entry.name);
113
118
  const link = await fs.lstat(absPath);
114
119
  if (link.isSymbolicLink()) {
115
120
  throw new Error(`dist 目录包含 symlink,拒绝处理:${relPath}`);
116
121
  }
117
- if (index$1.relativePathContainsNodeModulesSegment(relPath)) {
122
+ if (runtimePermissionEnv.relativePathContainsNodeModulesSegment(relPath)) {
118
123
  throw new Error(`dist 目录含 node_modules:${relPath}`);
119
124
  }
120
125
  if (entry.isDirectory()) {
@@ -1,11 +1,106 @@
1
1
  'use strict';
2
2
 
3
- var session = require('./session-YJ8xNESM.cjs');
4
- var index = require('./index-BQm5XmMC.cjs');
3
+ var session = require('./session-DJEuhrgq.cjs');
4
+ var runtimePermissionEnv = require('./runtime-permission-env-BSs4uCNa.cjs');
5
5
  var fs$1 = require('node:fs');
6
6
  var fs = require('node:fs/promises');
7
7
  var path = require('node:path');
8
8
 
9
+ const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(['network.request']);
10
+ /**
11
+ * 判断 permission key 是否由 Runtime 权限快照管理。
12
+ *
13
+ * @param key 待判断的 permission key。
14
+ * @returns 该 key 需要读取 Runtime 权限快照时返回 `true`。
15
+ */
16
+ function isManagedMiniProgramRuntimePermissionKey(key) {
17
+ return MANAGED_RUNTIME_PERMISSION_KEYS.has(key);
18
+ }
19
+ /**
20
+ * 解析服务端权限快照;格式不完整时整份快照失效并 fail closed。
21
+ *
22
+ * @param snapshot 待校验的服务端权限快照。
23
+ * @returns 解析状态和通过校验的受管权限。
24
+ */
25
+ function parseMiniProgramRuntimePermissions(snapshot) {
26
+ if (!isRecord(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
27
+ return { valid: false, permissions: {} };
28
+ }
29
+ if (snapshot.revision !== undefined && (typeof snapshot.revision !== 'number' || !Number.isInteger(snapshot.revision) || snapshot.revision < 0)) {
30
+ return { valid: false, permissions: {} };
31
+ }
32
+ const seenKeys = new Set();
33
+ const permissions = {};
34
+ for (const rawEntry of snapshot.entries) {
35
+ if (!isRecord(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
36
+ return { valid: false, permissions: {} };
37
+ }
38
+ const key = rawEntry.key.trim();
39
+ if (seenKeys.has(key) || (rawEntry.status !== 'enabled' && rawEntry.status !== 'disabled') || !isRecord(rawEntry.config)) {
40
+ return { valid: false, permissions: {} };
41
+ }
42
+ seenKeys.add(key);
43
+ if (!isManagedMiniProgramRuntimePermissionKey(key)) {
44
+ continue;
45
+ }
46
+ if (key === 'network.request' && typeof rawEntry.config.useOfficialDomain !== 'boolean') {
47
+ return { valid: false, permissions: {} };
48
+ }
49
+ permissions[key] = {
50
+ key,
51
+ status: rawEntry.status,
52
+ config: { useOfficialDomain: rawEntry.config.useOfficialDomain },
53
+ };
54
+ }
55
+ return { valid: true, permissions };
56
+ }
57
+ function isRecord(value) {
58
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
59
+ }
60
+
61
+ const DEFAULT_PERMISSION_STATE = {
62
+ networkRequest: {
63
+ status: 'disabled',
64
+ useOfficialDomain: false,
65
+ },
66
+ };
67
+ function createMiniProgramMockPermissionState(context) {
68
+ const parsed = parseMiniProgramRuntimePermissions(context.runtimePermissions);
69
+ const networkRequest = parsed.permissions['network.request'];
70
+ return parsed.valid && networkRequest
71
+ ? {
72
+ networkRequest: {
73
+ status: networkRequest.status,
74
+ useOfficialDomain: networkRequest.config.useOfficialDomain === true,
75
+ },
76
+ }
77
+ : cloneDefaultPermissionState();
78
+ }
79
+ function shouldSkipMiniappPlatformCsp(runtimePermissions) {
80
+ const parsed = parseMiniProgramRuntimePermissions(runtimePermissions);
81
+ const networkRequest = parsed.permissions['network.request'];
82
+ return parsed.valid && networkRequest?.status === 'enabled' && networkRequest.config.useOfficialDomain === true;
83
+ }
84
+ function createMiniProgramMockRuntimePermissions(state) {
85
+ return {
86
+ schema_version: 1,
87
+ entries: [
88
+ {
89
+ key: 'network.request',
90
+ status: state.networkRequest.status,
91
+ config: {
92
+ useOfficialDomain: state.networkRequest.useOfficialDomain,
93
+ },
94
+ },
95
+ ],
96
+ };
97
+ }
98
+ function cloneDefaultPermissionState() {
99
+ return {
100
+ networkRequest: { ...DEFAULT_PERMISSION_STATE.networkRequest },
101
+ };
102
+ }
103
+
9
104
  function createRemoteApiClient(options) {
10
105
  return {
11
106
  listDeveloperEntities: () => listDeveloperEntities(options),
@@ -32,74 +127,74 @@ function createRemoteApiClient(options) {
32
127
  };
33
128
  }
34
129
  async function listDeveloperEntities(runtime) {
35
- return remoteGet(index.DEVELOPER_ENTITY_LIST_API_PATH, {}, runtime);
130
+ return remoteGet(runtimePermissionEnv.DEVELOPER_ENTITY_LIST_API_PATH, {}, runtime);
36
131
  }
37
132
  async function switchDeveloperEntity(options, runtime) {
38
- return (await remotePostForm(index.DEVELOPER_ENTITY_SWITCH_API_PATH, options, runtime, { requireResult: false })) ?? {};
133
+ return (await remotePostForm(runtimePermissionEnv.DEVELOPER_ENTITY_SWITCH_API_PATH, options, runtime, { requireResult: false })) ?? {};
39
134
  }
40
135
  async function getDeveloperAccessStatus(runtime) {
41
- return remoteGet(index.USER_MINIPROGRAM_ACCESS_STATUS_API_PATH, {}, runtime);
136
+ return remoteGet(runtimePermissionEnv.USER_MINIPROGRAM_ACCESS_STATUS_API_PATH, {}, runtime);
42
137
  }
43
138
  async function listUserMiniprograms(options, runtime) {
44
- return remoteGet(index.LIST_USER_MINIPROGRAM_API_PATH, options, runtime);
139
+ return remoteGet(runtimePermissionEnv.LIST_USER_MINIPROGRAM_API_PATH, options, runtime);
45
140
  }
46
141
  async function createUserMiniprogram(runtime) {
47
- return remotePostForm(index.CREATE_USER_MINIPROGRAM_API_PATH, {}, runtime);
142
+ return remotePostForm(runtimePermissionEnv.CREATE_USER_MINIPROGRAM_API_PATH, {}, runtime);
48
143
  }
49
144
  async function getUserMiniprogramDetail(options, runtime) {
50
- return remoteGet(index.DETAIL_USER_MINIPROGRAM_API_PATH, options, runtime);
145
+ return remoteGet(runtimePermissionEnv.DETAIL_USER_MINIPROGRAM_API_PATH, options, runtime);
51
146
  }
52
147
  async function getPreviewAllowlist(options, runtime) {
53
- return remoteGet(index.USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH, options, runtime);
148
+ return remoteGet(runtimePermissionEnv.USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH, options, runtime);
54
149
  }
55
150
  async function updatePreviewAllowlist(options, runtime) {
56
- return remotePostForm(index.UPDATE_USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH, options, runtime);
151
+ return remotePostForm(runtimePermissionEnv.UPDATE_USER_MINIPROGRAM_PREVIEW_ALLOWLIST_API_PATH, options, runtime);
57
152
  }
58
153
  async function createUserMiniprogramLeaderboard(options, runtime) {
59
- return remotePostForm(index.CREATE_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime);
154
+ return remotePostForm(runtimePermissionEnv.CREATE_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime);
60
155
  }
61
156
  async function getUserMiniprogramLeaderboard(options, runtime) {
62
- return remoteGet(index.DETAIL_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime);
157
+ return remoteGet(runtimePermissionEnv.DETAIL_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime);
63
158
  }
64
159
  async function listUserMiniprogramLeaderboards(options, runtime) {
65
- return remoteGet(index.LIST_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime);
160
+ return remoteGet(runtimePermissionEnv.LIST_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime);
66
161
  }
67
162
  async function deleteUserMiniprogramLeaderboard(options, runtime) {
68
- return (await remotePostForm(index.DELETE_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime, { requireResult: false })) ?? {};
163
+ return (await remotePostForm(runtimePermissionEnv.DELETE_USER_MINIPROGRAM_LEADERBOARD_API_PATH, options, runtime, { requireResult: false })) ?? {};
69
164
  }
70
165
  async function precheckUserMiniprogramVersion(options, runtime) {
71
- return remotePostForm(index.PRECHECK_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
166
+ return remotePostForm(runtimePermissionEnv.PRECHECK_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
72
167
  }
73
168
  async function submitUserMiniprogramAudit(options, runtime) {
74
169
  const form = { ...options };
75
170
  if (form.manifest && typeof form.manifest !== 'string') {
76
171
  form.manifest = JSON.stringify(form.manifest);
77
172
  }
78
- return remotePostForm(index.SUBMIT_USER_MINIPROGRAM_AUDIT_API_PATH, form, runtime);
173
+ return remotePostForm(runtimePermissionEnv.SUBMIT_USER_MINIPROGRAM_AUDIT_API_PATH, form, runtime);
79
174
  }
80
175
  async function getVersionPreviewInfo(options, runtime) {
81
- return remoteGet(index.USER_MINIPROGRAM_VERSION_PREVIEW_INFO_API_PATH, {
176
+ return remoteGet(runtimePermissionEnv.USER_MINIPROGRAM_VERSION_PREVIEW_INFO_API_PATH, {
82
177
  mini_program_id: options.mini_program_id,
83
178
  preview_version: options.version,
84
179
  }, runtime);
85
180
  }
86
181
  async function withdrawUserMiniprogramVersion(options, runtime) {
87
- return remotePostForm(index.WITHDRAW_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
182
+ return remotePostForm(runtimePermissionEnv.WITHDRAW_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
88
183
  }
89
184
  async function releaseUserMiniprogramVersion(options, runtime) {
90
- return remotePostForm(index.RELEASE_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
185
+ return remotePostForm(runtimePermissionEnv.RELEASE_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
91
186
  }
92
187
  async function takeDownUserMiniprogram(options, runtime) {
93
- return remotePostForm(index.TAKE_DOWN_USER_MINIPROGRAM_API_PATH, options, runtime);
188
+ return remotePostForm(runtimePermissionEnv.TAKE_DOWN_USER_MINIPROGRAM_API_PATH, options, runtime);
94
189
  }
95
190
  async function reopenUserMiniprogram(options, runtime) {
96
- return remotePostForm(index.REOPEN_USER_MINIPROGRAM_API_PATH, options, runtime);
191
+ return remotePostForm(runtimePermissionEnv.REOPEN_USER_MINIPROGRAM_API_PATH, options, runtime);
97
192
  }
98
193
  async function updateSquareDisplay(options, runtime) {
99
- return remotePostForm(index.UPDATE_SQUARE_DISPLAY_API_PATH, options, runtime);
194
+ return remotePostForm(runtimePermissionEnv.UPDATE_SQUARE_DISPLAY_API_PATH, options, runtime);
100
195
  }
101
196
  async function listUserMiniprogramVersions(options, runtime) {
102
- return remoteGet(index.LIST_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
197
+ return remoteGet(runtimePermissionEnv.LIST_USER_MINIPROGRAM_VERSION_API_PATH, options, runtime);
103
198
  }
104
199
  async function remoteGet(path, query, runtime) {
105
200
  const pathWithQuery = createPathWithQuery(path, query);
@@ -302,10 +397,14 @@ function isTruthyEnvFlag(value) {
302
397
  }
303
398
 
304
399
  exports.MiniProgramProjectBindingError = MiniProgramProjectBindingError;
400
+ exports.createMiniProgramMockPermissionState = createMiniProgramMockPermissionState;
401
+ exports.createMiniProgramMockRuntimePermissions = createMiniProgramMockRuntimePermissions;
305
402
  exports.createRemoteApiClientForEnvironment = createRemoteApiClientForEnvironment;
306
403
  exports.getBoundMiniProgram = getBoundMiniProgram;
404
+ exports.parseMiniProgramRuntimePermissions = parseMiniProgramRuntimePermissions;
307
405
  exports.readBoundMiniProgramId = readBoundMiniProgramId;
308
406
  exports.readBoundMiniProgramIdFromPackageJson = readBoundMiniProgramIdFromPackageJson;
309
407
  exports.readMiniProgramProjectPackage = readMiniProgramProjectPackage;
310
408
  exports.resolveRemoteEnvironment = resolveRemoteEnvironment;
409
+ exports.shouldSkipMiniappPlatformCsp = shouldSkipMiniappPlatformCsp;
311
410
  exports.writeBoundMiniProgramId = writeBoundMiniProgramId;
@@ -5,7 +5,7 @@ var fs = require('node:fs/promises');
5
5
  var path = require('node:path');
6
6
  var require$$0 = require('fs');
7
7
  var require$$1 = require('path');
8
- var index = require('./index-QAkYgxPI.cjs');
8
+ var index = require('./index-19i3Dr5H.cjs');
9
9
  require('node:module');
10
10
  require('os');
11
11
  require('readline');
@@ -6,32 +6,33 @@ var path = require('node:path');
6
6
  var net = require('node:net');
7
7
  var promises = require('node:dns/promises');
8
8
  var node_http = require('node:http');
9
+ var context = require('./context-DvTynj3F.cjs');
9
10
  var node_crypto = require('node:crypto');
10
11
  var undici = require('undici');
11
12
  var browser = require('./browser-RAy8e8cV.cjs');
12
- var index = require('./index-QAkYgxPI.cjs');
13
- var projectVite = require('./project-vite-VcJMyz1l.cjs');
14
- var context = require('./context-CvZs9ZBf.cjs');
13
+ var index = require('./index-19i3Dr5H.cjs');
14
+ var projectVite = require('./project-vite-Dl3OoQjL.cjs');
15
15
  var fs$1 = require('node:fs/promises');
16
+ var runtimePermissionEnv = require('./runtime-permission-env-BSs4uCNa.cjs');
17
+ require('./session-DJEuhrgq.cjs');
18
+ require('fs');
19
+ require('constants');
20
+ require('stream');
21
+ require('util');
22
+ require('assert');
23
+ require('path');
16
24
  require('node:process');
17
25
  require('node:buffer');
18
26
  require('node:url');
19
27
  require('node:util');
20
28
  require('node:child_process');
21
29
  require('node:module');
22
- require('path');
23
30
  require('os');
24
31
  require('readline');
25
32
  require('tty');
26
- require('assert');
27
33
  require('events');
28
- require('stream');
29
34
  require('buffer');
30
- require('util');
31
- require('./session-YJ8xNESM.cjs');
32
- require('fs');
33
- require('constants');
34
- require('./index-BQm5XmMC.cjs');
35
+ require('node:async_hooks');
35
36
 
36
37
  class Locked extends Error {
37
38
  constructor(port) {
@@ -195,58 +196,6 @@ async function getPorts(options) {
195
196
  throw new Error('No available ports found');
196
197
  }
197
198
 
198
- const MANAGED_RUNTIME_PERMISSION_KEYS = new Set(['network.request']);
199
- /**
200
- * 判断 permission key 是否由 Runtime 权限快照管理。
201
- *
202
- * @param key 待判断的 permission key。
203
- * @returns 该 key 需要读取 Runtime 权限快照时返回 `true`。
204
- */
205
- function isManagedMiniProgramRuntimePermissionKey(key) {
206
- return MANAGED_RUNTIME_PERMISSION_KEYS.has(key);
207
- }
208
- /**
209
- * 解析服务端权限快照;格式不完整时整份快照失效并 fail closed。
210
- *
211
- * @param snapshot 待校验的服务端权限快照。
212
- * @returns 解析状态和通过校验的受管权限。
213
- */
214
- function parseMiniProgramRuntimePermissions(snapshot) {
215
- if (!isRecord$2(snapshot) || snapshot.schema_version !== 1 || !Array.isArray(snapshot.entries)) {
216
- return { valid: false, permissions: {} };
217
- }
218
- if (snapshot.revision !== undefined && (typeof snapshot.revision !== 'number' || !Number.isInteger(snapshot.revision) || snapshot.revision < 0)) {
219
- return { valid: false, permissions: {} };
220
- }
221
- const seenKeys = new Set();
222
- const permissions = {};
223
- for (const rawEntry of snapshot.entries) {
224
- if (!isRecord$2(rawEntry) || typeof rawEntry.key !== 'string' || !rawEntry.key.trim()) {
225
- return { valid: false, permissions: {} };
226
- }
227
- const key = rawEntry.key.trim();
228
- if (seenKeys.has(key) || (rawEntry.status !== 'enabled' && rawEntry.status !== 'disabled') || !isRecord$2(rawEntry.config)) {
229
- return { valid: false, permissions: {} };
230
- }
231
- seenKeys.add(key);
232
- if (!isManagedMiniProgramRuntimePermissionKey(key)) {
233
- continue;
234
- }
235
- if (key === 'network.request' && typeof rawEntry.config.useOfficialDomain !== 'boolean') {
236
- return { valid: false, permissions: {} };
237
- }
238
- permissions[key] = {
239
- key,
240
- status: rawEntry.status,
241
- config: { useOfficialDomain: rawEntry.config.useOfficialDomain },
242
- };
243
- }
244
- return { valid: true, permissions };
245
- }
246
- function isRecord$2(value) {
247
- return typeof value === 'object' && value !== null && !Array.isArray(value);
248
- }
249
-
250
199
  /** Dev Shell 读取局域网 Dev Session endpoint 的 query 参数。 */
251
200
  /** Mock Host 创建和读取 Dev Session 的固定路径。 */
252
201
  const MINI_PROGRAM_DEV_CONTEXT_PATH = '/__hb_sdk__/dev-context';
@@ -692,7 +641,7 @@ function validateDevSessionCreatePayload(payload, allowedMiniUrlOrigins) {
692
641
  !allowedMiniUrlOrigins.has(miniUrlOrigin.origin)) {
693
642
  throw new TypeError('mini_url_origin must be an allowed LAN origin');
694
643
  }
695
- const parsedPermissions = parseMiniProgramRuntimePermissions(payload.runtime_permissions);
644
+ const parsedPermissions = context.parseMiniProgramRuntimePermissions(payload.runtime_permissions);
696
645
  if (!parsedPermissions.valid) {
697
646
  throw new TypeError('runtime_permissions is invalid');
698
647
  }
@@ -1035,7 +984,7 @@ async function handleDevPermissionMutation(request, response, controller) {
1035
984
  if (!isRecord$1(payload) || Object.keys(payload).length !== 1 || !Object.hasOwn(payload, 'runtime_permissions')) {
1036
985
  throw createMockHostError(400, 'INVALID_DEV_PERMISSIONS', 'Dev permissions update body is invalid');
1037
986
  }
1038
- const parsed = parseMiniProgramRuntimePermissions(payload.runtime_permissions);
987
+ const parsed = context.parseMiniProgramRuntimePermissions(payload.runtime_permissions);
1039
988
  if (!parsed.valid) {
1040
989
  throw createMockHostError(400, 'INVALID_DEV_PERMISSIONS', 'runtime_permissions is invalid');
1041
990
  }
@@ -1218,48 +1167,10 @@ function createHeyboxProtocol(payload) {
1218
1167
  return `heybox://${encodeURIComponent(JSON.stringify(payload))}`;
1219
1168
  }
1220
1169
 
1221
- const DEFAULT_PERMISSION_STATE = {
1222
- networkRequest: {
1223
- status: 'disabled',
1224
- useOfficialDomain: false,
1225
- },
1226
- };
1227
- function createMiniProgramMockPermissionState(context) {
1228
- const parsed = parseMiniProgramRuntimePermissions(context.runtimePermissions);
1229
- const networkRequest = parsed.permissions['network.request'];
1230
- return parsed.valid && networkRequest
1231
- ? {
1232
- networkRequest: {
1233
- status: networkRequest.status,
1234
- useOfficialDomain: networkRequest.config.useOfficialDomain === true,
1235
- },
1236
- }
1237
- : cloneDefaultPermissionState();
1238
- }
1239
- function createMiniProgramMockRuntimePermissions(state) {
1240
- return {
1241
- schema_version: 1,
1242
- entries: [
1243
- {
1244
- key: 'network.request',
1245
- status: state.networkRequest.status,
1246
- config: {
1247
- useOfficialDomain: state.networkRequest.useOfficialDomain,
1248
- },
1249
- },
1250
- ],
1251
- };
1252
- }
1253
- function cloneDefaultPermissionState() {
1254
- return {
1255
- networkRequest: { ...DEFAULT_PERMISSION_STATE.networkRequest },
1256
- };
1257
- }
1258
-
1259
1170
  /** 构建时替换为当前发布包的实际版本。 */
1260
1171
  const HB_SDK_VERSION = typeof undefined === 'string'
1261
1172
  ? undefined
1262
- : '0.6.6-alpha.3';
1173
+ : '0.6.6-alpha.4';
1263
1174
 
1264
1175
  class DevPermissionOverrideStoreError extends Error {
1265
1176
  code;
@@ -1430,7 +1341,7 @@ async function runDevCommand(options, runtime = {}) {
1430
1341
  projectRoot,
1431
1342
  });
1432
1343
  const vite = await logger.task('正在加载项目 Vite', () => projectVite.loadProjectVite(projectRoot), { successText: '已加载项目 Vite' });
1433
- const appServer = await logger.task('正在创建 Vite dev server', () => withManagedDevOutputEnv(() => vite.createServer(createViteServerOptions(projectRoot, resolvedOptions)), runtime.env), { successText: '已创建 Vite dev server' });
1344
+ const appServer = await logger.task('正在创建 Vite dev server', () => withManagedDevOutputEnv(() => vite.createServer(createViteServerOptions(projectRoot, resolvedOptions)), runtime.env, devLaunchContext.runtimePermissions), { successText: '已创建 Vite dev server' });
1434
1345
  await logger.task('正在启动 Vite dev server', () => appServer.listen(appPort), {
1435
1346
  successText: 'Vite dev server 已启动',
1436
1347
  });
@@ -1547,7 +1458,7 @@ function createDevPermissionController(options) {
1547
1458
  source: devContext.source,
1548
1459
  ...(miniProgramId ? { mini_program_id: miniProgramId } : {}),
1549
1460
  ...(isRuntimePermissionsSnapshot(devContext.runtimePermissions) ? { remote_permissions: devContext.runtimePermissions } : {}),
1550
- ...(overrides ? { override_permissions: createMiniProgramMockRuntimePermissions(overrides) } : {}),
1461
+ ...(overrides ? { override_permissions: context.createMiniProgramMockRuntimePermissions(overrides) } : {}),
1551
1462
  ...(error ? { persistence_error: error } : {}),
1552
1463
  };
1553
1464
  };
@@ -1584,7 +1495,7 @@ function createDevPermissionController(options) {
1584
1495
  return createConfiguration(undefined);
1585
1496
  },
1586
1497
  async save(runtimePermissions) {
1587
- const overrides = createMiniProgramMockPermissionState({
1498
+ const overrides = context.createMiniProgramMockPermissionState({
1588
1499
  runtimePermissions,
1589
1500
  });
1590
1501
  try {
@@ -1602,7 +1513,7 @@ function createDevPermissionController(options) {
1602
1513
  };
1603
1514
  }
1604
1515
  function isRuntimePermissionsSnapshot(value) {
1605
- return parseMiniProgramRuntimePermissions(value).valid;
1516
+ return context.parseMiniProgramRuntimePermissions(value).valid;
1606
1517
  }
1607
1518
  async function loadRemoteDevContextWithTimeout(options) {
1608
1519
  const controller = new AbortController();
@@ -1744,18 +1655,18 @@ function rewriteLocalhostUrl(input) {
1744
1655
  function isLocalhostHost(hostname) {
1745
1656
  return hostname === 'localhost' || hostname === '::1' || hostname === '[::1]';
1746
1657
  }
1747
- async function withManagedDevOutputEnv(action, env = process.env) {
1748
- const previous = env[MANAGED_DEV_OUTPUT_ENV];
1658
+ async function withManagedDevOutputEnv(action, env = process.env, runtimePermissions) {
1659
+ const previousManagedOutput = env[MANAGED_DEV_OUTPUT_ENV];
1749
1660
  env[MANAGED_DEV_OUTPUT_ENV] = '1';
1750
1661
  try {
1751
- return await action();
1662
+ return await runtimePermissionEnv.withMiniappPlatformCspEnv(context.shouldSkipMiniappPlatformCsp(runtimePermissions), action, env);
1752
1663
  }
1753
1664
  finally {
1754
- if (previous === undefined) {
1665
+ if (previousManagedOutput === undefined) {
1755
1666
  delete env[MANAGED_DEV_OUTPUT_ENV];
1756
1667
  }
1757
1668
  else {
1758
- env[MANAGED_DEV_OUTPUT_ENV] = previous;
1669
+ env[MANAGED_DEV_OUTPUT_ENV] = previousManagedOutput;
1759
1670
  }
1760
1671
  }
1761
1672
  }
@@ -4,7 +4,7 @@ var fs$1 = require('node:fs');
4
4
  var fs = require('node:fs/promises');
5
5
  var os = require('node:os');
6
6
  var path = require('node:path');
7
- var index = require('./index-QAkYgxPI.cjs');
7
+ var index = require('./index-19i3Dr5H.cjs');
8
8
  require('node:module');
9
9
  require('path');
10
10
  require('os');