expo-harmony-toolkit 1.11.2 → 1.11.3
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.en.md +3 -3
- package/README.md +3 -3
- package/build/core/constants.d.ts +1 -1
- package/build/core/constants.js +1 -1
- package/build/core/metadata.js +15 -4
- package/build/core/report.js +8 -2
- package/build/core/safeProjectWrite.d.ts +3 -0
- package/build/core/safeProjectWrite.js +57 -0
- package/build/core/template.js +23 -9
- package/build/data/publicDocs.d.ts +1 -1
- package/build/plugin.js +2 -4
- package/docs/cli-build.md +1 -1
- package/docs/npm-release.md +3 -1
- package/docs/roadmap.md +2 -1
- package/docs/support-matrix.md +2 -2
- package/package.json +1 -1
- package/templates/harmony/AppScope/app.json5 +1 -1
- package/templates/harmony/AppScope/resources/base/element/string.json +1 -1
- package/templates/harmony/entry/oh-package.json5 +2 -2
- package/templates/harmony/entry/src/main/ets/pages/Index.ets +2 -2
- package/templates/harmony/entry/src/main/resources/base/element/string.json +3 -3
- package/templates/harmony/oh-package.json5 +2 -2
package/README.en.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<p>
|
|
10
10
|
<a href="https://github.com/BlackishGreen33/Expo-Harmony-Toolkit/actions/workflows/ci.yml"><img alt="Checks" src="https://img.shields.io/badge/checks-passing-16a34a?style=flat-square&logo=githubactions&logoColor=white"></a>
|
|
11
11
|
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-0f766e?style=flat-square"></a>
|
|
12
|
-
<a href="https://github.com/BlackishGreen33/Expo-Harmony-Toolkit/releases"><img alt="Version" src="https://img.shields.io/badge/version-v1.11.
|
|
12
|
+
<a href="https://github.com/BlackishGreen33/Expo-Harmony-Toolkit/releases"><img alt="Version" src="https://img.shields.io/badge/version-v1.11.3-111827?style=flat-square"></a>
|
|
13
13
|
<a href="./docs/support-matrix.md"><img alt="Matrix" src="https://img.shields.io/badge/matrix-expo55--rnoh082--ui--stack-2563eb?style=flat-square"></a>
|
|
14
14
|
<img alt="Input" src="https://img.shields.io/badge/input-Managed%2FCNG%20%2B%20bare%20intake-059669?style=flat-square">
|
|
15
15
|
</p>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
</div>
|
|
25
25
|
|
|
26
26
|
> [!IMPORTANT]
|
|
27
|
-
> `v1.11.
|
|
27
|
+
> `v1.11.3` updates repository code with the v2 readiness non-device gate / fallback / exception ledger; this update does not create a tag, publish npm, or create a GitHub Release. `v1.11.2` remains the current npm `latest` release and keeps the ccnubox_rn signed simulator app-shell gate record; the public promise stays tight: `latest` only carries fully accepted `verified` capabilities, and v1.11.3 is not a verified expansion.
|
|
28
28
|
|
|
29
29
|
> [!TIP]
|
|
30
30
|
> The two validated `@react-native-oh-tpl/*` adapters in the public matrix are currently consumed via exact Git URLs and commits. For repository development and the official UI-stack sample, prefer `pnpm install --ignore-scripts` so adapter prepare hooks do not fail on private upstream resources.
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
<!-- GENERATED:readme-current-status:start -->
|
|
49
49
|
| Item | Status |
|
|
50
50
|
| --- | --- |
|
|
51
|
-
| Current version | `v1.11.
|
|
51
|
+
| Current version | `v1.11.3` |
|
|
52
52
|
| Support model | `verified + preview + experimental` |
|
|
53
53
|
| Public `verified` matrix | `expo55-rnoh082-ui-stack` |
|
|
54
54
|
| Supported input | Managed/CNG Expo projects; bare and catalog-out intake classification |
|
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
<p>
|
|
10
10
|
<a href="https://github.com/BlackishGreen33/Expo-Harmony-Toolkit/actions/workflows/ci.yml"><img alt="Checks" src="https://img.shields.io/badge/checks-passing-16a34a?style=flat-square&logo=githubactions&logoColor=white"></a>
|
|
11
11
|
<a href="./LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-0f766e?style=flat-square"></a>
|
|
12
|
-
<a href="https://github.com/BlackishGreen33/Expo-Harmony-Toolkit/releases"><img alt="Version" src="https://img.shields.io/badge/version-v1.11.
|
|
12
|
+
<a href="https://github.com/BlackishGreen33/Expo-Harmony-Toolkit/releases"><img alt="Version" src="https://img.shields.io/badge/version-v1.11.3-111827?style=flat-square"></a>
|
|
13
13
|
<a href="./docs/support-matrix.md"><img alt="Matrix" src="https://img.shields.io/badge/matrix-expo55--rnoh082--ui--stack-2563eb?style=flat-square"></a>
|
|
14
14
|
<img alt="Input" src="https://img.shields.io/badge/input-Managed%2FCNG%20%2B%20bare%20intake-059669?style=flat-square">
|
|
15
15
|
</p>
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
</div>
|
|
25
25
|
|
|
26
26
|
> [!IMPORTANT]
|
|
27
|
-
> `v1.11.
|
|
27
|
+
> `v1.11.3` 已更新仓库代码,完成 v2 readiness 非实机 gate / fallback / exception 台账;本次不创建 tag、不发布 npm、不创建 GitHub Release。`v1.11.2` 仍是当前已发布到 npm `latest` 的版本,并保留 ccnubox_rn signed simulator app-shell gate 记录;当前公开承诺仍然收紧为:`latest` 只承诺完整验收的 `verified` 能力,v1.11.3 不是 verified 扩容。
|
|
28
28
|
|
|
29
29
|
> [!TIP]
|
|
30
30
|
> 由于当前公开矩阵内的两套 `@react-native-oh-tpl/*` adapter 依赖以 Git URL + exact commit 形式接入,仓库开发和官方 UI-stack sample 推荐使用 `pnpm install --ignore-scripts`,避免 Git adapter 在 prepare 阶段拉取私有资源而中断安装。
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
<!-- GENERATED:readme-current-status:start -->
|
|
49
49
|
| 项目 | 说明 |
|
|
50
50
|
| --- | --- |
|
|
51
|
-
| 当前版本 | `v1.11.
|
|
51
|
+
| 当前版本 | `v1.11.3` |
|
|
52
52
|
| 支持模型 | `verified + preview + experimental` |
|
|
53
53
|
| 唯一 `verified` 公开矩阵 | `expo55-rnoh082-ui-stack` |
|
|
54
54
|
| 输入范围 | Managed/CNG Expo 项目;bare 与 catalog 外项目 intake 分类 |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const TOOLKIT_PACKAGE_NAME = "expo-harmony-toolkit";
|
|
2
2
|
export declare const CLI_NAME = "expo-harmony";
|
|
3
|
-
export declare const TOOLKIT_VERSION = "1.11.
|
|
3
|
+
export declare const TOOLKIT_VERSION = "1.11.3";
|
|
4
4
|
export declare const TEMPLATE_VERSION = "rnoh-0.82.29";
|
|
5
5
|
export declare const RNOH_VERSION = "0.82.29";
|
|
6
6
|
export declare const RNOH_CLI_VERSION = "0.82.29";
|
package/build/core/constants.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.DESIRED_PACKAGE_SCRIPTS = exports.HARMONY_RUNTIME_PRELUDE_RELATIVE_PATH = exports.HARMONY_ROUTER_ENTRY_FILENAME = exports.STRICT_ENV_EXIT_CODE = exports.STRICT_DOCTOR_EXIT_CODE = exports.DEFAULT_HVIGOR_PLUGIN_FILENAME = exports.PREBUILD_METADATA_FILENAME = exports.TOOLKIT_CONFIG_FILENAME = exports.BUILD_REPORT_FILENAME = exports.ENV_REPORT_FILENAME = exports.DOCTOR_REPORT_FILENAME = exports.MANIFEST_FILENAME = exports.SIGNING_LOCAL_EXAMPLE_FILENAME = exports.SIGNING_LOCAL_FILENAME = exports.GENERATED_SHIMS_DIR = exports.GENERATED_DIR = exports.SUPPORTED_EXPO_SDKS = exports.RNOH_CLI_VERSION = exports.RNOH_VERSION = exports.TEMPLATE_VERSION = exports.TOOLKIT_VERSION = exports.CLI_NAME = exports.TOOLKIT_PACKAGE_NAME = void 0;
|
|
4
4
|
exports.TOOLKIT_PACKAGE_NAME = 'expo-harmony-toolkit';
|
|
5
5
|
exports.CLI_NAME = 'expo-harmony';
|
|
6
|
-
exports.TOOLKIT_VERSION = '1.11.
|
|
6
|
+
exports.TOOLKIT_VERSION = '1.11.3';
|
|
7
7
|
exports.TEMPLATE_VERSION = 'rnoh-0.82.29';
|
|
8
8
|
exports.RNOH_VERSION = '0.82.29';
|
|
9
9
|
exports.RNOH_CLI_VERSION = '0.82.29';
|
package/build/core/metadata.js
CHANGED
|
@@ -14,6 +14,7 @@ exports.writeBuildReport = writeBuildReport;
|
|
|
14
14
|
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
15
15
|
const path_1 = __importDefault(require("path"));
|
|
16
16
|
const constants_1 = require("./constants");
|
|
17
|
+
const safeProjectWrite_1 = require("./safeProjectWrite");
|
|
17
18
|
function getManifestPath(projectRoot) {
|
|
18
19
|
return path_1.default.join(projectRoot, constants_1.GENERATED_DIR, constants_1.MANIFEST_FILENAME);
|
|
19
20
|
}
|
|
@@ -42,13 +43,23 @@ async function readToolkitConfig(projectRoot) {
|
|
|
42
43
|
}
|
|
43
44
|
async function writeEnvReport(projectRoot, report, outputPath) {
|
|
44
45
|
const resolvedOutputPath = outputPath ?? getEnvReportPath(projectRoot);
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
if (outputPath) {
|
|
47
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(resolvedOutputPath));
|
|
48
|
+
await fs_extra_1.default.writeJson(resolvedOutputPath, report, { spaces: 2 });
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
await (0, safeProjectWrite_1.writeProjectJson)(projectRoot, path_1.default.join(constants_1.GENERATED_DIR, constants_1.ENV_REPORT_FILENAME), report);
|
|
52
|
+
}
|
|
47
53
|
return resolvedOutputPath;
|
|
48
54
|
}
|
|
49
55
|
async function writeBuildReport(projectRoot, report, outputPath) {
|
|
50
56
|
const resolvedOutputPath = outputPath ?? getBuildReportPath(projectRoot);
|
|
51
|
-
|
|
52
|
-
|
|
57
|
+
if (outputPath) {
|
|
58
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(resolvedOutputPath));
|
|
59
|
+
await fs_extra_1.default.writeJson(resolvedOutputPath, report, { spaces: 2 });
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
await (0, safeProjectWrite_1.writeProjectJson)(projectRoot, path_1.default.join(constants_1.GENERATED_DIR, constants_1.BUILD_REPORT_FILENAME), report);
|
|
63
|
+
}
|
|
53
64
|
return resolvedOutputPath;
|
|
54
65
|
}
|
package/build/core/report.js
CHANGED
|
@@ -10,6 +10,7 @@ const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const semver_1 = __importDefault(require("semver"));
|
|
12
12
|
const constants_1 = require("./constants");
|
|
13
|
+
const safeProjectWrite_1 = require("./safeProjectWrite");
|
|
13
14
|
const dependencyInspection_1 = require("./dependencyInspection");
|
|
14
15
|
const dependencyCatalog_1 = require("../data/dependencyCatalog");
|
|
15
16
|
const validatedMatrices_1 = require("../data/validatedMatrices");
|
|
@@ -178,8 +179,13 @@ async function buildDoctorReport(projectRoot, options = {}) {
|
|
|
178
179
|
}
|
|
179
180
|
async function writeDoctorReport(projectRoot, report, outputPath) {
|
|
180
181
|
const resolvedOutputPath = outputPath ?? path_1.default.join(projectRoot, constants_1.GENERATED_DIR, constants_1.DOCTOR_REPORT_FILENAME);
|
|
181
|
-
|
|
182
|
-
|
|
182
|
+
if (outputPath) {
|
|
183
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(resolvedOutputPath));
|
|
184
|
+
await fs_extra_1.default.writeJson(resolvedOutputPath, report, { spaces: 2 });
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
await (0, safeProjectWrite_1.writeProjectJson)(projectRoot, path_1.default.join(constants_1.GENERATED_DIR, constants_1.DOCTOR_REPORT_FILENAME), report);
|
|
188
|
+
}
|
|
183
189
|
return resolvedOutputPath;
|
|
184
190
|
}
|
|
185
191
|
function renderDoctorReport(report) {
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function resolveProjectPathForWrite(projectRoot: string, relativePath: string): Promise<string>;
|
|
2
|
+
export declare function writeProjectFile(projectRoot: string, relativePath: string, contents: string | Buffer): Promise<string>;
|
|
3
|
+
export declare function writeProjectJson(projectRoot: string, relativePath: string, value: unknown): Promise<string>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveProjectPathForWrite = resolveProjectPathForWrite;
|
|
7
|
+
exports.writeProjectFile = writeProjectFile;
|
|
8
|
+
exports.writeProjectJson = writeProjectJson;
|
|
9
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
|
+
const path_1 = __importDefault(require("path"));
|
|
11
|
+
async function resolveProjectPathForWrite(projectRoot, relativePath) {
|
|
12
|
+
if (path_1.default.isAbsolute(relativePath)) {
|
|
13
|
+
throw new Error(`Project output path must be relative: ${relativePath}`);
|
|
14
|
+
}
|
|
15
|
+
const realProjectRoot = await fs_extra_1.default.realpath(projectRoot);
|
|
16
|
+
const targetPath = path_1.default.resolve(realProjectRoot, relativePath);
|
|
17
|
+
if (!isPathInside(targetPath, realProjectRoot)) {
|
|
18
|
+
throw new Error(`Project output path escapes project root: ${relativePath}`);
|
|
19
|
+
}
|
|
20
|
+
await assertNoSymlinkPath(realProjectRoot, targetPath, relativePath);
|
|
21
|
+
return targetPath;
|
|
22
|
+
}
|
|
23
|
+
async function writeProjectFile(projectRoot, relativePath, contents) {
|
|
24
|
+
const targetPath = await resolveProjectPathForWrite(projectRoot, relativePath);
|
|
25
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(targetPath));
|
|
26
|
+
await fs_extra_1.default.writeFile(targetPath, contents);
|
|
27
|
+
return targetPath;
|
|
28
|
+
}
|
|
29
|
+
async function writeProjectJson(projectRoot, relativePath, value) {
|
|
30
|
+
const targetPath = await resolveProjectPathForWrite(projectRoot, relativePath);
|
|
31
|
+
await fs_extra_1.default.ensureDir(path_1.default.dirname(targetPath));
|
|
32
|
+
await fs_extra_1.default.writeJson(targetPath, value, { spaces: 2 });
|
|
33
|
+
return targetPath;
|
|
34
|
+
}
|
|
35
|
+
async function assertNoSymlinkPath(realProjectRoot, targetPath, displayPath) {
|
|
36
|
+
let currentPath = realProjectRoot;
|
|
37
|
+
const relativeSegments = path_1.default.relative(realProjectRoot, targetPath).split(path_1.default.sep);
|
|
38
|
+
for (const segment of relativeSegments) {
|
|
39
|
+
currentPath = path_1.default.join(currentPath, segment);
|
|
40
|
+
try {
|
|
41
|
+
const stat = await fs_extra_1.default.lstat(currentPath);
|
|
42
|
+
if (stat.isSymbolicLink()) {
|
|
43
|
+
throw new Error(`Project output path contains a symlink: ${displayPath}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error.code === 'ENOENT') {
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function isPathInside(candidatePath, parentPath) {
|
|
55
|
+
const relativePath = path_1.default.relative(parentPath, candidatePath);
|
|
56
|
+
return relativePath === '' || (!relativePath.startsWith('..') && !path_1.default.isAbsolute(relativePath));
|
|
57
|
+
}
|
package/build/core/template.js
CHANGED
|
@@ -15,6 +15,7 @@ const capabilities_1 = require("../data/capabilities");
|
|
|
15
15
|
const project_1 = require("./project");
|
|
16
16
|
const javascriptDependencies_1 = require("./javascriptDependencies");
|
|
17
17
|
const report_1 = require("./report");
|
|
18
|
+
const safeProjectWrite_1 = require("./safeProjectWrite");
|
|
18
19
|
const signing_1 = require("./signing");
|
|
19
20
|
const autolinking_1 = require("./autolinking");
|
|
20
21
|
const capabilityRegistry_1 = require("./template/capabilityRegistry");
|
|
@@ -95,7 +96,7 @@ async function syncProjectTemplate(projectRoot, force = false, options = {}) {
|
|
|
95
96
|
result.warnings.push(...(0, support_1.collectMetadataWarnings)(previousManifest, previousToolkitConfig));
|
|
96
97
|
const manifestFiles = [];
|
|
97
98
|
for (const file of desiredFiles) {
|
|
98
|
-
const targetPath =
|
|
99
|
+
const targetPath = await (0, safeProjectWrite_1.resolveProjectPathForWrite)(loadedProject.projectRoot, file.relativePath);
|
|
99
100
|
const expectedHash = (0, project_1.createGeneratedSha)(file.contents);
|
|
100
101
|
const previousRecord = previousManifest?.files.find((record) => record.relativePath === file.relativePath);
|
|
101
102
|
if (await fs_extra_1.default.pathExists(targetPath)) {
|
|
@@ -114,15 +115,13 @@ async function syncProjectTemplate(projectRoot, force = false, options = {}) {
|
|
|
114
115
|
continue;
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
|
-
await
|
|
118
|
-
await fs_extra_1.default.writeFile(targetPath, file.contents);
|
|
118
|
+
await (0, safeProjectWrite_1.writeProjectFile)(loadedProject.projectRoot, file.relativePath, file.contents);
|
|
119
119
|
result.writtenFiles.push(file.relativePath);
|
|
120
120
|
manifestFiles.push({ relativePath: file.relativePath, sha1: expectedHash });
|
|
121
121
|
}
|
|
122
122
|
if (!options.skipJavaScriptDependencyNormalization) {
|
|
123
123
|
await (0, javascriptDependencies_1.normalizeKnownJavaScriptDependencies)(loadedProject.projectRoot, loadedProject.packageJson);
|
|
124
124
|
}
|
|
125
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(result.manifestPath));
|
|
126
125
|
const manifest = {
|
|
127
126
|
generatedAt: new Date().toISOString(),
|
|
128
127
|
toolkitVersion: constants_1.TOOLKIT_VERSION,
|
|
@@ -131,7 +130,7 @@ async function syncProjectTemplate(projectRoot, force = false, options = {}) {
|
|
|
131
130
|
projectRoot: loadedProject.projectRoot,
|
|
132
131
|
files: manifestFiles,
|
|
133
132
|
};
|
|
134
|
-
await
|
|
133
|
+
await (0, safeProjectWrite_1.writeProjectJson)(loadedProject.projectRoot, path_1.default.relative(loadedProject.projectRoot, result.manifestPath), manifest);
|
|
135
134
|
return result;
|
|
136
135
|
}
|
|
137
136
|
function renderSidecarDriftRequiresForceWarning(relativePath) {
|
|
@@ -267,7 +266,7 @@ async function buildManagedFiles(loadedProject, identifiers, previousToolkitConf
|
|
|
267
266
|
];
|
|
268
267
|
}
|
|
269
268
|
async function syncPackageScripts(projectRoot, _force) {
|
|
270
|
-
const packageJsonPath =
|
|
269
|
+
const packageJsonPath = await (0, safeProjectWrite_1.resolveProjectPathForWrite)(projectRoot, 'package.json');
|
|
271
270
|
const packageJson = (await fs_extra_1.default.readJson(packageJsonPath));
|
|
272
271
|
const desiredScripts = (0, support_1.buildDesiredPackageScripts)(packageJson);
|
|
273
272
|
const scripts = { ...(packageJson.scripts ?? {}) };
|
|
@@ -290,14 +289,13 @@ async function syncPackageScripts(projectRoot, _force) {
|
|
|
290
289
|
}
|
|
291
290
|
if (didChange) {
|
|
292
291
|
packageJson.scripts = (0, support_1.sortRecordByKey)(scripts);
|
|
293
|
-
await
|
|
294
|
-
await fs_extra_1.default.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2) + '\n');
|
|
292
|
+
await (0, safeProjectWrite_1.writeProjectFile)(projectRoot, 'package.json', JSON.stringify(packageJson, null, 2) + '\n');
|
|
295
293
|
}
|
|
296
294
|
return warnings;
|
|
297
295
|
}
|
|
298
296
|
function renderTemplate(template, loadedProject, identifiers, hvigorPluginFilename) {
|
|
299
297
|
const appDescription = `${identifiers.appName} official minimal Harmony sample`;
|
|
300
|
-
const
|
|
298
|
+
const rawReplacements = {
|
|
301
299
|
APP_NAME: identifiers.appName,
|
|
302
300
|
APP_SLUG: identifiers.slug,
|
|
303
301
|
APP_VERSION: String(loadedProject.expoConfig.version ?? loadedProject.packageJson.version ?? '1.0.0'),
|
|
@@ -309,8 +307,24 @@ function renderTemplate(template, loadedProject, identifiers, hvigorPluginFilena
|
|
|
309
307
|
RNOH_CLI_VERSION: constants_1.RNOH_CLI_VERSION,
|
|
310
308
|
RNOH_HVIGOR_PLUGIN_FILENAME: hvigorPluginFilename,
|
|
311
309
|
};
|
|
310
|
+
const replacements = {
|
|
311
|
+
...rawReplacements,
|
|
312
|
+
APP_NAME_JSON: JSON.stringify(rawReplacements.APP_NAME),
|
|
313
|
+
APP_VERSION_JSON: JSON.stringify(rawReplacements.APP_VERSION),
|
|
314
|
+
APP_VERSION_JSON5: renderSingleQuotedStringContents(rawReplacements.APP_VERSION),
|
|
315
|
+
APP_DESCRIPTION_JSON: JSON.stringify(rawReplacements.APP_DESCRIPTION),
|
|
316
|
+
APP_DESCRIPTION_JSON5: renderSingleQuotedStringContents(rawReplacements.APP_DESCRIPTION),
|
|
317
|
+
APP_SLUG_ARKTS: renderSingleQuotedStringContents(rawReplacements.APP_SLUG),
|
|
318
|
+
};
|
|
312
319
|
return template.replace(/\{\{([A-Z0-9_]+)\}\}/g, (_, key) => replacements[key] ?? '');
|
|
313
320
|
}
|
|
321
|
+
function renderSingleQuotedStringContents(value) {
|
|
322
|
+
return JSON.stringify(value)
|
|
323
|
+
.slice(1, -1)
|
|
324
|
+
.replace(/'/g, "\\'")
|
|
325
|
+
.replace(/\u2028/g, '\\u2028')
|
|
326
|
+
.replace(/\u2029/g, '\\u2029');
|
|
327
|
+
}
|
|
314
328
|
function renderRnohGeneratedTsShim() {
|
|
315
329
|
let relativeTarget = path_1.default.relative(path_1.default.dirname(RNOH_GENERATED_TS_SHIM_RELATIVE_PATH), path_1.default.join('harmony', 'expo-harmony-local-deps', 'rnoh-react-native-openharmony-react_native_openharmony', 'ts.ts'));
|
|
316
330
|
relativeTarget = relativeTarget.replace(/\\/g, '/').replace(/\.ts$/, '');
|
|
@@ -8,4 +8,4 @@ export declare const SUPPORTING_SAMPLE_PATHS: readonly ["examples/official-app-s
|
|
|
8
8
|
export declare const VERIFIED_JS_UI_CAPABILITY_NAMES: readonly ["expo-router", "expo-linking", "expo-constants", ...("react-native-reanimated" | "react-native-svg")[]];
|
|
9
9
|
export declare const PREVIEW_CAPABILITY_DEFINITIONS: import("..").CapabilityDefinition[];
|
|
10
10
|
export declare const EXPERIMENTAL_CAPABILITY_NAMES: readonly string[];
|
|
11
|
-
export declare const PUBLIC_CURRENT_VERSION = "1.11.
|
|
11
|
+
export declare const PUBLIC_CURRENT_VERSION = "1.11.3";
|
package/build/plugin.js
CHANGED
|
@@ -6,13 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.withExpoHarmony = void 0;
|
|
7
7
|
exports.buildPrebuildMetadata = buildPrebuildMetadata;
|
|
8
8
|
exports.validatePluginProps = validatePluginProps;
|
|
9
|
-
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
10
9
|
const path_1 = __importDefault(require("path"));
|
|
11
10
|
const config_plugins_1 = require("expo/config-plugins");
|
|
12
11
|
const validatedMatrices_1 = require("./data/validatedMatrices");
|
|
13
12
|
const constants_1 = require("./core/constants");
|
|
14
13
|
const project_1 = require("./core/project");
|
|
15
14
|
const project_2 = require("./core/project");
|
|
15
|
+
const safeProjectWrite_1 = require("./core/safeProjectWrite");
|
|
16
16
|
const withExpoHarmony = (config, props = {}) => {
|
|
17
17
|
validatePluginProps(props);
|
|
18
18
|
const identifiers = (0, project_1.deriveHarmonyIdentifiers)(config, undefined, props);
|
|
@@ -59,9 +59,7 @@ function registerMetadataDangerousMod(config, platform, identifiers, props) {
|
|
|
59
59
|
async (currentConfig) => {
|
|
60
60
|
const metadata = buildPrebuildMetadata(currentConfig, identifiers, props);
|
|
61
61
|
const projectRoot = currentConfig.modRequest.projectRoot;
|
|
62
|
-
|
|
63
|
-
await fs_extra_1.default.ensureDir(path_1.default.dirname(targetPath));
|
|
64
|
-
await fs_extra_1.default.writeJson(targetPath, metadata, { spaces: 2 });
|
|
62
|
+
await (0, safeProjectWrite_1.writeProjectJson)(projectRoot, path_1.default.join(constants_1.GENERATED_DIR, constants_1.PREBUILD_METADATA_FILENAME), metadata);
|
|
65
63
|
return currentConfig;
|
|
66
64
|
},
|
|
67
65
|
]);
|
package/docs/cli-build.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# CLI 构建指南
|
|
2
2
|
|
|
3
|
-
`v1.11.
|
|
3
|
+
`v1.11.3` 延续 `verified + preview + experimental` 支持分层,并完成 v2 readiness 非实机 gate / fallback / exception 台账:v1.11.x 剩余 blocker 继续写成 burn-down 台账与降级策略,`v1.11.2` 的 ccnubox_rn signed simulator app-shell gate 作为既有证据保留;`doctor` 继续分类任意 Expo 项目、标出 blocker 类型并给出有序下一步;`expo55-rnoh082-ui-stack` 仍是唯一 verified 矩阵。
|
|
4
4
|
|
|
5
5
|
CLI 命令集合不变:
|
|
6
6
|
|
package/docs/npm-release.md
CHANGED
|
@@ -61,8 +61,10 @@ pnpm release:check
|
|
|
61
61
|
- hosted CI 默认仍可通过 `EXPO_HARMONY_RELEASE_SKIP_HAP=1` 跳过真实 DevEco HAP 构建
|
|
62
62
|
- debug / release HAP gate 继续由 capability acceptance、带工具链环境的 CI 或本地验收补齐
|
|
63
63
|
- `v1.11.0` 是未发布的 burn-down ledger checkpoint;`v1.11.1` 是第一个公开 `v1.11.x`,发布到 `latest` 只代表 sidecar drift 工具链行为收口,不代表 verified/capability 边界放宽
|
|
64
|
-
- `v1.11.2`
|
|
64
|
+
- `v1.11.2` 已完成非实机 closeout 与 ccnubox signed simulator app-shell gate,并已通过 tag/npm/GitHub Release 发布到 `latest`
|
|
65
|
+
- `v1.11.2` 远端状态:npm `latest -> 1.11.2`,npm `next -> 1.9.0`,GitHub Release `v1.11.2` 已建立
|
|
65
66
|
- `v1.11.2` 的 ccnubox signed simulator install/start 记录不替代真机 device acceptance,也不把 preview capability 标为 release-ready
|
|
67
|
+
- `v1.11.3` 当前只更新仓库代码与 v2 readiness 非实机台账;未创建 tag,未发布 npm,未创建 GitHub Release
|
|
66
68
|
- `v1.8.3` 只刷新 RNOH runtime / CLI 到 `0.82.29`,仍不宣称 RN `0.83.x` 已进入公开 Harmony 矩阵
|
|
67
69
|
- preview capability 若在报告里显示 `device=yes`,必须同时以 `evidenceSource.device=manual-doc` 对外说明其来源,不得表述成 CI 自动设备验证
|
|
68
70
|
|
package/docs/roadmap.md
CHANGED
|
@@ -252,7 +252,7 @@ Acceptance checklist:
|
|
|
252
252
|
|
|
253
253
|
目标日期:`2026-11-30`
|
|
254
254
|
|
|
255
|
-
状态:`v1.11.0` 是未发布的 burn-down ledger checkpoint;`v1.11.1` 是第一个公开 `v1.11.x`,发布到 `latest`,只收口 sidecar drift 工具链行为;`v1.11.2`
|
|
255
|
+
状态:`v1.11.0` 是未发布的 burn-down ledger checkpoint;`v1.11.1` 是第一个公开 `v1.11.x`,发布到 `latest`,只收口 sidecar drift 工具链行为;`v1.11.2` 已发布到 `latest`,完成非实机 closeout 与 ccnubox signed simulator app-shell gate;`v1.11.3` 更新仓库代码,完成 v2 readiness 非实机 gate / fallback / exception 台账,但不发布 tag/npm/GitHub Release,也不提升任何 capability 到 `verified`。
|
|
256
256
|
|
|
257
257
|
目标:把还会阻止“任何 Expo 项目可靠打包”的剩余高频 blocker 清到只剩极少数明确已知例外。
|
|
258
258
|
|
|
@@ -283,6 +283,7 @@ Acceptance checklist:
|
|
|
283
283
|
- 新增 `acceptance/v1.11.0-burn-down-ledger.md` 记录 v1.11.x 起始台账
|
|
284
284
|
- 新增 `acceptance/v1.11.1-acceptance.md` 记录第一个公开 v1.11.x release、`v1.11.0` 不发布决策与 sidecar drift 收口结果
|
|
285
285
|
- 更新 `acceptance/v1.11.2-acceptance.md` 记录非实机 closeout、ccnubox signed simulator app-shell gate、bare release gap 与 third-party fallback 策略
|
|
286
|
+
- 新增 `acceptance/v1.11.3-acceptance.md` 记录 v2 readiness 非实机 gate、fallback、exception 与公开边界
|
|
286
287
|
- 明确本阶段不改变 `latest` / `verified` 边界
|
|
287
288
|
- 不把 debug/release HAP build pass 表述为真机 device 或 runtime pass
|
|
288
289
|
- 对每个无法在 v1.11.x 关闭的 blocker 写出降级或替代路径
|
package/docs/support-matrix.md
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
- `v2.0.0` 本身被定义成“任何 Expo 项目都能可靠打包成鸿蒙 App”的目标版本
|
|
16
16
|
- 但当前公开承诺依旧没有放宽;它们只是进入同一主线 backlog,而不是已经进入 `verified`
|
|
17
17
|
- `v1.10.0` 已冻结 Any-project Intake:任何 Expo 项目进入 `doctor` 后都应有分类、明确 blocker 类型与有序 `nextActions`
|
|
18
|
-
- `v1.11.2`
|
|
18
|
+
- `v1.11.3` 已更新仓库代码,完成 v2 readiness 非实机 gate / fallback / exception 台账;`v1.11.2` 是当前已发布到 `latest` 的 tag/npm/GitHub Release,并完成非实机 closeout 与 ccnubox signed simulator app-shell gate;`v1.11.1` 是第一个公开 `v1.11.x`,只收口 sidecar drift 的可诊断行为;`v1.11.0` 保留为未发布的 burn-down ledger checkpoint
|
|
19
19
|
- 这不是 verified 扩容;`latest` 仍只承诺完整验收的 `verified` 能力,catalog 外项目只承诺可诊断路径
|
|
20
20
|
|
|
21
21
|
`doctor --strict` 继续只代表 `verified`。
|
|
@@ -250,7 +250,7 @@ toolkit 受管的核心产物仍包括:
|
|
|
250
250
|
|
|
251
251
|
## Release Tracks
|
|
252
252
|
|
|
253
|
-
从 `v1.8` 开始,发布节奏按双轨设计;`v1.11.
|
|
253
|
+
从 `v1.8` 开始,发布节奏按双轨设计;`v1.11.3` 继续沿用同一规则:
|
|
254
254
|
|
|
255
255
|
<!-- GENERATED:support-matrix-release-tracks:start -->
|
|
256
256
|
- `latest`
|
package/package.json
CHANGED
|
@@ -21,12 +21,12 @@ struct Index {
|
|
|
21
21
|
}
|
|
22
22
|
RNApp({
|
|
23
23
|
rnInstanceConfig: {
|
|
24
|
-
name: '{{
|
|
24
|
+
name: '{{APP_SLUG_ARKTS}}',
|
|
25
25
|
createRNPackages: getRNOHPackages,
|
|
26
26
|
fontResourceByFontFamily: {},
|
|
27
27
|
enableDebugger: this.rnohCoreContext?.isDebugModeEnabled,
|
|
28
28
|
},
|
|
29
|
-
appKey: '{{
|
|
29
|
+
appKey: '{{APP_SLUG_ARKTS}}',
|
|
30
30
|
jsBundleProvider: this.rnohCoreContext?.isDebugModeEnabled
|
|
31
31
|
? new AnyJSBundleProvider([
|
|
32
32
|
new MetroJSBundleProvider(),
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"string": [
|
|
3
3
|
{
|
|
4
4
|
"name": "module_desc",
|
|
5
|
-
"value":
|
|
5
|
+
"value": {{APP_DESCRIPTION_JSON}}
|
|
6
6
|
},
|
|
7
7
|
{
|
|
8
8
|
"name": "EntryAbility_desc",
|
|
9
|
-
"value":
|
|
9
|
+
"value": {{APP_DESCRIPTION_JSON}}
|
|
10
10
|
},
|
|
11
11
|
{
|
|
12
12
|
"name": "EntryAbility_label",
|
|
13
|
-
"value":
|
|
13
|
+
"value": {{APP_NAME_JSON}}
|
|
14
14
|
}
|
|
15
15
|
]
|
|
16
16
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
modelVersion: '5.0.0',
|
|
3
3
|
name: '{{BUNDLE_NAME}}',
|
|
4
|
-
version: '{{
|
|
5
|
-
description: '{{
|
|
4
|
+
version: '{{APP_VERSION_JSON5}}',
|
|
5
|
+
description: '{{APP_DESCRIPTION_JSON5}}',
|
|
6
6
|
dependencies: {},
|
|
7
7
|
devDependencies: {
|
|
8
8
|
'@ohos/hypium': '1.0.6',
|