@arcote.tech/arc-cli 0.8.2 → 0.8.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/dist/index.js +318 -41
- package/package.json +10 -10
- package/src/builder/chunk-planner.ts +14 -0
- package/src/builder/module-builder.ts +432 -30
- package/src/commands/platform-build.ts +6 -1
- package/src/deploy/caddyfile.ts +3 -0
- package/src/index.ts +6 -2
- package/src/platform/shared.ts +68 -21
- package/src/platform/startup.ts +17 -3
package/dist/index.js
CHANGED
|
@@ -31692,6 +31692,52 @@ function workspaceSourcePlugin(srcByName) {
|
|
|
31692
31692
|
}
|
|
31693
31693
|
};
|
|
31694
31694
|
}
|
|
31695
|
+
var SERVER_ONLY_NODE_BUILTINS = new Set([
|
|
31696
|
+
"crypto",
|
|
31697
|
+
"stream",
|
|
31698
|
+
"zlib",
|
|
31699
|
+
"fs",
|
|
31700
|
+
"fs/promises",
|
|
31701
|
+
"net",
|
|
31702
|
+
"tls",
|
|
31703
|
+
"http",
|
|
31704
|
+
"https",
|
|
31705
|
+
"http2",
|
|
31706
|
+
"dns",
|
|
31707
|
+
"dgram",
|
|
31708
|
+
"child_process",
|
|
31709
|
+
"worker_threads",
|
|
31710
|
+
"cluster",
|
|
31711
|
+
"os",
|
|
31712
|
+
"v8",
|
|
31713
|
+
"vm",
|
|
31714
|
+
"readline",
|
|
31715
|
+
"repl",
|
|
31716
|
+
"tty",
|
|
31717
|
+
"perf_hooks",
|
|
31718
|
+
"inspector",
|
|
31719
|
+
"async_hooks",
|
|
31720
|
+
"diagnostics_channel",
|
|
31721
|
+
"module",
|
|
31722
|
+
"constants"
|
|
31723
|
+
]);
|
|
31724
|
+
function nodeServerBuiltinStubPlugin() {
|
|
31725
|
+
return {
|
|
31726
|
+
name: "node-server-builtin-stub",
|
|
31727
|
+
setup(build2) {
|
|
31728
|
+
build2.onResolve({ filter: /^(node:)?[a-z_/]+$/ }, (args) => {
|
|
31729
|
+
const bare = args.path.replace(/^node:/, "");
|
|
31730
|
+
if (!SERVER_ONLY_NODE_BUILTINS.has(bare))
|
|
31731
|
+
return;
|
|
31732
|
+
return { path: args.path, namespace: "node-server-stub" };
|
|
31733
|
+
});
|
|
31734
|
+
build2.onLoad({ filter: /.*/, namespace: "node-server-stub" }, (args) => ({
|
|
31735
|
+
contents: `const e=()=>{throw new Error("Node builtin '${args.path}' jest server-only \u2014 niedost\u0119pny w przegl\u0105darce");};` + `module.exports=new Proxy({},{get:(_,p)=>p==="__esModule"?false:e});`,
|
|
31736
|
+
loader: "js"
|
|
31737
|
+
}));
|
|
31738
|
+
}
|
|
31739
|
+
};
|
|
31740
|
+
}
|
|
31695
31741
|
function jsxDevShimPlugin() {
|
|
31696
31742
|
return {
|
|
31697
31743
|
name: "jsx-dev-runtime-shim",
|
|
@@ -31813,7 +31859,10 @@ async function buildContextClient(pkg, rootDir, client, cache, noCache) {
|
|
|
31813
31859
|
format: "esm",
|
|
31814
31860
|
naming: "index.[ext]",
|
|
31815
31861
|
external: externals,
|
|
31816
|
-
plugins: [
|
|
31862
|
+
plugins: [
|
|
31863
|
+
jsxDevShimPlugin(),
|
|
31864
|
+
...client.target === "browser" ? [nodeServerBuiltinStubPlugin()] : []
|
|
31865
|
+
],
|
|
31817
31866
|
define: client.defines
|
|
31818
31867
|
});
|
|
31819
31868
|
if (!result.success) {
|
|
@@ -31926,7 +31975,6 @@ async function buildServerApp(rootDir, serverDir, packages, cache, noCache) {
|
|
|
31926
31975
|
try {
|
|
31927
31976
|
result = await Bun.build({
|
|
31928
31977
|
entrypoints: [entrySrc],
|
|
31929
|
-
outdir: serverDir,
|
|
31930
31978
|
target: "bun",
|
|
31931
31979
|
format: "esm",
|
|
31932
31980
|
splitting: true,
|
|
@@ -31955,6 +32003,9 @@ async function buildServerApp(rootDir, serverDir, packages, cache, noCache) {
|
|
|
31955
32003
|
if (basename3(entryOut.path) !== SERVER_ENTRY_FILE) {
|
|
31956
32004
|
throw new Error(`Server app build: unexpected entry name ${basename3(entryOut.path)} (wanted ${SERVER_ENTRY_FILE})`);
|
|
31957
32005
|
}
|
|
32006
|
+
for (const out of result.outputs) {
|
|
32007
|
+
writeFileSync7(join9(serverDir, basename3(out.path)), new Uint8Array(await out.arrayBuffer()));
|
|
32008
|
+
}
|
|
31958
32009
|
const externals = [...recorded].filter(([name]) => !FRAMEWORK_PEER_SET.has(name)).map(([name, version]) => ({ name, version })).sort((a, b) => a.name.localeCompare(b.name));
|
|
31959
32010
|
writeFileSync7(externalsFileAbs, JSON.stringify(externals, null, 2) + `
|
|
31960
32011
|
`);
|
|
@@ -31972,9 +32023,141 @@ function readServerExternals(path4) {
|
|
|
31972
32023
|
return [];
|
|
31973
32024
|
}
|
|
31974
32025
|
}
|
|
32026
|
+
function buildStatsEnabled() {
|
|
32027
|
+
return process.env.ARC_BUILD_STATS === "1";
|
|
32028
|
+
}
|
|
32029
|
+
function classifySource(src) {
|
|
32030
|
+
const nm = src.lastIndexOf("node_modules/");
|
|
32031
|
+
if (nm >= 0) {
|
|
32032
|
+
const rest = src.slice(nm + "node_modules/".length);
|
|
32033
|
+
const parts = rest.split("/");
|
|
32034
|
+
const pkg = parts[0].startsWith("@") ? `${parts[0]}/${parts[1]}` : parts[0];
|
|
32035
|
+
const external = !pkg.startsWith("@ndt/") && !pkg.startsWith("@arcote.tech/");
|
|
32036
|
+
return { pkg, external };
|
|
32037
|
+
}
|
|
32038
|
+
const m = src.match(/(?:^|\/)packages\/([^/]+)\//);
|
|
32039
|
+
if (m)
|
|
32040
|
+
return { pkg: `packages/${m[1]}`, external: false };
|
|
32041
|
+
return { pkg: src.split("/").slice(0, 2).join("/") || src, external: false };
|
|
32042
|
+
}
|
|
32043
|
+
function chunkPkgWeights(map) {
|
|
32044
|
+
const acc = new Map;
|
|
32045
|
+
const sources = map.sources ?? [];
|
|
32046
|
+
const contents = map.sourcesContent ?? [];
|
|
32047
|
+
for (let i = 0;i < sources.length; i++) {
|
|
32048
|
+
const bytes = contents[i]?.length ?? 0;
|
|
32049
|
+
const { pkg, external } = classifySource(sources[i]);
|
|
32050
|
+
const cur = acc.get(pkg) ?? { pkg, bytes: 0, external };
|
|
32051
|
+
cur.bytes += bytes;
|
|
32052
|
+
acc.set(pkg, cur);
|
|
32053
|
+
}
|
|
32054
|
+
return [...acc.values()].sort((a, b) => b.bytes - a.bytes);
|
|
32055
|
+
}
|
|
32056
|
+
var kb = (n) => `${Math.round(n / 1024)} KB`;
|
|
32057
|
+
function stripTrailingSourcemapComment(bytes) {
|
|
32058
|
+
let text = Buffer.from(bytes).toString("utf8");
|
|
32059
|
+
text = text.replace(/\n*\/\/# (?:debugId|sourceMappingURL)=[^\n]*\s*$/, "");
|
|
32060
|
+
if (!text.endsWith(`
|
|
32061
|
+
`))
|
|
32062
|
+
text += `
|
|
32063
|
+
`;
|
|
32064
|
+
return new Uint8Array(Buffer.from(text, "utf8"));
|
|
32065
|
+
}
|
|
32066
|
+
function reportBrowserBuildStats(opts) {
|
|
32067
|
+
const { label, entries, jsByName, mapsByJs } = opts;
|
|
32068
|
+
const staticEdge = /(?:^|[;}\s])import\s*["'](\.\/[^"']+\.js)["']|from\s*["'](\.\/[^"']+\.js)["']/g;
|
|
32069
|
+
const staticImports = (name) => {
|
|
32070
|
+
const bytes = jsByName.get(name);
|
|
32071
|
+
if (!bytes)
|
|
32072
|
+
return [];
|
|
32073
|
+
const s = Buffer.from(bytes).toString("utf8");
|
|
32074
|
+
const out = [];
|
|
32075
|
+
let m;
|
|
32076
|
+
staticEdge.lastIndex = 0;
|
|
32077
|
+
while (m = staticEdge.exec(s))
|
|
32078
|
+
out.push(basename3(m[1] ?? m[2]));
|
|
32079
|
+
return out;
|
|
32080
|
+
};
|
|
32081
|
+
const closure = (start) => {
|
|
32082
|
+
const seen = new Set;
|
|
32083
|
+
const stack = [start];
|
|
32084
|
+
while (stack.length) {
|
|
32085
|
+
const f = stack.pop();
|
|
32086
|
+
if (seen.has(f) || !jsByName.has(f))
|
|
32087
|
+
continue;
|
|
32088
|
+
seen.add(f);
|
|
32089
|
+
stack.push(...staticImports(f));
|
|
32090
|
+
}
|
|
32091
|
+
return seen;
|
|
32092
|
+
};
|
|
32093
|
+
const gz = (bytes) => Bun.gzipSync(bytes, { level: 6 }).length;
|
|
32094
|
+
console.log(`
|
|
32095
|
+
\u2501\u2501\u2501\u2501\u2501 Build stats: ${label} \u2501\u2501\u2501\u2501\u2501`);
|
|
32096
|
+
const globalExt = new Map;
|
|
32097
|
+
for (const entry of entries) {
|
|
32098
|
+
const files = closure(entry.file);
|
|
32099
|
+
let raw = 0;
|
|
32100
|
+
let gzip = 0;
|
|
32101
|
+
const pkgAcc = new Map;
|
|
32102
|
+
for (const f of files) {
|
|
32103
|
+
const bytes = jsByName.get(f);
|
|
32104
|
+
raw += bytes.length;
|
|
32105
|
+
gzip += gz(bytes);
|
|
32106
|
+
const map = mapsByJs.get(f);
|
|
32107
|
+
if (!map)
|
|
32108
|
+
continue;
|
|
32109
|
+
for (const w of chunkPkgWeights(map)) {
|
|
32110
|
+
const cur = pkgAcc.get(w.pkg) ?? { pkg: w.pkg, bytes: 0, external: w.external };
|
|
32111
|
+
cur.bytes += w.bytes;
|
|
32112
|
+
pkgAcc.set(w.pkg, cur);
|
|
32113
|
+
if (w.external) {
|
|
32114
|
+
const g = globalExt.get(w.pkg) ?? { bytes: 0, chunks: new Set, entries: new Set };
|
|
32115
|
+
g.bytes = Math.max(g.bytes, w.bytes);
|
|
32116
|
+
g.chunks.add(f);
|
|
32117
|
+
g.entries.add(entry.name);
|
|
32118
|
+
globalExt.set(w.pkg, g);
|
|
32119
|
+
}
|
|
32120
|
+
}
|
|
32121
|
+
}
|
|
32122
|
+
const top = [...pkgAcc.values()].sort((a, b) => b.bytes - a.bytes).slice(0, 10);
|
|
32123
|
+
console.log(`
|
|
32124
|
+
\u25B8 ${entry.name}: pierwsze wczytanie ${kb(raw)} raw / ${kb(gzip)} gzip (${files.size} plik\xF3w)`);
|
|
32125
|
+
for (const w of top) {
|
|
32126
|
+
const tag = w.external ? "ext" : "wewn";
|
|
32127
|
+
console.log(` ${kb(w.bytes).padStart(8)} [${tag}] ${w.pkg}`);
|
|
32128
|
+
}
|
|
32129
|
+
}
|
|
32130
|
+
const heaviest = [...globalExt.entries()].sort((a, b) => b[1].bytes - a[1].bytes).slice(0, 15);
|
|
32131
|
+
if (heaviest.length) {
|
|
32132
|
+
console.log(`
|
|
32133
|
+
\u25B8 Najci\u0119\u017Csze biblioteki ZEWN\u0118TRZNE (\u017Ar\xF3d\u0142a) i gdzie l\u0105duj\u0105:`);
|
|
32134
|
+
for (const [pkg, g] of heaviest) {
|
|
32135
|
+
console.log(` ${kb(g.bytes).padStart(8)} ${pkg} \u2192 ${[...g.entries].join(", ")}`);
|
|
32136
|
+
}
|
|
32137
|
+
}
|
|
32138
|
+
console.log(`
|
|
32139
|
+
\u2501\u2501\u2501\u2501\u2501 koniec stats: ${label} \u2501\u2501\u2501\u2501\u2501
|
|
32140
|
+
`);
|
|
32141
|
+
}
|
|
32142
|
+
function looksMinified(files) {
|
|
32143
|
+
for (const f of files) {
|
|
32144
|
+
if (!f.name.endsWith(".js") || f.bytes.length < 16 * 1024)
|
|
32145
|
+
continue;
|
|
32146
|
+
const sample = f.bytes.subarray(0, 64 * 1024);
|
|
32147
|
+
let newlines = 0;
|
|
32148
|
+
for (const b of sample)
|
|
32149
|
+
if (b === 10)
|
|
32150
|
+
newlines++;
|
|
32151
|
+
const avgLineLen = sample.length / Math.max(1, newlines);
|
|
32152
|
+
if (avgLineLen < 200)
|
|
32153
|
+
return false;
|
|
32154
|
+
}
|
|
32155
|
+
return true;
|
|
32156
|
+
}
|
|
31975
32157
|
async function buildBrowserApp(rootDir, outDir, plan, cache, noCache, i18nCollector, opts) {
|
|
31976
32158
|
const federated = opts?.federated ?? false;
|
|
31977
32159
|
const exposeRuntime = opts?.exposeRuntime ?? false;
|
|
32160
|
+
const minify = opts?.minify ?? true;
|
|
31978
32161
|
mkdirSync7(outDir, { recursive: true });
|
|
31979
32162
|
const publicMembers = plan.groups.get("public") ?? [];
|
|
31980
32163
|
const protectedGroups = plan.chunks.filter((c) => c !== "public").map((c) => ({ name: c, members: plan.groups.get(c) ?? [] })).filter((g) => g.members.length > 0);
|
|
@@ -31997,10 +32180,11 @@ async function buildBrowserApp(rootDir, outDir, plan, cache, noCache, i18nCollec
|
|
|
31997
32180
|
define: { ONLY_SERVER: "false", ONLY_BROWSER: "true", ONLY_CLIENT: "true" },
|
|
31998
32181
|
federated,
|
|
31999
32182
|
exposeRuntime,
|
|
32183
|
+
minify,
|
|
32000
32184
|
externals: federated ? [...SHELL_EXTERNALS] : [],
|
|
32001
32185
|
builderRev: 3
|
|
32002
32186
|
});
|
|
32003
|
-
if (!noCache && isCacheHit(cache, unitId, inputHash)) {
|
|
32187
|
+
if (!noCache && !buildStatsEnabled() && isCacheHit(cache, unitId, inputHash)) {
|
|
32004
32188
|
const cached = cache.units[unitId]?.outputHashes;
|
|
32005
32189
|
if (cached?._manifest) {
|
|
32006
32190
|
try {
|
|
@@ -32024,24 +32208,27 @@ async function buildBrowserApp(rootDir, outDir, plan, cache, noCache, i18nCollec
|
|
|
32024
32208
|
rmSync3(join9(outDir, f), { force: true });
|
|
32025
32209
|
}
|
|
32026
32210
|
}
|
|
32027
|
-
const tmpDir = join9(
|
|
32028
|
-
mkdirSync7(tmpDir, { recursive: true });
|
|
32211
|
+
const tmpDir = join9(rootDir, ".arc", "tmp", `entries-${unitId}`);
|
|
32029
32212
|
const importLines = (pkgs) => pkgs.map((m) => `import "${m.pkg.name}";`).join(`
|
|
32030
32213
|
`);
|
|
32031
32214
|
const initialEntry = join9(tmpDir, "initial.ts");
|
|
32032
|
-
writeFileSync7(initialEntry, (exposeRuntime ? runtimeExposePrelude() + `
|
|
32033
|
-
` : "") + `${importLines(publicMembers)}
|
|
32034
|
-
export { startApp } from "@arcote.tech/platform";
|
|
32035
|
-
`);
|
|
32036
32215
|
const entryPaths = [initialEntry];
|
|
32037
32216
|
const groupModuleMap = new Map;
|
|
32038
32217
|
for (const g of protectedGroups) {
|
|
32039
|
-
|
|
32040
|
-
writeFileSync7(entry, `${importLines(g.members)}
|
|
32041
|
-
`);
|
|
32042
|
-
entryPaths.push(entry);
|
|
32218
|
+
entryPaths.push(join9(tmpDir, `${g.name}.ts`));
|
|
32043
32219
|
groupModuleMap.set(g.name, g.members.map((m) => m.moduleName));
|
|
32044
32220
|
}
|
|
32221
|
+
const writeEntryFiles = () => {
|
|
32222
|
+
mkdirSync7(tmpDir, { recursive: true });
|
|
32223
|
+
writeFileSync7(initialEntry, (exposeRuntime ? runtimeExposePrelude() + `
|
|
32224
|
+
` : "") + `${importLines(publicMembers)}
|
|
32225
|
+
export { startApp } from "@arcote.tech/platform";
|
|
32226
|
+
`);
|
|
32227
|
+
for (const g of protectedGroups) {
|
|
32228
|
+
writeFileSync7(join9(tmpDir, `${g.name}.ts`), `${importLines(g.members)}
|
|
32229
|
+
`);
|
|
32230
|
+
}
|
|
32231
|
+
};
|
|
32045
32232
|
const allMemberPkgs = new Map;
|
|
32046
32233
|
for (const m of publicMembers)
|
|
32047
32234
|
allMemberPkgs.set(m.pkg.name, m.pkg);
|
|
@@ -32062,11 +32249,13 @@ export { startApp } from "@arcote.tech/platform";
|
|
|
32062
32249
|
`);
|
|
32063
32250
|
patchedPkgJsons.push({ path: pkgJsonPath, original });
|
|
32064
32251
|
}
|
|
32252
|
+
const statsMode = buildStatsEnabled();
|
|
32253
|
+
const mapsByJs = new Map;
|
|
32065
32254
|
let result;
|
|
32066
|
-
|
|
32067
|
-
|
|
32255
|
+
const runBuild = () => {
|
|
32256
|
+
writeEntryFiles();
|
|
32257
|
+
return Bun.build({
|
|
32068
32258
|
entrypoints: entryPaths,
|
|
32069
|
-
outdir: outDir,
|
|
32070
32259
|
splitting: true,
|
|
32071
32260
|
format: "esm",
|
|
32072
32261
|
target: "browser",
|
|
@@ -32074,9 +32263,12 @@ export { startApp } from "@arcote.tech/platform";
|
|
|
32074
32263
|
plugins: [
|
|
32075
32264
|
...federated ? [] : [singleReactPlugin(rootDir)],
|
|
32076
32265
|
jsxDevShimPlugin(),
|
|
32266
|
+
nodeServerBuiltinStubPlugin(),
|
|
32077
32267
|
i18nExtractPlugin(i18nCollector, rootDir)
|
|
32078
32268
|
],
|
|
32079
32269
|
naming: "[name].[ext]",
|
|
32270
|
+
minify,
|
|
32271
|
+
sourcemap: statsMode ? "external" : "none",
|
|
32080
32272
|
define: {
|
|
32081
32273
|
ONLY_SERVER: "false",
|
|
32082
32274
|
ONLY_BROWSER: "true",
|
|
@@ -32084,12 +32276,46 @@ export { startApp } from "@arcote.tech/platform";
|
|
|
32084
32276
|
"process.env.NODE_ENV": '"production"'
|
|
32085
32277
|
}
|
|
32086
32278
|
});
|
|
32279
|
+
};
|
|
32280
|
+
let outFiles = null;
|
|
32281
|
+
try {
|
|
32282
|
+
for (let attempt = 1;; attempt++) {
|
|
32283
|
+
result = await runBuild();
|
|
32284
|
+
if (result.success) {
|
|
32285
|
+
const files = [];
|
|
32286
|
+
mapsByJs.clear();
|
|
32287
|
+
for (const out of result.outputs) {
|
|
32288
|
+
const name = basename3(out.path);
|
|
32289
|
+
if (name.endsWith(".map")) {
|
|
32290
|
+
try {
|
|
32291
|
+
mapsByJs.set(name.replace(/\.map$/, ""), JSON.parse(await out.text()));
|
|
32292
|
+
} catch {}
|
|
32293
|
+
continue;
|
|
32294
|
+
}
|
|
32295
|
+
let bytes = new Uint8Array(await out.arrayBuffer());
|
|
32296
|
+
if (statsMode && name.endsWith(".js")) {
|
|
32297
|
+
bytes = stripTrailingSourcemapComment(bytes);
|
|
32298
|
+
}
|
|
32299
|
+
files.push({ kind: out.kind, name, bytes });
|
|
32300
|
+
}
|
|
32301
|
+
if (!minify || looksMinified(files)) {
|
|
32302
|
+
outFiles = files;
|
|
32303
|
+
break;
|
|
32304
|
+
}
|
|
32305
|
+
}
|
|
32306
|
+
if (attempt >= 3) {
|
|
32307
|
+
if (!result.success)
|
|
32308
|
+
break;
|
|
32309
|
+
throw new Error("Browser app build: output NIEZMINIFIKOWANY mimo minify:true (3 pr\xF3by). Przerwane, \u017Ceby nie wypu\u015Bci\u0107 ci\u0119\u017Ckich bundli.");
|
|
32310
|
+
}
|
|
32311
|
+
console.warn(` ! browser build pass ${attempt} ${result.success ? "niezminifikowany mimo minify:true (wy\u015Bcig minify Bun.build)" : "nieudany (wy\u015Bcig Bun.build \u2014 np. znikni\u0119te pliki entry)"} \u2014 powtarzam`);
|
|
32312
|
+
}
|
|
32087
32313
|
} finally {
|
|
32088
32314
|
for (const p of patchedPkgJsons)
|
|
32089
32315
|
writeFileSync7(p.path, p.original);
|
|
32090
32316
|
}
|
|
32091
32317
|
rmSync3(tmpDir, { recursive: true, force: true });
|
|
32092
|
-
if (!result.success) {
|
|
32318
|
+
if (!result.success || !outFiles) {
|
|
32093
32319
|
for (const log2 of result.logs)
|
|
32094
32320
|
console.error(log2);
|
|
32095
32321
|
throw new Error("Browser app build failed");
|
|
@@ -32098,17 +32324,12 @@ export { startApp } from "@arcote.tech/platform";
|
|
|
32098
32324
|
let initialHash = "";
|
|
32099
32325
|
const groups = {};
|
|
32100
32326
|
const sharedChunks = [];
|
|
32101
|
-
for (const out of
|
|
32102
|
-
const name = basename3(out.path);
|
|
32327
|
+
for (const out of outFiles) {
|
|
32103
32328
|
if (out.kind === "entry-point") {
|
|
32104
|
-
const
|
|
32105
|
-
const
|
|
32106
|
-
const stem = name.replace(/\.js$/, "");
|
|
32329
|
+
const hash = sha256Hex(out.bytes).slice(0, 16);
|
|
32330
|
+
const stem = out.name.replace(/\.js$/, "");
|
|
32107
32331
|
const finalName = `${stem}.${hash}.js`;
|
|
32108
|
-
|
|
32109
|
-
rmSync3(finalPath, { force: true });
|
|
32110
|
-
writeFileSync7(finalPath, bytes);
|
|
32111
|
-
rmSync3(out.path, { force: true });
|
|
32332
|
+
writeFileSync7(join9(outDir, finalName), out.bytes);
|
|
32112
32333
|
if (stem === "initial") {
|
|
32113
32334
|
initialFile = finalName;
|
|
32114
32335
|
initialHash = hash;
|
|
@@ -32120,18 +32341,56 @@ export { startApp } from "@arcote.tech/platform";
|
|
|
32120
32341
|
};
|
|
32121
32342
|
}
|
|
32122
32343
|
} else if (out.kind === "chunk") {
|
|
32123
|
-
|
|
32344
|
+
writeFileSync7(join9(outDir, out.name), out.bytes);
|
|
32345
|
+
sharedChunks.push(out.name);
|
|
32124
32346
|
}
|
|
32125
32347
|
}
|
|
32126
32348
|
if (!initialFile) {
|
|
32127
32349
|
throw new Error("Browser app build: initial entry not found in outputs");
|
|
32128
32350
|
}
|
|
32351
|
+
const written = new Map;
|
|
32352
|
+
for (const out of outFiles) {
|
|
32353
|
+
const name = out.kind === "entry-point" ? `${out.name.replace(/\.js$/, "")}.${sha256Hex(out.bytes).slice(0, 16)}.js` : out.name;
|
|
32354
|
+
if (out.kind === "entry-point" || out.kind === "chunk") {
|
|
32355
|
+
written.set(name, sha256Hex(out.bytes));
|
|
32356
|
+
}
|
|
32357
|
+
}
|
|
32358
|
+
for (const f of readdirSync4(outDir)) {
|
|
32359
|
+
if (!f.endsWith(".js"))
|
|
32360
|
+
continue;
|
|
32361
|
+
const expected = written.get(f);
|
|
32362
|
+
const actual = sha256Hex(readFileSync8(join9(outDir, f)));
|
|
32363
|
+
if (!expected || expected !== actual) {
|
|
32364
|
+
throw new Error(`Browser app build: plik "${f}" w ${outDir} nie zgadza si\u0119 z artefaktami builda ` + `(${expected ? "tre\u015B\u0107 rozjechana z zapisem" : "obcy plik \u2014 co\u015B innego pisze do outDir"}). ` + `Przerwane, \u017Ceby nie wypu\u015Bci\u0107 niesp\xF3jnego builda.`);
|
|
32365
|
+
}
|
|
32366
|
+
}
|
|
32129
32367
|
const manifest = {
|
|
32130
32368
|
initial: { file: initialFile, hash: initialHash },
|
|
32131
32369
|
groups,
|
|
32132
32370
|
sharedChunks,
|
|
32133
32371
|
cached: false
|
|
32134
32372
|
};
|
|
32373
|
+
if (statsMode) {
|
|
32374
|
+
const jsByName = new Map;
|
|
32375
|
+
const mapsByFinal = new Map;
|
|
32376
|
+
const finalNameOf = (out) => out.kind === "entry-point" ? `${out.name.replace(/\.js$/, "")}.${sha256Hex(out.bytes).slice(0, 16)}.js` : out.name;
|
|
32377
|
+
for (const out of outFiles) {
|
|
32378
|
+
const fn = finalNameOf(out);
|
|
32379
|
+
jsByName.set(fn, out.bytes);
|
|
32380
|
+
const map = mapsByJs.get(out.name);
|
|
32381
|
+
if (map)
|
|
32382
|
+
mapsByFinal.set(fn, map);
|
|
32383
|
+
}
|
|
32384
|
+
reportBrowserBuildStats({
|
|
32385
|
+
label: federated ? "browser-fed" : "browser",
|
|
32386
|
+
entries: [
|
|
32387
|
+
{ name: "initial", file: initialFile },
|
|
32388
|
+
...Object.entries(groups).map(([stem, g]) => ({ name: stem, file: g.file }))
|
|
32389
|
+
],
|
|
32390
|
+
jsByName,
|
|
32391
|
+
mapsByJs: mapsByFinal
|
|
32392
|
+
});
|
|
32393
|
+
}
|
|
32135
32394
|
updateCache(cache, unitId, inputHash, {
|
|
32136
32395
|
outputHashes: { _manifest: JSON.stringify(manifest) }
|
|
32137
32396
|
});
|
|
@@ -32433,6 +32692,11 @@ function collectModuleNames(dir, acc) {
|
|
|
32433
32692
|
}
|
|
32434
32693
|
}
|
|
32435
32694
|
}
|
|
32695
|
+
function packageDeclaresModule(pkg) {
|
|
32696
|
+
const names = new Set;
|
|
32697
|
+
collectModuleNames(join11(pkg.path, "src"), names);
|
|
32698
|
+
return names.size > 0;
|
|
32699
|
+
}
|
|
32436
32700
|
function assertOneModulePerPackage(packages) {
|
|
32437
32701
|
const offenders = [];
|
|
32438
32702
|
for (const pkg of packages) {
|
|
@@ -32623,6 +32887,7 @@ function resolveWorkspace() {
|
|
|
32623
32887
|
async function buildAll(ws, opts = {}) {
|
|
32624
32888
|
const cache = loadBuildCache(ws.arcDir);
|
|
32625
32889
|
const noCache = opts.noCache ?? false;
|
|
32890
|
+
const minify = opts.minify ?? true;
|
|
32626
32891
|
const themePath = ws.rootPkg.arc?.theme;
|
|
32627
32892
|
const federation = getFederationConfig(ws);
|
|
32628
32893
|
log2(`Building (concurrency parallel${noCache ? ", no-cache" : ""})...`);
|
|
@@ -32637,8 +32902,9 @@ async function buildAll(ws, opts = {}) {
|
|
|
32637
32902
|
const isHost = Boolean(federation?.host);
|
|
32638
32903
|
const moduleNameOf2 = (name) => name.split("/").pop() ?? name;
|
|
32639
32904
|
const exposureOf = (pkgName) => accessMap.exposure[moduleNameOf2(pkgName)]?.exposure ?? "local";
|
|
32640
|
-
const
|
|
32641
|
-
const
|
|
32905
|
+
const modulePackages = ws.packages.filter(packageDeclaresModule);
|
|
32906
|
+
const localPackages = isHost ? modulePackages : modulePackages.filter((p) => exposureOf(p.name) !== "external");
|
|
32907
|
+
const fedPackages = modulePackages.filter((p) => ["external", "both"].includes(exposureOf(p.name)));
|
|
32642
32908
|
const hasFederatedModules = fedPackages.length > 0;
|
|
32643
32909
|
const needsPeerShell = isHost || hasFederatedModules;
|
|
32644
32910
|
log2();
|
|
@@ -32649,16 +32915,17 @@ async function buildAll(ws, opts = {}) {
|
|
|
32649
32915
|
ok(`Federated modules: ${fedPackages.map((p) => moduleNameOf2(p.name)).join(", ")}`);
|
|
32650
32916
|
}
|
|
32651
32917
|
const i18nCollector = new Map;
|
|
32652
|
-
const
|
|
32653
|
-
buildBrowserApp(ws.rootDir, ws.browserDir, plan, cache, noCache, i18nCollector, {
|
|
32654
|
-
|
|
32655
|
-
|
|
32656
|
-
|
|
32918
|
+
const browserSequence = (async () => {
|
|
32919
|
+
const bundled = await buildBrowserApp(ws.rootDir, ws.browserDir, plan, cache, noCache, i18nCollector, { federated: false, exposeRuntime: isHost, minify });
|
|
32920
|
+
const fed = fedPlan ? await buildBrowserApp(ws.rootDir, join13(ws.arcDir, "browser-fed"), fedPlan, cache, noCache, i18nCollector, { federated: true, unitId: "browser-app-fed", minify }) : undefined;
|
|
32921
|
+
return { bundled, fed };
|
|
32922
|
+
})();
|
|
32923
|
+
const [{ bundled: browserResult, fed: fedResult }, , , , shellResult] = await Promise.all([
|
|
32924
|
+
browserSequence,
|
|
32657
32925
|
buildStyles(ws.rootDir, ws.arcDir, ws.packages, themePath, cache, noCache),
|
|
32658
32926
|
copyBrowserAssets(ws, cache, noCache),
|
|
32659
32927
|
buildTranslations(ws.rootDir, ws.arcDir, cache, noCache),
|
|
32660
|
-
needsPeerShell ? buildPeerShell(ws.rootDir, join13(ws.arcDir, "shell"), cache, noCache) : Promise.resolve(undefined)
|
|
32661
|
-
fedPlan ? buildBrowserApp(ws.rootDir, join13(ws.arcDir, "browser-fed"), fedPlan, cache, noCache, i18nCollector, { federated: true, unitId: "browser-app-fed" }) : Promise.resolve(undefined)
|
|
32928
|
+
needsPeerShell ? buildPeerShell(ws.rootDir, join13(ws.arcDir, "shell"), cache, noCache) : Promise.resolve(undefined)
|
|
32662
32929
|
]);
|
|
32663
32930
|
const { finalizeTranslations: finalizeTranslations3 } = await Promise.resolve().then(() => (init_i18n(), exports_i18n));
|
|
32664
32931
|
await finalizeTranslations3(ws.rootDir, ws.arcDir, i18nCollector);
|
|
@@ -32806,20 +33073,25 @@ async function loadServerContext(ws) {
|
|
|
32806
33073
|
if (!existsSync11(serverEntry)) {
|
|
32807
33074
|
return { context: null, moduleAccess: new Map };
|
|
32808
33075
|
}
|
|
33076
|
+
let serverError;
|
|
32809
33077
|
try {
|
|
32810
33078
|
await import(serverEntry);
|
|
32811
33079
|
} catch (e) {
|
|
32812
33080
|
err(`Failed to load server bundle ${SERVER_ENTRY_FILE}: ${e}`);
|
|
33081
|
+
serverError = e;
|
|
32813
33082
|
}
|
|
32814
33083
|
const { getContext, getAllModuleAccess } = await import(platformEntry);
|
|
32815
33084
|
return {
|
|
32816
33085
|
context: getContext() ?? null,
|
|
32817
|
-
moduleAccess: getAllModuleAccess()
|
|
33086
|
+
moduleAccess: getAllModuleAccess(),
|
|
33087
|
+
serverError
|
|
32818
33088
|
};
|
|
32819
33089
|
}
|
|
32820
33090
|
|
|
32821
33091
|
// src/commands/platform-build.ts
|
|
32822
33092
|
async function platformBuild(opts = {}) {
|
|
33093
|
+
if (opts.stats)
|
|
33094
|
+
process.env.ARC_BUILD_STATS = "1";
|
|
32823
33095
|
const ws = resolveWorkspace();
|
|
32824
33096
|
const manifest = await buildAll(ws, { noCache: opts.noCache });
|
|
32825
33097
|
const groupCount = Object.keys(manifest.groups).length;
|
|
@@ -33247,6 +33519,7 @@ function generateCaddyfile(cfg) {
|
|
|
33247
33519
|
for (const [name, env2] of Object.entries(cfg.envs)) {
|
|
33248
33520
|
lines.push(`${env2.domain} {${tlsDirective}`);
|
|
33249
33521
|
lines.push(...logDirective);
|
|
33522
|
+
lines.push(" encode zstd gzip");
|
|
33250
33523
|
if (observability) {
|
|
33251
33524
|
lines.push(" handle_path /otel/* {");
|
|
33252
33525
|
lines.push(" reverse_proxy otel-collector:4318");
|
|
@@ -39025,7 +39298,7 @@ async function startPlatform(opts) {
|
|
|
39025
39298
|
const dbPath = opts.dbPath ?? join23(ws.rootDir, ".arc", "data", devMode ? "dev.db" : "prod.db");
|
|
39026
39299
|
let manifest;
|
|
39027
39300
|
if (devMode) {
|
|
39028
|
-
manifest = await buildAll(ws);
|
|
39301
|
+
manifest = await buildAll(ws, { minify: false });
|
|
39029
39302
|
} else {
|
|
39030
39303
|
const manifestPath = join23(ws.arcDir, "manifest.json");
|
|
39031
39304
|
if (!existsSync20(manifestPath)) {
|
|
@@ -39041,7 +39314,11 @@ async function startPlatform(opts) {
|
|
|
39041
39314
|
process.env.ARC_APP_SECRET = resolveAppSecret(ws.rootDir);
|
|
39042
39315
|
}
|
|
39043
39316
|
log2("Loading server context...");
|
|
39044
|
-
const { context: context2, moduleAccess } = await loadServerContext(ws);
|
|
39317
|
+
const { context: context2, moduleAccess, serverError } = await loadServerContext(ws);
|
|
39318
|
+
if (serverError) {
|
|
39319
|
+
err("Serwer NIE wstanie: modu\u0142 serwerowy nie za\u0142adowa\u0142 si\u0119 (b\u0142\u0105d wy\u017Cej). " + "Cz\u0119\u015Bciowy kontekst = po\u0142owiczna aplikacja (query rzucaj\u0105 " + "'Element not found'). Napraw przyczyn\u0119 (np. brakuj\u0105ce zmienne " + "\u015Brodowiskowe) i wystartuj ponownie.");
|
|
39320
|
+
process.exit(1);
|
|
39321
|
+
}
|
|
39045
39322
|
if (context2) {
|
|
39046
39323
|
ok("Context loaded");
|
|
39047
39324
|
} else {
|
|
@@ -39207,7 +39484,7 @@ function attachDevWatcher(ws, platform3, onReload) {
|
|
|
39207
39484
|
isRebuilding = true;
|
|
39208
39485
|
log2("Rebuilding...");
|
|
39209
39486
|
try {
|
|
39210
|
-
const next = await buildAll(ws);
|
|
39487
|
+
const next = await buildAll(ws, { minify: false });
|
|
39211
39488
|
platform3.setManifest(next);
|
|
39212
39489
|
platform3.notifyReload(next);
|
|
39213
39490
|
onReload?.();
|
|
@@ -39299,7 +39576,7 @@ platform3.command("dev").description("Start platform in dev mode (Bun server + V
|
|
|
39299
39576
|
map: opts.map,
|
|
39300
39577
|
headless: opts.headless
|
|
39301
39578
|
}));
|
|
39302
|
-
platform3.command("build").description("Build platform for production").option("--no-cache", "Force full rebuild").action((opts) => platformBuild({ noCache: opts.cache === false }));
|
|
39579
|
+
platform3.command("build").description("Build platform for production").option("--no-cache", "Force full rebuild").option("--stats", "Wypisz rozbicie chunk\xF3w na biblioteki (per-wej\u015Bcie raw/gzip + najci\u0119\u017Csze liby, ext/wewn). Wymusza pe\u0142ny build.").action((opts) => platformBuild({ noCache: opts.cache === false, stats: opts.stats }));
|
|
39303
39580
|
platform3.command("start").description("Start platform in production mode (requires prior build)").action(platformStart);
|
|
39304
39581
|
platform3.command("pairing-token").description("Generate a one-time federation pairing code (writes to DB, prints it)").action(platformPairingToken);
|
|
39305
39582
|
platform3.command("deploy [env]").description("Deploy platform to a remote server (reads deploy.arc.json, surveys if missing)").option("--skip-build", "Skip local build step").option("--rebuild", "Force rebuild before deploy").option("--build-only", "Build the Docker image locally, then exit (no remote push)").option("--image-tag <hash>", "Roll back / pin to an existing image tag instead of building a new one").option("--force-bootstrap", "Re-run Ansible host bootstrap even if the server is already configured").action((env2, opts) => platformDeploy(env2, opts));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arcote.tech/arc-cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.3",
|
|
4
4
|
"description": "CLI tool for Arc framework",
|
|
5
5
|
"module": "index.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -12,13 +12,13 @@
|
|
|
12
12
|
"build": "bun build --target=bun ./src/index.ts --outdir=dist --external @arcote.tech/arc --external @arcote.tech/arc-ds --external @arcote.tech/arc-react --external @arcote.tech/platform --external @arcote.tech/arc-map --external '@opentelemetry/*' && chmod +x dist/index.js"
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
|
-
"@arcote.tech/arc": "^0.8.
|
|
16
|
-
"@arcote.tech/arc-ds": "^0.8.
|
|
17
|
-
"@arcote.tech/arc-react": "^0.8.
|
|
18
|
-
"@arcote.tech/arc-host": "^0.8.
|
|
19
|
-
"@arcote.tech/arc-adapter-db-sqlite": "^0.8.
|
|
20
|
-
"@arcote.tech/arc-adapter-db-postgres": "^0.8.
|
|
21
|
-
"@arcote.tech/arc-otel": "^0.8.
|
|
15
|
+
"@arcote.tech/arc": "^0.8.3",
|
|
16
|
+
"@arcote.tech/arc-ds": "^0.8.3",
|
|
17
|
+
"@arcote.tech/arc-react": "^0.8.3",
|
|
18
|
+
"@arcote.tech/arc-host": "^0.8.3",
|
|
19
|
+
"@arcote.tech/arc-adapter-db-sqlite": "^0.8.3",
|
|
20
|
+
"@arcote.tech/arc-adapter-db-postgres": "^0.8.3",
|
|
21
|
+
"@arcote.tech/arc-otel": "^0.8.3",
|
|
22
22
|
"@opentelemetry/api": "^1.9.0",
|
|
23
23
|
"@opentelemetry/api-logs": "^0.57.0",
|
|
24
24
|
"@opentelemetry/core": "^1.30.0",
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"@opentelemetry/sdk-trace-base": "^1.30.0",
|
|
32
32
|
"@opentelemetry/sdk-trace-node": "^1.30.0",
|
|
33
33
|
"@opentelemetry/semantic-conventions": "^1.27.0",
|
|
34
|
-
"@arcote.tech/platform": "^0.8.
|
|
35
|
-
"@arcote.tech/arc-map": "^0.8.
|
|
34
|
+
"@arcote.tech/platform": "^0.8.3",
|
|
35
|
+
"@arcote.tech/arc-map": "^0.8.3",
|
|
36
36
|
"@clack/prompts": "^0.9.0",
|
|
37
37
|
"commander": "^11.1.0",
|
|
38
38
|
"chokidar": "^3.5.3",
|
|
@@ -120,6 +120,20 @@ function collectModuleNames(dir: string, acc: Set<string>): void {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Czy pakiet DEKLARUJE moduł Arc (`module("...")` w źródłach). Tylko takie
|
|
125
|
+
* pakiety są „członkami" wchodzącymi do initial/grup — czysta biblioteka bez
|
|
126
|
+
* modułu (np. pakiet z szablonami maili) NIE może być side-effect-importowana
|
|
127
|
+
* przez initial, bo z `sideEffects:true` wciągałaby całe swoje drzewo
|
|
128
|
+
* zależności do pierwszego wczytania (patrz: @react-email w NDT — 1,4 MB
|
|
129
|
+
* stosu maili w bundlu klienta przez samo `import "@ndt/email"`).
|
|
130
|
+
*/
|
|
131
|
+
export function packageDeclaresModule(pkg: WorkspacePackage): boolean {
|
|
132
|
+
const names = new Set<string>();
|
|
133
|
+
collectModuleNames(join(pkg.path, "src"), names);
|
|
134
|
+
return names.size > 0;
|
|
135
|
+
}
|
|
136
|
+
|
|
123
137
|
/**
|
|
124
138
|
* Assert every workspace package declares at most one `module()`. Throws a
|
|
125
139
|
* build error listing offenders, with the fix (split each extra module into
|