openxiangda 1.0.4 → 1.0.6
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/package.json +1 -1
- package/packages/sdk/dist/runtime/index.cjs +84 -23
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.mjs +63 -2
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/src/build-source/scripts/build-forms.mjs +66 -13
- package/packages/sdk/src/build-source/scripts/publish-all.mjs +11 -2
- package/packages/sdk/src/build-source/scripts/utils/incremental.mjs +41 -9
- package/packages/sdk/src/build-source/scripts/utils/incremental.test.ts +78 -0
|
@@ -13,8 +13,9 @@ import minimist from "minimist";
|
|
|
13
13
|
import { rootDir } from "./utils/load-config.mjs";
|
|
14
14
|
import {
|
|
15
15
|
discoverWorkspaceModules,
|
|
16
|
+
commitIncrementalPublish,
|
|
16
17
|
normalizeOnly,
|
|
17
|
-
|
|
18
|
+
planIncrementalPublish,
|
|
18
19
|
printPlan,
|
|
19
20
|
} from "./utils/incremental.mjs";
|
|
20
21
|
|
|
@@ -99,7 +100,7 @@ const maybeDryRun = dryRun ? ["--dry-run"] : [];
|
|
|
99
100
|
const maybeForce = force ? ["--force"] : [];
|
|
100
101
|
|
|
101
102
|
const allModules = discoverWorkspaceModules();
|
|
102
|
-
const plan =
|
|
103
|
+
const plan = planIncrementalPublish(allModules, { force, only });
|
|
103
104
|
printPlan(plan, "publish-all");
|
|
104
105
|
if (plan.changed.length === 0 && !force) {
|
|
105
106
|
console.log("✅ 没有检测到变更,跳过发布");
|
|
@@ -110,18 +111,26 @@ console.log(`🚀 发布应用工作区 (${dryRun ? "DRY RUN" : "LIVE"})`);
|
|
|
110
111
|
console.log(` APP_BUILD_ID=${buildId}`);
|
|
111
112
|
console.log("");
|
|
112
113
|
|
|
114
|
+
const publishedModules = [];
|
|
115
|
+
|
|
113
116
|
for (const moduleItem of plan.changed) {
|
|
114
117
|
if (moduleItem.kind === "forms") {
|
|
115
118
|
await run("sync-schema.mjs", ["--form", moduleItem.name, ...maybeDryRun]);
|
|
116
119
|
await run("build-forms.mjs", ["--form", moduleItem.name, ...maybeForce]);
|
|
117
120
|
await run("publish-oss.mjs", ["--form", moduleItem.name, ...maybeDryRun]);
|
|
118
121
|
await run("register.mjs", ["--form", moduleItem.name, ...maybeDryRun]);
|
|
122
|
+
publishedModules.push(moduleItem);
|
|
119
123
|
} else if (moduleItem.kind === "pages") {
|
|
120
124
|
await run("build-pages.mjs", ["--page", moduleItem.name, ...maybeForce]);
|
|
121
125
|
await run("publish-oss.mjs", ["--page", moduleItem.name, ...maybeDryRun]);
|
|
122
126
|
await run("register.mjs", ["--page", moduleItem.name, ...maybeDryRun]);
|
|
127
|
+
publishedModules.push(moduleItem);
|
|
123
128
|
}
|
|
124
129
|
}
|
|
125
130
|
|
|
131
|
+
if (!dryRun) {
|
|
132
|
+
commitIncrementalPublish(plan, publishedModules);
|
|
133
|
+
}
|
|
134
|
+
|
|
126
135
|
console.log("");
|
|
127
136
|
console.log(`✅ 发布流程完成,buildId=${buildId}`);
|
|
@@ -5,6 +5,11 @@ import { rootDir } from "./load-config.mjs";
|
|
|
5
5
|
|
|
6
6
|
const CACHE_VERSION = 1;
|
|
7
7
|
export const CACHE_FILE = path.join(rootDir, ".openxiangda", "build-cache.json");
|
|
8
|
+
export const PUBLISH_CACHE_FILE = path.join(
|
|
9
|
+
rootDir,
|
|
10
|
+
".openxiangda",
|
|
11
|
+
"publish-cache.json",
|
|
12
|
+
);
|
|
8
13
|
|
|
9
14
|
function toPosix(filePath) {
|
|
10
15
|
return filePath.split(path.sep).join("/");
|
|
@@ -89,15 +94,23 @@ export function computeConfigHash() {
|
|
|
89
94
|
return hash.digest("hex");
|
|
90
95
|
}
|
|
91
96
|
|
|
92
|
-
|
|
97
|
+
function loadCache(cacheFile) {
|
|
93
98
|
try {
|
|
94
|
-
const cache = JSON.parse(fs.readFileSync(
|
|
99
|
+
const cache = JSON.parse(fs.readFileSync(cacheFile, "utf-8"));
|
|
95
100
|
return cache.version === CACHE_VERSION ? cache : null;
|
|
96
101
|
} catch {
|
|
97
102
|
return null;
|
|
98
103
|
}
|
|
99
104
|
}
|
|
100
105
|
|
|
106
|
+
export function loadBuildCache() {
|
|
107
|
+
return loadCache(CACHE_FILE);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function loadPublishCache() {
|
|
111
|
+
return loadCache(PUBLISH_CACHE_FILE);
|
|
112
|
+
}
|
|
113
|
+
|
|
101
114
|
export function cleanBuildCache() {
|
|
102
115
|
fs.rmSync(CACHE_FILE, { force: true });
|
|
103
116
|
}
|
|
@@ -111,7 +124,7 @@ export function normalizeOnly(value) {
|
|
|
111
124
|
.filter(Boolean);
|
|
112
125
|
}
|
|
113
126
|
|
|
114
|
-
|
|
127
|
+
function createIncrementalPlan(modules, options = {}, cache = null) {
|
|
115
128
|
const only = normalizeOnly(options.only);
|
|
116
129
|
const selected = only.length
|
|
117
130
|
? modules.filter((item) => only.includes(item.key))
|
|
@@ -125,7 +138,6 @@ export function planIncrementalBuild(modules, options = {}) {
|
|
|
125
138
|
configHash: computeConfigHash(),
|
|
126
139
|
moduleHashes,
|
|
127
140
|
};
|
|
128
|
-
const cache = loadBuildCache();
|
|
129
141
|
const fullRebuild =
|
|
130
142
|
Boolean(options.force) ||
|
|
131
143
|
!cache ||
|
|
@@ -145,6 +157,14 @@ export function planIncrementalBuild(modules, options = {}) {
|
|
|
145
157
|
};
|
|
146
158
|
}
|
|
147
159
|
|
|
160
|
+
export function planIncrementalBuild(modules, options = {}) {
|
|
161
|
+
return createIncrementalPlan(modules, options, loadBuildCache());
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export function planIncrementalPublish(modules, options = {}) {
|
|
165
|
+
return createIncrementalPlan(modules, options, loadPublishCache());
|
|
166
|
+
}
|
|
167
|
+
|
|
148
168
|
export function discoverWorkspaceModules() {
|
|
149
169
|
const modules = [];
|
|
150
170
|
for (const [kind, requiredFile] of [
|
|
@@ -168,24 +188,23 @@ export function discoverWorkspaceModules() {
|
|
|
168
188
|
return modules.sort((left, right) => left.key.localeCompare(right.key));
|
|
169
189
|
}
|
|
170
190
|
|
|
171
|
-
|
|
172
|
-
const previous = loadBuildCache();
|
|
191
|
+
function commitIncrementalCache(cacheFile, previous, plan, modules) {
|
|
173
192
|
const entries = { ...(previous?.entries || {}) };
|
|
174
193
|
const now = new Date().toISOString();
|
|
175
194
|
const isPartialBuild = plan.selected.length !== plan.all.length;
|
|
176
195
|
const preserveGlobalSnapshot = Boolean(
|
|
177
196
|
previous && isPartialBuild && plan.fullRebuild,
|
|
178
197
|
);
|
|
179
|
-
for (const item of
|
|
198
|
+
for (const item of modules) {
|
|
180
199
|
entries[item.key] = {
|
|
181
200
|
contentHash: plan.snapshot.moduleHashes[item.key],
|
|
182
201
|
lastBuildTime: now,
|
|
183
202
|
success: true,
|
|
184
203
|
};
|
|
185
204
|
}
|
|
186
|
-
fs.mkdirSync(path.dirname(
|
|
205
|
+
fs.mkdirSync(path.dirname(cacheFile), { recursive: true });
|
|
187
206
|
fs.writeFileSync(
|
|
188
|
-
|
|
207
|
+
cacheFile,
|
|
189
208
|
`${JSON.stringify(
|
|
190
209
|
{
|
|
191
210
|
version: CACHE_VERSION,
|
|
@@ -207,6 +226,19 @@ export function commitIncrementalBuild(plan, builtModules) {
|
|
|
207
226
|
);
|
|
208
227
|
}
|
|
209
228
|
|
|
229
|
+
export function commitIncrementalBuild(plan, builtModules) {
|
|
230
|
+
commitIncrementalCache(CACHE_FILE, loadBuildCache(), plan, builtModules);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function commitIncrementalPublish(plan, publishedModules) {
|
|
234
|
+
commitIncrementalCache(
|
|
235
|
+
PUBLISH_CACHE_FILE,
|
|
236
|
+
loadPublishCache(),
|
|
237
|
+
plan,
|
|
238
|
+
publishedModules,
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
210
242
|
export function printPlan(plan, label) {
|
|
211
243
|
if (plan.changed.length === 0) {
|
|
212
244
|
console.log(`[build] ${label}: No changes detected`);
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import os from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
|
|
5
|
+
import { afterEach, describe, expect, it, vi } from "vitest";
|
|
6
|
+
|
|
7
|
+
let tempDirs: string[] = [];
|
|
8
|
+
|
|
9
|
+
function createWorkspace() {
|
|
10
|
+
const dir = fs.mkdtempSync(path.join(os.tmpdir(), "workspace-incremental-"));
|
|
11
|
+
tempDirs.push(dir);
|
|
12
|
+
fs.mkdirSync(path.join(dir, "src", "pages", "dashboard"), {
|
|
13
|
+
recursive: true,
|
|
14
|
+
});
|
|
15
|
+
fs.writeFileSync(
|
|
16
|
+
path.join(dir, "package.json"),
|
|
17
|
+
JSON.stringify({ name: "test-workspace", dependencies: { openxiangda: "1.0.5" } }),
|
|
18
|
+
"utf-8",
|
|
19
|
+
);
|
|
20
|
+
fs.writeFileSync(path.join(dir, "pnpm-lock.yaml"), "lockfileVersion: 9.0\n", "utf-8");
|
|
21
|
+
fs.writeFileSync(
|
|
22
|
+
path.join(dir, "src", "pages", "dashboard", "page.config.ts"),
|
|
23
|
+
"export default { code: 'dashboard', name: 'Dashboard' };\n",
|
|
24
|
+
"utf-8",
|
|
25
|
+
);
|
|
26
|
+
fs.writeFileSync(
|
|
27
|
+
path.join(dir, "src", "pages", "dashboard", "index.tsx"),
|
|
28
|
+
"export default function Dashboard() { return null; }\n",
|
|
29
|
+
"utf-8",
|
|
30
|
+
);
|
|
31
|
+
return dir;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function loadIncremental(rootDir: string) {
|
|
35
|
+
const previousRoot = process.env.LOWCODE_WORKSPACE_ROOT;
|
|
36
|
+
process.env.LOWCODE_WORKSPACE_ROOT = rootDir;
|
|
37
|
+
vi.resetModules();
|
|
38
|
+
const module = await import("./incremental.mjs");
|
|
39
|
+
if (previousRoot === undefined) {
|
|
40
|
+
delete process.env.LOWCODE_WORKSPACE_ROOT;
|
|
41
|
+
} else {
|
|
42
|
+
process.env.LOWCODE_WORKSPACE_ROOT = previousRoot;
|
|
43
|
+
}
|
|
44
|
+
return module;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
afterEach(() => {
|
|
48
|
+
for (const dir of tempDirs) {
|
|
49
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
50
|
+
}
|
|
51
|
+
tempDirs = [];
|
|
52
|
+
vi.resetModules();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
describe("incremental publish cache", () => {
|
|
56
|
+
it("does not treat a local build cache entry as an already published module", async () => {
|
|
57
|
+
const workspaceRoot = createWorkspace();
|
|
58
|
+
const incremental = await loadIncremental(workspaceRoot);
|
|
59
|
+
const modules = incremental.discoverWorkspaceModules();
|
|
60
|
+
|
|
61
|
+
const buildPlan = incremental.planIncrementalBuild(modules);
|
|
62
|
+
expect(buildPlan.changed.map((item: any) => item.key)).toEqual([
|
|
63
|
+
"pages/dashboard",
|
|
64
|
+
]);
|
|
65
|
+
|
|
66
|
+
incremental.commitIncrementalBuild(buildPlan, buildPlan.changed);
|
|
67
|
+
|
|
68
|
+
expect(incremental.planIncrementalBuild(modules).changed).toHaveLength(0);
|
|
69
|
+
expect(incremental.planIncrementalPublish(modules).changed.map((item: any) => item.key)).toEqual([
|
|
70
|
+
"pages/dashboard",
|
|
71
|
+
]);
|
|
72
|
+
|
|
73
|
+
const publishPlan = incremental.planIncrementalPublish(modules);
|
|
74
|
+
incremental.commitIncrementalPublish(publishPlan, publishPlan.changed);
|
|
75
|
+
|
|
76
|
+
expect(incremental.planIncrementalPublish(modules).changed).toHaveLength(0);
|
|
77
|
+
});
|
|
78
|
+
});
|