@arcote.tech/arc-cli 0.5.6 → 0.5.7
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 +768 -401
- package/package.json +7 -7
- package/src/builder/build-cache.ts +79 -0
- package/src/builder/hash.ts +100 -0
- package/src/builder/module-builder.ts +392 -196
- package/src/builder/parallel.ts +26 -0
- package/src/commands/platform-build.ts +2 -2
- package/src/commands/platform-deploy.ts +1 -1
- package/src/commands/platform-dev.ts +28 -45
- package/src/index.ts +8 -2
- package/src/platform/server.ts +10 -0
- package/src/platform/shared.ts +349 -143
package/dist/index.js
CHANGED
|
@@ -26345,19 +26345,20 @@ ${colors3.yellow}Type declaration errors:${colors3.reset}`);
|
|
|
26345
26345
|
}
|
|
26346
26346
|
|
|
26347
26347
|
// src/platform/shared.ts
|
|
26348
|
-
import { copyFileSync, existsSync as
|
|
26349
|
-
import { dirname as dirname6, join as
|
|
26348
|
+
import { copyFileSync, existsSync as existsSync8, mkdirSync as mkdirSync7, readFileSync as readFileSync8, readdirSync as readdirSync5, rmSync as rmSync2, writeFileSync as writeFileSync7 } from "fs";
|
|
26349
|
+
import { dirname as dirname6, join as join9 } from "path";
|
|
26350
26350
|
|
|
26351
26351
|
// src/builder/module-builder.ts
|
|
26352
26352
|
import { execSync } from "child_process";
|
|
26353
26353
|
import {
|
|
26354
|
-
existsSync as
|
|
26355
|
-
mkdirSync as
|
|
26356
|
-
readFileSync as
|
|
26357
|
-
readdirSync as
|
|
26358
|
-
|
|
26354
|
+
existsSync as existsSync7,
|
|
26355
|
+
mkdirSync as mkdirSync6,
|
|
26356
|
+
readFileSync as readFileSync7,
|
|
26357
|
+
readdirSync as readdirSync4,
|
|
26358
|
+
rmSync,
|
|
26359
|
+
writeFileSync as writeFileSync6
|
|
26359
26360
|
} from "fs";
|
|
26360
|
-
import { dirname as dirname5, join as
|
|
26361
|
+
import { dirname as dirname5, join as join8, relative as relative3 } from "path";
|
|
26361
26362
|
|
|
26362
26363
|
// src/i18n/index.ts
|
|
26363
26364
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
@@ -26630,43 +26631,154 @@ async function finalizeTranslations(rootDir, outDir, collector) {
|
|
|
26630
26631
|
}
|
|
26631
26632
|
}
|
|
26632
26633
|
|
|
26634
|
+
// src/builder/build-cache.ts
|
|
26635
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync5 } from "fs";
|
|
26636
|
+
import { join as join6 } from "path";
|
|
26637
|
+
var CACHE_VERSION = 1;
|
|
26638
|
+
var CACHE_FILE = ".build-cache.json";
|
|
26639
|
+
function emptyCache() {
|
|
26640
|
+
return { version: CACHE_VERSION, units: {} };
|
|
26641
|
+
}
|
|
26642
|
+
function loadBuildCache(arcDir) {
|
|
26643
|
+
const path4 = join6(arcDir, CACHE_FILE);
|
|
26644
|
+
if (!existsSync5(path4))
|
|
26645
|
+
return emptyCache();
|
|
26646
|
+
try {
|
|
26647
|
+
const raw = JSON.parse(readFileSync5(path4, "utf-8"));
|
|
26648
|
+
if (raw?.version !== CACHE_VERSION || typeof raw.units !== "object") {
|
|
26649
|
+
return emptyCache();
|
|
26650
|
+
}
|
|
26651
|
+
return raw;
|
|
26652
|
+
} catch {
|
|
26653
|
+
return emptyCache();
|
|
26654
|
+
}
|
|
26655
|
+
}
|
|
26656
|
+
function saveBuildCache(arcDir, cache) {
|
|
26657
|
+
mkdirSync5(arcDir, { recursive: true });
|
|
26658
|
+
writeFileSync5(join6(arcDir, CACHE_FILE), JSON.stringify(cache, null, 2));
|
|
26659
|
+
}
|
|
26660
|
+
function isCacheHit(cache, unitId, inputHash, requiredOutputs = []) {
|
|
26661
|
+
const entry = cache.units[unitId];
|
|
26662
|
+
if (!entry || entry.inputHash !== inputHash)
|
|
26663
|
+
return false;
|
|
26664
|
+
for (const out of requiredOutputs) {
|
|
26665
|
+
if (!existsSync5(out))
|
|
26666
|
+
return false;
|
|
26667
|
+
}
|
|
26668
|
+
return true;
|
|
26669
|
+
}
|
|
26670
|
+
function updateCache(cache, unitId, inputHash, output = {}) {
|
|
26671
|
+
cache.units[unitId] = {
|
|
26672
|
+
inputHash,
|
|
26673
|
+
...output.outputHash !== undefined && { outputHash: output.outputHash },
|
|
26674
|
+
...output.outputHashes !== undefined && { outputHashes: output.outputHashes }
|
|
26675
|
+
};
|
|
26676
|
+
}
|
|
26677
|
+
|
|
26678
|
+
// src/builder/hash.ts
|
|
26679
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, readdirSync as readdirSync3, statSync } from "fs";
|
|
26680
|
+
import { join as join7, relative as relative2, sep as sep2 } from "path";
|
|
26681
|
+
function sha256Hex(bytes) {
|
|
26682
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
26683
|
+
hasher.update(bytes);
|
|
26684
|
+
return hasher.digest("hex");
|
|
26685
|
+
}
|
|
26686
|
+
function sha256OfFiles(paths) {
|
|
26687
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
26688
|
+
const sorted = [...paths].sort();
|
|
26689
|
+
for (const p of sorted) {
|
|
26690
|
+
if (!existsSync6(p))
|
|
26691
|
+
continue;
|
|
26692
|
+
hasher.update(readFileSync6(p));
|
|
26693
|
+
hasher.update("\x00");
|
|
26694
|
+
}
|
|
26695
|
+
return hasher.digest("hex");
|
|
26696
|
+
}
|
|
26697
|
+
function sha256OfDir(dir, filter2) {
|
|
26698
|
+
if (!existsSync6(dir))
|
|
26699
|
+
return sha256Hex("");
|
|
26700
|
+
const hasher = new Bun.CryptoHasher("sha256");
|
|
26701
|
+
const entries = [];
|
|
26702
|
+
function walk(absDir) {
|
|
26703
|
+
for (const entry of readdirSync3(absDir, { withFileTypes: true })) {
|
|
26704
|
+
const abs = join7(absDir, entry.name);
|
|
26705
|
+
const rel = relative2(dir, abs).split(sep2).join("/");
|
|
26706
|
+
if (filter2 && !filter2(rel))
|
|
26707
|
+
continue;
|
|
26708
|
+
if (entry.isDirectory())
|
|
26709
|
+
walk(abs);
|
|
26710
|
+
else if (entry.isFile())
|
|
26711
|
+
entries.push({ rel, abs });
|
|
26712
|
+
}
|
|
26713
|
+
}
|
|
26714
|
+
walk(dir);
|
|
26715
|
+
entries.sort((a, b) => a.rel < b.rel ? -1 : a.rel > b.rel ? 1 : 0);
|
|
26716
|
+
for (const { rel, abs } of entries) {
|
|
26717
|
+
hasher.update(rel);
|
|
26718
|
+
hasher.update("\x00");
|
|
26719
|
+
hasher.update(readFileSync6(abs));
|
|
26720
|
+
hasher.update("\x00");
|
|
26721
|
+
}
|
|
26722
|
+
return hasher.digest("hex");
|
|
26723
|
+
}
|
|
26724
|
+
function sha256OfJson(value) {
|
|
26725
|
+
return sha256Hex(stableStringify(value));
|
|
26726
|
+
}
|
|
26727
|
+
function stableStringify(value) {
|
|
26728
|
+
if (value === null || typeof value !== "object")
|
|
26729
|
+
return JSON.stringify(value);
|
|
26730
|
+
if (Array.isArray(value)) {
|
|
26731
|
+
return "[" + value.map(stableStringify).join(",") + "]";
|
|
26732
|
+
}
|
|
26733
|
+
const obj = value;
|
|
26734
|
+
const keys = Object.keys(obj).sort();
|
|
26735
|
+
return "{" + keys.map((k) => JSON.stringify(k) + ":" + stableStringify(obj[k])).join(",") + "}";
|
|
26736
|
+
}
|
|
26737
|
+
function readInstalledVersion(rootDir, pkgName) {
|
|
26738
|
+
const pkgJson = join7(rootDir, "node_modules", pkgName, "package.json");
|
|
26739
|
+
if (!existsSync6(pkgJson))
|
|
26740
|
+
return null;
|
|
26741
|
+
try {
|
|
26742
|
+
return JSON.parse(readFileSync6(pkgJson, "utf-8")).version ?? null;
|
|
26743
|
+
} catch {
|
|
26744
|
+
return null;
|
|
26745
|
+
}
|
|
26746
|
+
}
|
|
26747
|
+
function mtimeOf(path4) {
|
|
26748
|
+
if (!existsSync6(path4))
|
|
26749
|
+
return 0;
|
|
26750
|
+
try {
|
|
26751
|
+
return statSync(path4).mtimeMs;
|
|
26752
|
+
} catch {
|
|
26753
|
+
return 0;
|
|
26754
|
+
}
|
|
26755
|
+
}
|
|
26756
|
+
|
|
26757
|
+
// src/builder/parallel.ts
|
|
26758
|
+
import { cpus } from "os";
|
|
26759
|
+
var DEFAULT_CONCURRENCY = Math.max(1, cpus().length - 1);
|
|
26760
|
+
async function pAll(tasks, concurrency = DEFAULT_CONCURRENCY) {
|
|
26761
|
+
const results = new Array(tasks.length);
|
|
26762
|
+
let nextIndex = 0;
|
|
26763
|
+
const limit = Math.max(1, Math.min(concurrency, tasks.length));
|
|
26764
|
+
async function worker() {
|
|
26765
|
+
while (true) {
|
|
26766
|
+
const i = nextIndex++;
|
|
26767
|
+
if (i >= tasks.length)
|
|
26768
|
+
return;
|
|
26769
|
+
results[i] = await tasks[i]();
|
|
26770
|
+
}
|
|
26771
|
+
}
|
|
26772
|
+
const workers = Array.from({ length: limit }, () => worker());
|
|
26773
|
+
await Promise.all(workers);
|
|
26774
|
+
return results;
|
|
26775
|
+
}
|
|
26776
|
+
|
|
26633
26777
|
// src/builder/module-builder.ts
|
|
26634
26778
|
var CONTEXT_CLIENTS = [
|
|
26635
26779
|
{ name: "server", target: "bun", defines: { ONLY_SERVER: "true", ONLY_BROWSER: "false", ONLY_CLIENT: "false" } },
|
|
26636
26780
|
{ name: "browser", target: "browser", defines: { ONLY_SERVER: "false", ONLY_BROWSER: "true", ONLY_CLIENT: "true" } }
|
|
26637
26781
|
];
|
|
26638
|
-
async function buildContextPackage(pkg) {
|
|
26639
|
-
const entrypoint = pkg.entrypoint;
|
|
26640
|
-
const outDir = join6(pkg.path, "dist");
|
|
26641
|
-
const peerDeps = Object.keys(pkg.packageJson.peerDependencies || {});
|
|
26642
|
-
const deps = Object.keys(pkg.packageJson.dependencies || {});
|
|
26643
|
-
const externals = [...peerDeps, ...deps];
|
|
26644
|
-
const allDeclErrors = [];
|
|
26645
|
-
for (const client of CONTEXT_CLIENTS) {
|
|
26646
|
-
const result = await Bun.build({
|
|
26647
|
-
entrypoints: [entrypoint],
|
|
26648
|
-
outdir: join6(outDir, client.name, "main"),
|
|
26649
|
-
target: client.target,
|
|
26650
|
-
format: "esm",
|
|
26651
|
-
naming: "index.[ext]",
|
|
26652
|
-
external: externals,
|
|
26653
|
-
define: client.defines
|
|
26654
|
-
});
|
|
26655
|
-
if (!result.success) {
|
|
26656
|
-
console.error(`Context ${client.name} build failed:`);
|
|
26657
|
-
for (const log2 of result.logs)
|
|
26658
|
-
console.error(log2);
|
|
26659
|
-
throw new Error(`${client.name} build failed for ${pkg.name}`);
|
|
26660
|
-
}
|
|
26661
|
-
const globalsContent = Object.entries(client.defines).map(([k, v]) => `declare const ${k}: ${v};`).join(`
|
|
26662
|
-
`);
|
|
26663
|
-
const declResult = await buildTypeDeclarations([entrypoint], join6(outDir, client.name), dirname5(entrypoint), globalsContent);
|
|
26664
|
-
if (!declResult.success && declResult.errors.length > 0) {
|
|
26665
|
-
allDeclErrors.push(...declResult.errors.map((e) => `[${pkg.name}/${client.name}] ${e}`));
|
|
26666
|
-
}
|
|
26667
|
-
}
|
|
26668
|
-
return { declarationErrors: allDeclErrors };
|
|
26669
|
-
}
|
|
26670
26782
|
var SHELL_EXTERNALS = [
|
|
26671
26783
|
"react",
|
|
26672
26784
|
"react-dom",
|
|
@@ -26680,57 +26792,41 @@ var SHELL_EXTERNALS = [
|
|
|
26680
26792
|
"@arcote.tech/arc-workspace",
|
|
26681
26793
|
"@arcote.tech/platform"
|
|
26682
26794
|
];
|
|
26683
|
-
function sha256Hex(bytes) {
|
|
26684
|
-
const hasher = new Bun.CryptoHasher("sha256");
|
|
26685
|
-
hasher.update(bytes);
|
|
26686
|
-
return hasher.digest("hex");
|
|
26687
|
-
}
|
|
26688
|
-
function sha256OfFiles(paths) {
|
|
26689
|
-
const hasher = new Bun.CryptoHasher("sha256");
|
|
26690
|
-
const sorted = [...paths].sort();
|
|
26691
|
-
for (const p of sorted) {
|
|
26692
|
-
if (!existsSync5(p))
|
|
26693
|
-
continue;
|
|
26694
|
-
hasher.update(readFileSync5(p));
|
|
26695
|
-
hasher.update("\x00");
|
|
26696
|
-
}
|
|
26697
|
-
return hasher.digest("hex");
|
|
26698
|
-
}
|
|
26699
26795
|
function discoverPackages(rootDir) {
|
|
26700
|
-
const rootPkg = JSON.parse(
|
|
26796
|
+
const rootPkg = JSON.parse(readFileSync7(join8(rootDir, "package.json"), "utf-8"));
|
|
26701
26797
|
const workspaceGlobs = rootPkg.workspaces ?? [];
|
|
26702
26798
|
const results = [];
|
|
26703
26799
|
for (const glob2 of workspaceGlobs) {
|
|
26704
26800
|
const base2 = glob2.replace("/*", "");
|
|
26705
|
-
const baseDir =
|
|
26706
|
-
if (!
|
|
26801
|
+
const baseDir = join8(rootDir, base2);
|
|
26802
|
+
if (!existsSync7(baseDir))
|
|
26707
26803
|
continue;
|
|
26708
26804
|
let entries;
|
|
26709
26805
|
try {
|
|
26710
|
-
entries =
|
|
26806
|
+
entries = readdirSync4(baseDir);
|
|
26711
26807
|
} catch {
|
|
26712
26808
|
continue;
|
|
26713
26809
|
}
|
|
26714
26810
|
for (const entry of entries) {
|
|
26715
|
-
const pkgPath =
|
|
26716
|
-
if (!
|
|
26811
|
+
const pkgPath = join8(baseDir, entry, "package.json");
|
|
26812
|
+
if (!existsSync7(pkgPath))
|
|
26717
26813
|
continue;
|
|
26718
|
-
const pkg = JSON.parse(
|
|
26814
|
+
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
26719
26815
|
if (pkg.name?.startsWith("@arcote.tech/"))
|
|
26720
26816
|
continue;
|
|
26721
|
-
const pkgDir =
|
|
26817
|
+
const pkgDir = join8(baseDir, entry);
|
|
26722
26818
|
const candidates = [
|
|
26723
|
-
|
|
26724
|
-
|
|
26725
|
-
|
|
26726
|
-
|
|
26819
|
+
join8(pkgDir, "src", "index.ts"),
|
|
26820
|
+
join8(pkgDir, "src", "index.tsx"),
|
|
26821
|
+
join8(pkgDir, "index.ts"),
|
|
26822
|
+
join8(pkgDir, "index.tsx")
|
|
26727
26823
|
];
|
|
26728
|
-
const entrypoint = candidates.find((c) =>
|
|
26824
|
+
const entrypoint = candidates.find((c) => existsSync7(c)) ?? null;
|
|
26729
26825
|
if (!entrypoint)
|
|
26730
26826
|
continue;
|
|
26731
26827
|
results.push({
|
|
26732
26828
|
name: pkg.name,
|
|
26733
|
-
path:
|
|
26829
|
+
path: join8(baseDir, entry),
|
|
26734
26830
|
entrypoint,
|
|
26735
26831
|
packageJson: pkg
|
|
26736
26832
|
});
|
|
@@ -26749,95 +26845,198 @@ function isContextPackage(pkg) {
|
|
|
26749
26845
|
}
|
|
26750
26846
|
return false;
|
|
26751
26847
|
}
|
|
26752
|
-
|
|
26753
|
-
|
|
26754
|
-
|
|
26755
|
-
|
|
26756
|
-
|
|
26757
|
-
|
|
26758
|
-
|
|
26759
|
-
|
|
26760
|
-
|
|
26761
|
-
|
|
26762
|
-
|
|
26763
|
-
|
|
26764
|
-
|
|
26765
|
-
|
|
26766
|
-
|
|
26767
|
-
|
|
26768
|
-
|
|
26769
|
-
|
|
26770
|
-
|
|
26771
|
-
|
|
26772
|
-
|
|
26773
|
-
|
|
26774
|
-
|
|
26775
|
-
|
|
26776
|
-
|
|
26777
|
-
|
|
26778
|
-
|
|
26779
|
-
|
|
26780
|
-
|
|
26848
|
+
var sourceFilter = (rel) => {
|
|
26849
|
+
if (rel.startsWith("dist/") || rel.startsWith("dist"))
|
|
26850
|
+
return false;
|
|
26851
|
+
if (rel.includes("/node_modules/") || rel.startsWith("node_modules"))
|
|
26852
|
+
return false;
|
|
26853
|
+
if (rel.startsWith(".arc/") || rel.startsWith(".arc"))
|
|
26854
|
+
return false;
|
|
26855
|
+
return true;
|
|
26856
|
+
};
|
|
26857
|
+
function pkgSourceHash(pkg) {
|
|
26858
|
+
return sha256OfDir(join8(pkg.path, "src"), sourceFilter);
|
|
26859
|
+
}
|
|
26860
|
+
function depVersionsHash(rootDir, pkg) {
|
|
26861
|
+
const peerDeps = Object.keys(pkg.packageJson.peerDependencies ?? {});
|
|
26862
|
+
const deps = Object.keys(pkg.packageJson.dependencies ?? {});
|
|
26863
|
+
const versions = {};
|
|
26864
|
+
for (const dep of [...peerDeps, ...deps].sort()) {
|
|
26865
|
+
versions[dep] = readInstalledVersion(rootDir, dep);
|
|
26866
|
+
}
|
|
26867
|
+
return sha256OfJson(versions);
|
|
26868
|
+
}
|
|
26869
|
+
async function buildContextClient(pkg, rootDir, client, cache, noCache) {
|
|
26870
|
+
const unitId = `context-pkg:${pkg.name}:${client.name}`;
|
|
26871
|
+
const outDir = join8(pkg.path, "dist", client.name);
|
|
26872
|
+
const inputHash = sha256OfJson({
|
|
26873
|
+
src: pkgSourceHash(pkg),
|
|
26874
|
+
pkg: pkg.packageJson,
|
|
26875
|
+
deps: depVersionsHash(rootDir, pkg),
|
|
26876
|
+
client: client.name,
|
|
26877
|
+
target: client.target,
|
|
26878
|
+
defines: client.defines
|
|
26879
|
+
});
|
|
26880
|
+
if (!noCache && isCacheHit(cache, unitId, inputHash, [join8(outDir, "main", "index.js")])) {
|
|
26881
|
+
console.log(` \u2713 cached: ${pkg.name} (${client.name})`);
|
|
26882
|
+
return { pkgName: pkg.name, client: client.name, declarationErrors: [], cached: true };
|
|
26781
26883
|
}
|
|
26782
|
-
console.log(`
|
|
26783
|
-
const
|
|
26784
|
-
const
|
|
26785
|
-
|
|
26786
|
-
setup(build2) {
|
|
26787
|
-
build2.onResolve({ filter: /^@arcote\.tech\// }, (args) => {
|
|
26788
|
-
return { path: args.path, external: true };
|
|
26789
|
-
});
|
|
26790
|
-
}
|
|
26791
|
-
};
|
|
26884
|
+
console.log(` building: ${pkg.name} (${client.name})`);
|
|
26885
|
+
const peerDeps = Object.keys(pkg.packageJson.peerDependencies ?? {});
|
|
26886
|
+
const deps = Object.keys(pkg.packageJson.dependencies ?? {});
|
|
26887
|
+
const externals = [...peerDeps, ...deps];
|
|
26792
26888
|
const result = await Bun.build({
|
|
26793
|
-
entrypoints,
|
|
26794
|
-
outdir: outDir,
|
|
26795
|
-
|
|
26889
|
+
entrypoints: [pkg.entrypoint],
|
|
26890
|
+
outdir: join8(outDir, "main"),
|
|
26891
|
+
target: client.target,
|
|
26796
26892
|
format: "esm",
|
|
26797
|
-
|
|
26798
|
-
external:
|
|
26799
|
-
|
|
26800
|
-
naming: "[name].[ext]",
|
|
26801
|
-
define: {
|
|
26802
|
-
ONLY_SERVER: "false",
|
|
26803
|
-
ONLY_BROWSER: "true",
|
|
26804
|
-
ONLY_CLIENT: "true"
|
|
26805
|
-
}
|
|
26893
|
+
naming: "index.[ext]",
|
|
26894
|
+
external: externals,
|
|
26895
|
+
define: client.defines
|
|
26806
26896
|
});
|
|
26807
26897
|
if (!result.success) {
|
|
26808
|
-
console.error(
|
|
26898
|
+
console.error(`Context ${client.name} build failed:`);
|
|
26809
26899
|
for (const log2 of result.logs)
|
|
26810
26900
|
console.error(log2);
|
|
26811
|
-
throw new Error(
|
|
26812
|
-
}
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
|
|
26816
|
-
const
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
|
|
26820
|
-
|
|
26821
|
-
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
};
|
|
26901
|
+
throw new Error(`${client.name} build failed for ${pkg.name}`);
|
|
26902
|
+
}
|
|
26903
|
+
const globalsContent = Object.entries(client.defines).map(([k, v]) => `declare const ${k}: ${v};`).join(`
|
|
26904
|
+
`);
|
|
26905
|
+
const declResult = await buildTypeDeclarations([pkg.entrypoint], outDir, dirname5(pkg.entrypoint), globalsContent);
|
|
26906
|
+
const declarationErrors = !declResult.success && declResult.errors.length > 0 ? declResult.errors.map((e) => `[${pkg.name}/${client.name}] ${e}`) : [];
|
|
26907
|
+
const outputHash = sha256OfDir(outDir);
|
|
26908
|
+
updateCache(cache, unitId, inputHash, { outputHash });
|
|
26909
|
+
return { pkgName: pkg.name, client: client.name, declarationErrors, cached: false };
|
|
26910
|
+
}
|
|
26911
|
+
async function buildContextPackages(rootDir, packages, cache, noCache) {
|
|
26912
|
+
const contexts = packages.filter((p) => isContextPackage(p.packageJson));
|
|
26913
|
+
if (contexts.length === 0)
|
|
26914
|
+
return { declarationErrors: [] };
|
|
26915
|
+
const tasks = contexts.flatMap((pkg) => CONTEXT_CLIENTS.map((client) => () => buildContextClient(pkg, rootDir, client, cache, noCache)));
|
|
26916
|
+
const results = await pAll(tasks);
|
|
26917
|
+
const declarationErrors = results.flatMap((r) => r.declarationErrors);
|
|
26918
|
+
if (declarationErrors.length > 0) {
|
|
26919
|
+
console.warn(`
|
|
26920
|
+
\x1B[33mType declaration errors:\x1B[0m`);
|
|
26921
|
+
for (const err of declarationErrors)
|
|
26922
|
+
console.warn(` ${err}`);
|
|
26923
|
+
console.warn("");
|
|
26924
|
+
}
|
|
26925
|
+
return { declarationErrors };
|
|
26926
|
+
}
|
|
26927
|
+
async function buildModulesBundle(rootDir, outDir, packages, cache, noCache) {
|
|
26928
|
+
mkdirSync6(outDir, { recursive: true });
|
|
26929
|
+
const unitId = "modules-bundle";
|
|
26930
|
+
const pkgHashes = packages.map((p) => ({
|
|
26931
|
+
name: p.name,
|
|
26932
|
+
safeName: p.path.split("/").pop(),
|
|
26933
|
+
srcHash: pkgSourceHash(p)
|
|
26934
|
+
}));
|
|
26935
|
+
const inputHash = sha256OfJson({
|
|
26936
|
+
pkgHashes,
|
|
26937
|
+
externals: SHELL_EXTERNALS,
|
|
26938
|
+
define: { ONLY_SERVER: "false", ONLY_BROWSER: "true", ONLY_CLIENT: "true" }
|
|
26825
26939
|
});
|
|
26826
|
-
|
|
26827
|
-
|
|
26828
|
-
|
|
26829
|
-
|
|
26830
|
-
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26940
|
+
if (!noCache && isCacheHit(cache, unitId, inputHash)) {
|
|
26941
|
+
const existing = cache.units[unitId]?.outputHashes ?? {};
|
|
26942
|
+
const modules = [];
|
|
26943
|
+
for (const { safeName, name } of pkgHashes) {
|
|
26944
|
+
const file = `${safeName}.js`;
|
|
26945
|
+
const filePath = join8(outDir, file);
|
|
26946
|
+
if (!existsSync7(filePath)) {
|
|
26947
|
+
console.log(` rebuilding modules-bundle: output ${file} missing`);
|
|
26948
|
+
return await actuallyBuild();
|
|
26949
|
+
}
|
|
26950
|
+
modules.push({ file, name, hash: existing[safeName] ?? sha256Hex(readFileSync7(filePath)) });
|
|
26951
|
+
}
|
|
26952
|
+
console.log(` \u2713 cached: modules-bundle (${modules.length} module(s))`);
|
|
26953
|
+
return { modules, cached: true };
|
|
26954
|
+
}
|
|
26955
|
+
return await actuallyBuild();
|
|
26956
|
+
async function actuallyBuild() {
|
|
26957
|
+
console.log(` building: modules-bundle (${packages.length} package(s))`);
|
|
26958
|
+
const tmpDir = join8(outDir, "_entries");
|
|
26959
|
+
mkdirSync6(tmpDir, { recursive: true });
|
|
26960
|
+
const entrypoints = [];
|
|
26961
|
+
const fileToName = new Map;
|
|
26962
|
+
for (const pkg of packages) {
|
|
26963
|
+
const safeName = pkg.path.split("/").pop();
|
|
26964
|
+
const moduleName = pkg.name.includes("/") ? pkg.name.split("/").pop() : pkg.name;
|
|
26965
|
+
fileToName.set(safeName, moduleName);
|
|
26966
|
+
const wrapperFile = join8(tmpDir, `${safeName}.ts`);
|
|
26967
|
+
writeFileSync6(wrapperFile, `export * from "${pkg.name}";
|
|
26968
|
+
`);
|
|
26969
|
+
entrypoints.push(wrapperFile);
|
|
26970
|
+
}
|
|
26971
|
+
const i18nCollector = new Map;
|
|
26972
|
+
const arcExternalPlugin = {
|
|
26973
|
+
name: "arc-external",
|
|
26974
|
+
setup(build2) {
|
|
26975
|
+
build2.onResolve({ filter: /^@arcote\.tech\// }, (args) => {
|
|
26976
|
+
return { path: args.path, external: true };
|
|
26977
|
+
});
|
|
26978
|
+
}
|
|
26979
|
+
};
|
|
26980
|
+
const result = await Bun.build({
|
|
26981
|
+
entrypoints,
|
|
26982
|
+
outdir: outDir,
|
|
26983
|
+
splitting: true,
|
|
26984
|
+
format: "esm",
|
|
26985
|
+
target: "browser",
|
|
26986
|
+
external: SHELL_EXTERNALS,
|
|
26987
|
+
plugins: [arcExternalPlugin, i18nExtractPlugin(i18nCollector, rootDir)],
|
|
26988
|
+
naming: "[name].[ext]",
|
|
26989
|
+
define: {
|
|
26990
|
+
ONLY_SERVER: "false",
|
|
26991
|
+
ONLY_BROWSER: "true",
|
|
26992
|
+
ONLY_CLIENT: "true"
|
|
26993
|
+
}
|
|
26994
|
+
});
|
|
26995
|
+
if (!result.success) {
|
|
26996
|
+
console.error("Modules bundle build failed:");
|
|
26997
|
+
for (const log2 of result.logs)
|
|
26998
|
+
console.error(log2);
|
|
26999
|
+
throw new Error("Module build failed");
|
|
27000
|
+
}
|
|
27001
|
+
await finalizeTranslations(rootDir, join8(outDir, ".."), i18nCollector);
|
|
27002
|
+
rmSync(tmpDir, { recursive: true, force: true });
|
|
27003
|
+
const outputHashes = {};
|
|
27004
|
+
const modules = result.outputs.filter((o) => o.kind === "entry-point").map((o) => {
|
|
27005
|
+
const file = o.path.split("/").pop();
|
|
27006
|
+
const safeName = file.replace(/\.js$/, "");
|
|
27007
|
+
const bytes = readFileSync7(o.path);
|
|
27008
|
+
const hash = sha256Hex(bytes);
|
|
27009
|
+
outputHashes[safeName] = hash;
|
|
27010
|
+
return {
|
|
27011
|
+
file,
|
|
27012
|
+
name: fileToName.get(safeName) ?? safeName,
|
|
27013
|
+
hash
|
|
27014
|
+
};
|
|
27015
|
+
});
|
|
27016
|
+
updateCache(cache, unitId, inputHash, { outputHashes });
|
|
27017
|
+
return { modules, cached: false };
|
|
27018
|
+
}
|
|
27019
|
+
}
|
|
27020
|
+
async function buildTranslations(rootDir, arcDir, cache, noCache) {
|
|
27021
|
+
const localesDir = join8(rootDir, "locales");
|
|
27022
|
+
if (!existsSync7(localesDir))
|
|
27023
|
+
return;
|
|
27024
|
+
const unitId = "translations";
|
|
27025
|
+
const poFiles = readdirSync4(localesDir).filter((f) => f.endsWith(".po")).map((f) => join8(localesDir, f));
|
|
27026
|
+
if (poFiles.length === 0)
|
|
27027
|
+
return;
|
|
27028
|
+
const inputHash = sha256OfFiles(poFiles);
|
|
27029
|
+
if (!noCache && isCacheHit(cache, unitId, inputHash, [join8(arcDir, "locales")])) {
|
|
27030
|
+
console.log(` \u2713 cached: translations`);
|
|
27031
|
+
return;
|
|
27032
|
+
}
|
|
27033
|
+
console.log(` building: translations (${poFiles.length} catalog(s))`);
|
|
27034
|
+
compileAllCatalogs(localesDir, join8(arcDir, "locales"));
|
|
27035
|
+
const jsonFiles = readdirSync4(join8(arcDir, "locales")).filter((f) => f.endsWith(".json")).map((f) => join8(arcDir, "locales", f));
|
|
27036
|
+
const outputHash = sha256OfFiles(jsonFiles);
|
|
27037
|
+
updateCache(cache, unitId, inputHash, { outputHash });
|
|
26834
27038
|
}
|
|
26835
|
-
|
|
26836
|
-
mkdirSync5(outDir, { recursive: true });
|
|
26837
|
-
const inputCss = join6(outDir, "_input.css");
|
|
26838
|
-
const outputCss = join6(outDir, "styles.css");
|
|
26839
|
-
const rootRel = relative2(outDir, rootDir).replace(/\\/g, "/");
|
|
26840
|
-
writeFileSync5(inputCss, `@import "tailwindcss";
|
|
27039
|
+
var TAILWIND_INPUT_TEMPLATE = (rootRel) => `@import "tailwindcss";
|
|
26841
27040
|
@import "tw-animate-css";
|
|
26842
27041
|
|
|
26843
27042
|
@source "${rootRel}/packages/*/*.{ts,tsx}";
|
|
@@ -26895,12 +27094,61 @@ async function buildStyles(rootDir, outDir) {
|
|
|
26895
27094
|
min-height: 100vh;
|
|
26896
27095
|
}
|
|
26897
27096
|
}
|
|
26898
|
-
|
|
26899
|
-
|
|
27097
|
+
`;
|
|
27098
|
+
async function buildStyles(rootDir, arcDir, packages, themePath, cache, noCache) {
|
|
27099
|
+
mkdirSync6(arcDir, { recursive: true });
|
|
27100
|
+
const inputCss = join8(arcDir, "_input.css");
|
|
27101
|
+
const outputCss = join8(arcDir, "styles.css");
|
|
27102
|
+
const themeOutput = join8(arcDir, "theme.css");
|
|
27103
|
+
const rootRel = relative3(arcDir, rootDir).replace(/\\/g, "/");
|
|
27104
|
+
const inputCssContent = TAILWIND_INPUT_TEMPLATE(rootRel);
|
|
27105
|
+
const tsxFilter = (rel) => {
|
|
27106
|
+
if (!sourceFilter(rel))
|
|
27107
|
+
return false;
|
|
27108
|
+
if (/\.[^/]+$/.test(rel) && !/\.(ts|tsx)$/.test(rel))
|
|
27109
|
+
return false;
|
|
27110
|
+
return true;
|
|
27111
|
+
};
|
|
27112
|
+
const wsHashes = {};
|
|
27113
|
+
for (const p of packages) {
|
|
27114
|
+
wsHashes[p.name] = sha256OfDir(join8(p.path, "src"), tsxFilter);
|
|
27115
|
+
}
|
|
27116
|
+
const platformSrc = join8(rootDir, "node_modules", "@arcote.tech", "platform", "src");
|
|
27117
|
+
const arcDsSrc = join8(rootDir, "node_modules", "@arcote.tech", "arc-ds", "src");
|
|
27118
|
+
const frameworkHashes = {
|
|
27119
|
+
platform: sha256OfDir(platformSrc, tsxFilter),
|
|
27120
|
+
arcDs: sha256OfDir(arcDsSrc, tsxFilter)
|
|
27121
|
+
};
|
|
27122
|
+
const themeContent = themePath && existsSync7(join8(rootDir, themePath)) ? readFileSync7(join8(rootDir, themePath)) : null;
|
|
27123
|
+
const themeHash = themeContent ? sha256Hex(themeContent) : null;
|
|
27124
|
+
const unitId = "styles";
|
|
27125
|
+
const inputHash = sha256OfJson({
|
|
27126
|
+
workspaces: wsHashes,
|
|
27127
|
+
framework: frameworkHashes,
|
|
27128
|
+
inputCss: inputCssContent,
|
|
27129
|
+
themeHash
|
|
27130
|
+
});
|
|
27131
|
+
const requiredOutputs = [outputCss];
|
|
27132
|
+
if (themePath)
|
|
27133
|
+
requiredOutputs.push(themeOutput);
|
|
27134
|
+
if (!noCache && isCacheHit(cache, unitId, inputHash, requiredOutputs)) {
|
|
27135
|
+
console.log(` \u2713 cached: styles`);
|
|
27136
|
+
return;
|
|
27137
|
+
}
|
|
27138
|
+
console.log(` building: styles`);
|
|
27139
|
+
writeFileSync6(inputCss, inputCssContent);
|
|
26900
27140
|
execSync(`bunx @tailwindcss/cli -i ${inputCss} -o ${outputCss} --minify`, {
|
|
26901
27141
|
cwd: rootDir,
|
|
26902
27142
|
stdio: "inherit"
|
|
26903
27143
|
});
|
|
27144
|
+
if (themePath && themeContent) {
|
|
27145
|
+
writeFileSync6(themeOutput, themeContent);
|
|
27146
|
+
}
|
|
27147
|
+
const outFiles = [outputCss];
|
|
27148
|
+
if (themePath && existsSync7(themeOutput))
|
|
27149
|
+
outFiles.push(themeOutput);
|
|
27150
|
+
const outputHash = sha256OfFiles(outFiles);
|
|
27151
|
+
updateCache(cache, unitId, inputHash, { outputHash });
|
|
26904
27152
|
}
|
|
26905
27153
|
|
|
26906
27154
|
// src/platform/shared.ts
|
|
@@ -26920,9 +27168,9 @@ function resolveWorkspace() {
|
|
|
26920
27168
|
process.exit(1);
|
|
26921
27169
|
}
|
|
26922
27170
|
const rootDir = dirname6(packageJsonPath);
|
|
26923
|
-
const rootPkg = JSON.parse(
|
|
27171
|
+
const rootPkg = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
|
|
26924
27172
|
const appName = rootPkg.name ?? "Arc App";
|
|
26925
|
-
const arcDir =
|
|
27173
|
+
const arcDir = join9(rootDir, ".arc", "platform");
|
|
26926
27174
|
log2("Scanning workspaces...");
|
|
26927
27175
|
const packages = discoverPackages(rootDir);
|
|
26928
27176
|
ok(`Found ${packages.length} package(s): ${packages.map((p) => p.name).join(", ")}`);
|
|
@@ -26932,10 +27180,10 @@ function resolveWorkspace() {
|
|
|
26932
27180
|
}
|
|
26933
27181
|
let manifest;
|
|
26934
27182
|
for (const name of ["manifest.json", "manifest.webmanifest"]) {
|
|
26935
|
-
const manifestPath =
|
|
26936
|
-
if (
|
|
27183
|
+
const manifestPath = join9(rootDir, name);
|
|
27184
|
+
if (existsSync8(manifestPath)) {
|
|
26937
27185
|
try {
|
|
26938
|
-
const data = JSON.parse(
|
|
27186
|
+
const data = JSON.parse(readFileSync8(manifestPath, "utf-8"));
|
|
26939
27187
|
const icons = data.icons;
|
|
26940
27188
|
manifest = {
|
|
26941
27189
|
path: manifestPath,
|
|
@@ -26954,61 +27202,135 @@ function resolveWorkspace() {
|
|
|
26954
27202
|
rootPkg,
|
|
26955
27203
|
appName,
|
|
26956
27204
|
arcDir,
|
|
26957
|
-
modulesDir:
|
|
26958
|
-
shellDir:
|
|
26959
|
-
|
|
27205
|
+
modulesDir: join9(arcDir, "modules"),
|
|
27206
|
+
shellDir: join9(arcDir, "shell"),
|
|
27207
|
+
assetsDir: join9(arcDir, "assets"),
|
|
27208
|
+
publicDir: join9(rootDir, "public"),
|
|
26960
27209
|
packages,
|
|
26961
27210
|
manifest
|
|
26962
27211
|
};
|
|
26963
27212
|
}
|
|
26964
|
-
async function buildAll(ws) {
|
|
26965
|
-
|
|
26966
|
-
const
|
|
26967
|
-
ok(`Built ${manifest.modules.length} module(s)`);
|
|
26968
|
-
log2("Building styles...");
|
|
26969
|
-
await buildStyles(ws.rootDir, ws.arcDir);
|
|
26970
|
-
ok("Styles built");
|
|
27213
|
+
async function buildAll(ws, opts = {}) {
|
|
27214
|
+
const cache = loadBuildCache(ws.arcDir);
|
|
27215
|
+
const noCache = opts.noCache ?? false;
|
|
26971
27216
|
const themePath = ws.rootPkg.arc?.theme;
|
|
26972
|
-
|
|
26973
|
-
|
|
26974
|
-
|
|
26975
|
-
|
|
26976
|
-
|
|
26977
|
-
|
|
26978
|
-
|
|
26979
|
-
|
|
26980
|
-
|
|
26981
|
-
|
|
26982
|
-
const finalManifest =
|
|
26983
|
-
|
|
27217
|
+
log2(`Building (concurrency parallel${noCache ? ", no-cache" : ""})...`);
|
|
27218
|
+
const [, modulesResult] = await Promise.all([
|
|
27219
|
+
buildContextPackages(ws.rootDir, ws.packages, cache, noCache),
|
|
27220
|
+
buildModulesBundle(ws.rootDir, ws.modulesDir, ws.packages, cache, noCache),
|
|
27221
|
+
buildShell(ws, cache, noCache),
|
|
27222
|
+
buildStyles(ws.rootDir, ws.arcDir, ws.packages, themePath, cache, noCache),
|
|
27223
|
+
copyBrowserAssets(ws, cache, noCache),
|
|
27224
|
+
buildTranslations(ws.rootDir, ws.arcDir, cache, noCache)
|
|
27225
|
+
]);
|
|
27226
|
+
saveBuildCache(ws.arcDir, cache);
|
|
27227
|
+
const finalManifest = assembleManifest(ws, modulesResult.modules, cache);
|
|
27228
|
+
writeFileSync7(join9(ws.modulesDir, "manifest.json"), JSON.stringify(finalManifest, null, 2));
|
|
26984
27229
|
return finalManifest;
|
|
26985
27230
|
}
|
|
26986
|
-
function
|
|
26987
|
-
const
|
|
26988
|
-
const
|
|
26989
|
-
|
|
26990
|
-
|
|
26991
|
-
|
|
27231
|
+
function assembleManifest(ws, modules, cache) {
|
|
27232
|
+
const shellEntries = {};
|
|
27233
|
+
for (const [unitId, entry] of Object.entries(cache.units)) {
|
|
27234
|
+
if (unitId.startsWith("shell:") && entry.outputHash) {
|
|
27235
|
+
shellEntries[unitId] = entry.outputHash;
|
|
27236
|
+
}
|
|
27237
|
+
}
|
|
27238
|
+
const shellHash = sha256OfJson(shellEntries);
|
|
27239
|
+
const stylesHash = cache.units["styles"]?.outputHash ?? "";
|
|
26992
27240
|
return {
|
|
26993
|
-
modules
|
|
26994
|
-
shellHash
|
|
26995
|
-
stylesHash
|
|
26996
|
-
buildTime:
|
|
27241
|
+
modules,
|
|
27242
|
+
shellHash,
|
|
27243
|
+
stylesHash,
|
|
27244
|
+
buildTime: new Date().toISOString()
|
|
26997
27245
|
};
|
|
26998
27246
|
}
|
|
26999
|
-
function
|
|
27000
|
-
if (
|
|
27247
|
+
function resolveAssetSource(from, pkgDir, rootDir) {
|
|
27248
|
+
if (from.startsWith("./") || from.startsWith("../")) {
|
|
27249
|
+
const resolved = join9(pkgDir, from);
|
|
27250
|
+
return existsSync8(resolved) ? resolved : null;
|
|
27251
|
+
}
|
|
27252
|
+
const candidates = [
|
|
27253
|
+
join9(rootDir, "node_modules", from),
|
|
27254
|
+
join9(pkgDir, "node_modules", from)
|
|
27255
|
+
];
|
|
27256
|
+
for (const c of candidates) {
|
|
27257
|
+
if (existsSync8(c))
|
|
27258
|
+
return c;
|
|
27259
|
+
}
|
|
27260
|
+
const bunCacheDir = join9(rootDir, "node_modules", ".bun");
|
|
27261
|
+
if (existsSync8(bunCacheDir)) {
|
|
27262
|
+
for (const entry of readdirSync5(bunCacheDir, { withFileTypes: true })) {
|
|
27263
|
+
if (!entry.isDirectory())
|
|
27264
|
+
continue;
|
|
27265
|
+
const candidate = join9(bunCacheDir, entry.name, "node_modules", from);
|
|
27266
|
+
if (existsSync8(candidate))
|
|
27267
|
+
return candidate;
|
|
27268
|
+
}
|
|
27269
|
+
}
|
|
27270
|
+
return null;
|
|
27271
|
+
}
|
|
27272
|
+
function readBrowserAssets(pkgDir) {
|
|
27273
|
+
const pkgJsonPath = join9(pkgDir, "package.json");
|
|
27274
|
+
if (!existsSync8(pkgJsonPath))
|
|
27275
|
+
return [];
|
|
27276
|
+
try {
|
|
27277
|
+
const pkg = JSON.parse(readFileSync8(pkgJsonPath, "utf-8"));
|
|
27278
|
+
const assets = pkg.arc?.browserAssets;
|
|
27279
|
+
if (!Array.isArray(assets))
|
|
27280
|
+
return [];
|
|
27281
|
+
return assets.filter((a) => typeof a?.from === "string" && typeof a?.to === "string");
|
|
27282
|
+
} catch {
|
|
27283
|
+
return [];
|
|
27284
|
+
}
|
|
27285
|
+
}
|
|
27286
|
+
function discoverBrowserAssets(ws) {
|
|
27287
|
+
const arcDir = join9(ws.rootDir, "node_modules", "@arcote.tech");
|
|
27288
|
+
if (!existsSync8(arcDir))
|
|
27001
27289
|
return [];
|
|
27002
27290
|
const out = [];
|
|
27003
|
-
for (const entry of
|
|
27004
|
-
|
|
27005
|
-
|
|
27006
|
-
|
|
27007
|
-
|
|
27008
|
-
|
|
27291
|
+
for (const entry of readdirSync5(arcDir, { withFileTypes: true })) {
|
|
27292
|
+
if (!entry.isDirectory() && !entry.isSymbolicLink())
|
|
27293
|
+
continue;
|
|
27294
|
+
const pkgDir = join9(arcDir, entry.name);
|
|
27295
|
+
const assets = readBrowserAssets(pkgDir);
|
|
27296
|
+
for (const asset of assets) {
|
|
27297
|
+
const src = resolveAssetSource(asset.from, pkgDir, ws.rootDir);
|
|
27298
|
+
if (!src) {
|
|
27299
|
+
err(`browserAsset not found: ${asset.from} (from @arcote.tech/${entry.name})`);
|
|
27300
|
+
continue;
|
|
27301
|
+
}
|
|
27302
|
+
out.push({ arcPkg: entry.name, from: asset.from, to: asset.to, src });
|
|
27303
|
+
}
|
|
27009
27304
|
}
|
|
27010
27305
|
return out;
|
|
27011
27306
|
}
|
|
27307
|
+
async function copyBrowserAssets(ws, cache, noCache) {
|
|
27308
|
+
mkdirSync7(ws.assetsDir, { recursive: true });
|
|
27309
|
+
const assets = discoverBrowserAssets(ws);
|
|
27310
|
+
if (assets.length === 0)
|
|
27311
|
+
return;
|
|
27312
|
+
const unitId = "browser-assets";
|
|
27313
|
+
const inputHash = sha256OfJson(assets.map((a) => ({
|
|
27314
|
+
arcPkg: a.arcPkg,
|
|
27315
|
+
from: a.from,
|
|
27316
|
+
to: a.to,
|
|
27317
|
+
mtime: mtimeOf(a.src)
|
|
27318
|
+
})));
|
|
27319
|
+
const requiredOutputs = assets.map((a) => join9(ws.assetsDir, a.to));
|
|
27320
|
+
if (!noCache && isCacheHit(cache, unitId, inputHash, requiredOutputs)) {
|
|
27321
|
+
console.log(` \u2713 cached: browser-assets (${assets.length})`);
|
|
27322
|
+
return;
|
|
27323
|
+
}
|
|
27324
|
+
console.log(` building: browser-assets (${assets.length})`);
|
|
27325
|
+
const outputHashes = {};
|
|
27326
|
+
for (const asset of assets) {
|
|
27327
|
+
const dest = join9(ws.assetsDir, asset.to);
|
|
27328
|
+
mkdirSync7(dirname6(dest), { recursive: true });
|
|
27329
|
+
copyFileSync(asset.src, dest);
|
|
27330
|
+
outputHashes[asset.to] = sha256Hex(readFileSync8(dest));
|
|
27331
|
+
}
|
|
27332
|
+
updateCache(cache, unitId, inputHash, { outputHashes });
|
|
27333
|
+
}
|
|
27012
27334
|
function collectArcPeerDeps(packages) {
|
|
27013
27335
|
const seen = new Set;
|
|
27014
27336
|
for (const pkg of ["@arcote.tech/arc", "@arcote.tech/arc-ds", "@arcote.tech/arc-react", "@arcote.tech/platform"]) {
|
|
@@ -27026,14 +27348,10 @@ function collectArcPeerDeps(packages) {
|
|
|
27026
27348
|
return [short, pkg];
|
|
27027
27349
|
});
|
|
27028
27350
|
}
|
|
27029
|
-
|
|
27030
|
-
|
|
27031
|
-
|
|
27032
|
-
|
|
27033
|
-
const reactEntries = [
|
|
27034
|
-
[
|
|
27035
|
-
"react",
|
|
27036
|
-
`import React from "react";
|
|
27351
|
+
var REACT_ENTRIES = [
|
|
27352
|
+
[
|
|
27353
|
+
"react",
|
|
27354
|
+
`import React from "react";
|
|
27037
27355
|
export default React;
|
|
27038
27356
|
export const {
|
|
27039
27357
|
Children, Component, Fragment, Profiler, PureComponent, StrictMode, Suspense,
|
|
@@ -27043,84 +27361,133 @@ export const {
|
|
|
27043
27361
|
useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore,
|
|
27044
27362
|
useTransition, version, useActionState, useOptimistic,
|
|
27045
27363
|
} = React;`
|
|
27046
|
-
|
|
27047
|
-
|
|
27048
|
-
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27053
|
-
|
|
27054
|
-
|
|
27364
|
+
],
|
|
27365
|
+
["jsx-runtime", `export { jsx, jsxs, Fragment } from "react/jsx-runtime";`],
|
|
27366
|
+
[
|
|
27367
|
+
"jsx-dev-runtime",
|
|
27368
|
+
`export { jsxDEV, Fragment } from "react/jsx-dev-runtime";`
|
|
27369
|
+
],
|
|
27370
|
+
[
|
|
27371
|
+
"react-dom",
|
|
27372
|
+
`import ReactDOM from "react-dom";
|
|
27055
27373
|
export default ReactDOM;
|
|
27056
27374
|
export const { createPortal, flushSync } = ReactDOM;`
|
|
27057
|
-
|
|
27058
|
-
|
|
27059
|
-
|
|
27060
|
-
|
|
27061
|
-
|
|
27062
|
-
|
|
27375
|
+
],
|
|
27376
|
+
[
|
|
27377
|
+
"react-dom-client",
|
|
27378
|
+
`export { createRoot, hydrateRoot } from "react-dom/client";`
|
|
27379
|
+
]
|
|
27380
|
+
];
|
|
27381
|
+
var REACT_OUTPUT_FILES = REACT_ENTRIES.map(([n]) => `${n}.js`);
|
|
27382
|
+
var SHELL_BASE_EXTERNAL = [
|
|
27383
|
+
"react",
|
|
27384
|
+
"react-dom",
|
|
27385
|
+
"react/jsx-runtime",
|
|
27386
|
+
"react/jsx-dev-runtime",
|
|
27387
|
+
"react-dom/client"
|
|
27388
|
+
];
|
|
27389
|
+
var sourceFilter2 = (rel) => {
|
|
27390
|
+
if (rel.startsWith("dist/") || rel.startsWith("dist"))
|
|
27391
|
+
return false;
|
|
27392
|
+
if (rel.includes("/node_modules/") || rel.startsWith("node_modules"))
|
|
27393
|
+
return false;
|
|
27394
|
+
if (rel.startsWith(".arc/") || rel.startsWith(".arc"))
|
|
27395
|
+
return false;
|
|
27396
|
+
return true;
|
|
27397
|
+
};
|
|
27398
|
+
function arcPkgSrcHash(rootDir, pkg) {
|
|
27399
|
+
const srcDir = join9(rootDir, "node_modules", pkg, "src");
|
|
27400
|
+
if (existsSync8(srcDir))
|
|
27401
|
+
return sha256OfDir(srcDir, sourceFilter2);
|
|
27402
|
+
return sha256OfDir(join9(rootDir, "node_modules", pkg), sourceFilter2);
|
|
27403
|
+
}
|
|
27404
|
+
async function buildShellReact(shellDir, tmpDir, rootDir, cache, noCache) {
|
|
27405
|
+
const unitId = "shell:react";
|
|
27406
|
+
const inputHash = sha256OfJson({
|
|
27407
|
+
react: readInstalledVersion(rootDir, "react"),
|
|
27408
|
+
"react-dom": readInstalledVersion(rootDir, "react-dom"),
|
|
27409
|
+
entries: REACT_ENTRIES.map(([k, v]) => [k, v])
|
|
27410
|
+
});
|
|
27411
|
+
const requiredOutputs = REACT_OUTPUT_FILES.map((f) => join9(shellDir, f));
|
|
27412
|
+
if (!noCache && isCacheHit(cache, unitId, inputHash, requiredOutputs)) {
|
|
27413
|
+
console.log(` \u2713 cached: shell:react`);
|
|
27414
|
+
return;
|
|
27415
|
+
}
|
|
27416
|
+
console.log(` building: shell:react`);
|
|
27063
27417
|
const reactEps = [];
|
|
27064
|
-
for (const [name, code] of
|
|
27065
|
-
const f =
|
|
27066
|
-
Bun.write(f, code);
|
|
27418
|
+
for (const [name, code] of REACT_ENTRIES) {
|
|
27419
|
+
const f = join9(tmpDir, `${name}.ts`);
|
|
27420
|
+
await Bun.write(f, code);
|
|
27067
27421
|
reactEps.push(f);
|
|
27068
27422
|
}
|
|
27069
|
-
const
|
|
27423
|
+
const r = await Bun.build({
|
|
27070
27424
|
entrypoints: reactEps,
|
|
27071
|
-
outdir:
|
|
27425
|
+
outdir: shellDir,
|
|
27072
27426
|
splitting: true,
|
|
27073
27427
|
format: "esm",
|
|
27074
27428
|
target: "browser",
|
|
27075
27429
|
naming: "[name].[ext]"
|
|
27076
27430
|
});
|
|
27077
|
-
if (!
|
|
27078
|
-
for (const l of
|
|
27431
|
+
if (!r.success) {
|
|
27432
|
+
for (const l of r.logs)
|
|
27079
27433
|
console.error(l);
|
|
27080
27434
|
throw new Error("Shell React build failed");
|
|
27081
27435
|
}
|
|
27082
|
-
const
|
|
27083
|
-
|
|
27084
|
-
|
|
27085
|
-
|
|
27086
|
-
|
|
27087
|
-
|
|
27088
|
-
const
|
|
27089
|
-
|
|
27090
|
-
|
|
27091
|
-
|
|
27092
|
-
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
const
|
|
27096
|
-
|
|
27097
|
-
|
|
27098
|
-
|
|
27436
|
+
const outputHash = sha256OfFiles(requiredOutputs);
|
|
27437
|
+
updateCache(cache, unitId, inputHash, { outputHash });
|
|
27438
|
+
}
|
|
27439
|
+
async function buildShellArcEntry(shortName, pkg, allArcPkgs, shellDir, tmpDir, rootDir, cache, noCache) {
|
|
27440
|
+
const unitId = `shell:arc:${shortName}`;
|
|
27441
|
+
const otherExternals = allArcPkgs.filter((p) => p !== pkg);
|
|
27442
|
+
const inputHash = sha256OfJson({
|
|
27443
|
+
pkg,
|
|
27444
|
+
version: readInstalledVersion(rootDir, pkg),
|
|
27445
|
+
src: arcPkgSrcHash(rootDir, pkg),
|
|
27446
|
+
base: SHELL_BASE_EXTERNAL,
|
|
27447
|
+
others: [...otherExternals].sort()
|
|
27448
|
+
});
|
|
27449
|
+
const outputFile = join9(shellDir, `${shortName}.js`);
|
|
27450
|
+
if (!noCache && isCacheHit(cache, unitId, inputHash, [outputFile])) {
|
|
27451
|
+
console.log(` \u2713 cached: ${unitId}`);
|
|
27452
|
+
return;
|
|
27453
|
+
}
|
|
27454
|
+
console.log(` building: ${unitId}`);
|
|
27455
|
+
const f = join9(tmpDir, `${shortName}.ts`);
|
|
27456
|
+
await Bun.write(f, `export * from "${pkg}";
|
|
27099
27457
|
`);
|
|
27100
|
-
|
|
27101
|
-
|
|
27102
|
-
|
|
27103
|
-
|
|
27104
|
-
|
|
27105
|
-
|
|
27106
|
-
|
|
27107
|
-
|
|
27108
|
-
|
|
27109
|
-
|
|
27110
|
-
|
|
27111
|
-
ONLY_SERVER: "false",
|
|
27112
|
-
ONLY_BROWSER: "true",
|
|
27113
|
-
ONLY_CLIENT: "true"
|
|
27114
|
-
}
|
|
27115
|
-
});
|
|
27116
|
-
if (!r2.success) {
|
|
27117
|
-
for (const l of r2.logs)
|
|
27118
|
-
console.error(l);
|
|
27119
|
-
throw new Error(`Shell build failed for ${pkg}`);
|
|
27458
|
+
const r = await Bun.build({
|
|
27459
|
+
entrypoints: [f],
|
|
27460
|
+
outdir: shellDir,
|
|
27461
|
+
format: "esm",
|
|
27462
|
+
target: "browser",
|
|
27463
|
+
naming: "[name].[ext]",
|
|
27464
|
+
external: [...SHELL_BASE_EXTERNAL, ...otherExternals],
|
|
27465
|
+
define: {
|
|
27466
|
+
ONLY_SERVER: "false",
|
|
27467
|
+
ONLY_BROWSER: "true",
|
|
27468
|
+
ONLY_CLIENT: "true"
|
|
27120
27469
|
}
|
|
27470
|
+
});
|
|
27471
|
+
if (!r.success) {
|
|
27472
|
+
for (const l of r.logs)
|
|
27473
|
+
console.error(l);
|
|
27474
|
+
throw new Error(`Shell build failed for ${pkg}`);
|
|
27121
27475
|
}
|
|
27122
|
-
const
|
|
27123
|
-
|
|
27476
|
+
const outputHash = sha256OfFiles([outputFile]);
|
|
27477
|
+
updateCache(cache, unitId, inputHash, { outputHash });
|
|
27478
|
+
}
|
|
27479
|
+
async function buildShell(ws, cache, noCache) {
|
|
27480
|
+
mkdirSync7(ws.shellDir, { recursive: true });
|
|
27481
|
+
const tmpDir = join9(ws.shellDir, "_tmp");
|
|
27482
|
+
mkdirSync7(tmpDir, { recursive: true });
|
|
27483
|
+
const arcEntries = collectArcPeerDeps(ws.packages);
|
|
27484
|
+
const allArcPkgs = arcEntries.map(([, pkg]) => pkg);
|
|
27485
|
+
const tasks = [
|
|
27486
|
+
() => buildShellReact(ws.shellDir, tmpDir, ws.rootDir, cache, noCache),
|
|
27487
|
+
...arcEntries.map(([short, pkg]) => () => buildShellArcEntry(short, pkg, allArcPkgs, ws.shellDir, tmpDir, ws.rootDir, cache, noCache))
|
|
27488
|
+
];
|
|
27489
|
+
await pAll(tasks);
|
|
27490
|
+
rmSync2(tmpDir, { recursive: true, force: true });
|
|
27124
27491
|
}
|
|
27125
27492
|
async function loadServerContext(packages) {
|
|
27126
27493
|
const ctxPackages = packages.filter((p) => isContextPackage(p.packageJson));
|
|
@@ -27129,13 +27496,13 @@ async function loadServerContext(packages) {
|
|
|
27129
27496
|
globalThis.ONLY_SERVER = true;
|
|
27130
27497
|
globalThis.ONLY_BROWSER = false;
|
|
27131
27498
|
globalThis.ONLY_CLIENT = false;
|
|
27132
|
-
const platformDir =
|
|
27133
|
-
const platformPkg = JSON.parse(
|
|
27134
|
-
const platformEntry =
|
|
27499
|
+
const platformDir = join9(process.cwd(), "node_modules", "@arcote.tech", "platform");
|
|
27500
|
+
const platformPkg = JSON.parse(readFileSync8(join9(platformDir, "package.json"), "utf-8"));
|
|
27501
|
+
const platformEntry = join9(platformDir, platformPkg.main ?? "src/index.ts");
|
|
27135
27502
|
await import(platformEntry);
|
|
27136
27503
|
for (const ctx of ctxPackages) {
|
|
27137
|
-
const serverDist =
|
|
27138
|
-
if (!
|
|
27504
|
+
const serverDist = join9(ctx.path, "dist", "server", "main", "index.js");
|
|
27505
|
+
if (!existsSync8(serverDist)) {
|
|
27139
27506
|
err(`Context server dist not found: ${serverDist}`);
|
|
27140
27507
|
continue;
|
|
27141
27508
|
}
|
|
@@ -27159,26 +27526,26 @@ async function loadServerContext(packages) {
|
|
|
27159
27526
|
}
|
|
27160
27527
|
|
|
27161
27528
|
// src/commands/platform-build.ts
|
|
27162
|
-
async function platformBuild() {
|
|
27529
|
+
async function platformBuild(opts = {}) {
|
|
27163
27530
|
const ws = resolveWorkspace();
|
|
27164
|
-
const manifest = await buildAll(ws);
|
|
27531
|
+
const manifest = await buildAll(ws, { noCache: opts.noCache });
|
|
27165
27532
|
ok(`Platform built \u2014 ${manifest.modules.length} module(s)`);
|
|
27166
27533
|
}
|
|
27167
27534
|
|
|
27168
27535
|
// src/commands/platform-deploy.ts
|
|
27169
|
-
import { existsSync as
|
|
27170
|
-
import { join as
|
|
27536
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
|
|
27537
|
+
import { join as join15 } from "path";
|
|
27171
27538
|
|
|
27172
27539
|
// src/deploy/bootstrap.ts
|
|
27173
|
-
import { mkdirSync as
|
|
27540
|
+
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
27174
27541
|
import { tmpdir as tmpdir3 } from "os";
|
|
27175
|
-
import { join as
|
|
27542
|
+
import { join as join13 } from "path";
|
|
27176
27543
|
|
|
27177
27544
|
// src/deploy/ansible.ts
|
|
27178
27545
|
var {spawn: spawn2 } = globalThis.Bun;
|
|
27179
|
-
import { mkdirSync as
|
|
27546
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
27180
27547
|
import { tmpdir } from "os";
|
|
27181
|
-
import { join as
|
|
27548
|
+
import { join as join10 } from "path";
|
|
27182
27549
|
|
|
27183
27550
|
// src/deploy/assets.ts
|
|
27184
27551
|
var TERRAFORM_MAIN_TF = `terraform {
|
|
@@ -27435,18 +27802,18 @@ var ASSETS = {
|
|
|
27435
27802
|
}
|
|
27436
27803
|
};
|
|
27437
27804
|
async function materializeAssets(targetDir, files) {
|
|
27438
|
-
const { mkdirSync:
|
|
27439
|
-
const { join:
|
|
27440
|
-
|
|
27805
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync8 } = await import("fs");
|
|
27806
|
+
const { join: join10 } = await import("path");
|
|
27807
|
+
mkdirSync8(targetDir, { recursive: true });
|
|
27441
27808
|
for (const [name, content] of Object.entries(files)) {
|
|
27442
|
-
|
|
27809
|
+
writeFileSync8(join10(targetDir, name), content);
|
|
27443
27810
|
}
|
|
27444
27811
|
}
|
|
27445
27812
|
|
|
27446
27813
|
// src/deploy/ansible.ts
|
|
27447
27814
|
async function runAnsible(inputs) {
|
|
27448
|
-
const workDir =
|
|
27449
|
-
|
|
27815
|
+
const workDir = join10(tmpdir(), "arc-deploy", `ansible-${Date.now()}`);
|
|
27816
|
+
mkdirSync8(workDir, { recursive: true });
|
|
27450
27817
|
await materializeAssets(workDir, ASSETS.ansible);
|
|
27451
27818
|
const user = inputs.asRoot ? "root" : inputs.target.user;
|
|
27452
27819
|
const port = inputs.ansible?.sshPort ?? inputs.target.port;
|
|
@@ -27460,7 +27827,7 @@ async function runAnsible(inputs) {
|
|
|
27460
27827
|
""
|
|
27461
27828
|
].join(`
|
|
27462
27829
|
`);
|
|
27463
|
-
|
|
27830
|
+
writeFileSync8(join10(workDir, "inventory.ini"), inventory);
|
|
27464
27831
|
const extraVars = [
|
|
27465
27832
|
`username=${inputs.target.user}`,
|
|
27466
27833
|
`ssh_port=${port}`
|
|
@@ -27585,15 +27952,15 @@ function generateCompose({ cfg }) {
|
|
|
27585
27952
|
|
|
27586
27953
|
// src/deploy/terraform.ts
|
|
27587
27954
|
var {spawn: spawn3 } = globalThis.Bun;
|
|
27588
|
-
import { existsSync as
|
|
27955
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
27589
27956
|
import { tmpdir as tmpdir2 } from "os";
|
|
27590
|
-
import { join as
|
|
27957
|
+
import { join as join11 } from "path";
|
|
27591
27958
|
async function runTerraform(inputs) {
|
|
27592
|
-
const workDir =
|
|
27593
|
-
|
|
27959
|
+
const workDir = join11(tmpdir2(), "arc-deploy", `tf-${Date.now()}`);
|
|
27960
|
+
mkdirSync9(workDir, { recursive: true });
|
|
27594
27961
|
await materializeAssets(workDir, ASSETS.terraform);
|
|
27595
27962
|
const sshPubKey = inputs.tf.sshPublicKey ?? expandHome("~/.ssh/id_ed25519.pub");
|
|
27596
|
-
if (!
|
|
27963
|
+
if (!existsSync9(expandHome(sshPubKey))) {
|
|
27597
27964
|
throw new Error(`SSH public key not found at ${sshPubKey}. Set provision.terraform.sshPublicKey in deploy.arc.json.`);
|
|
27598
27965
|
}
|
|
27599
27966
|
const tfvars = [
|
|
@@ -27606,7 +27973,7 @@ async function runTerraform(inputs) {
|
|
|
27606
27973
|
].join(`
|
|
27607
27974
|
`) + `
|
|
27608
27975
|
`;
|
|
27609
|
-
|
|
27976
|
+
writeFileSync9(join11(workDir, "terraform.tfvars"), tfvars);
|
|
27610
27977
|
await runTf(workDir, ["init", "-input=false", "-no-color"]);
|
|
27611
27978
|
await runTf(workDir, [
|
|
27612
27979
|
"apply",
|
|
@@ -27658,21 +28025,21 @@ function expandHome(p) {
|
|
|
27658
28025
|
}
|
|
27659
28026
|
|
|
27660
28027
|
// src/deploy/config.ts
|
|
27661
|
-
import { existsSync as
|
|
27662
|
-
import { join as
|
|
28028
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
28029
|
+
import { join as join12 } from "path";
|
|
27663
28030
|
var DEPLOY_CONFIG_FILE = "deploy.arc.json";
|
|
27664
28031
|
function deployConfigPath(rootDir) {
|
|
27665
|
-
return
|
|
28032
|
+
return join12(rootDir, DEPLOY_CONFIG_FILE);
|
|
27666
28033
|
}
|
|
27667
28034
|
function deployConfigExists(rootDir) {
|
|
27668
|
-
return
|
|
28035
|
+
return existsSync10(deployConfigPath(rootDir));
|
|
27669
28036
|
}
|
|
27670
28037
|
function loadDeployConfig(rootDir) {
|
|
27671
28038
|
const path4 = deployConfigPath(rootDir);
|
|
27672
|
-
if (!
|
|
28039
|
+
if (!existsSync10(path4)) {
|
|
27673
28040
|
throw new Error(`Missing ${DEPLOY_CONFIG_FILE} at ${path4}`);
|
|
27674
28041
|
}
|
|
27675
|
-
const raw =
|
|
28042
|
+
const raw = readFileSync9(path4, "utf-8");
|
|
27676
28043
|
let parsed;
|
|
27677
28044
|
try {
|
|
27678
28045
|
parsed = JSON.parse(raw);
|
|
@@ -27683,7 +28050,7 @@ function loadDeployConfig(rootDir) {
|
|
|
27683
28050
|
return validateDeployConfig(expanded);
|
|
27684
28051
|
}
|
|
27685
28052
|
function saveDeployConfig(rootDir, cfg) {
|
|
27686
|
-
|
|
28053
|
+
writeFileSync10(deployConfigPath(rootDir), JSON.stringify(cfg, null, 2) + `
|
|
27687
28054
|
`);
|
|
27688
28055
|
}
|
|
27689
28056
|
var VAR_REGEX = /\$\{([A-Z0-9_]+)\}|\$([A-Z0-9_]+)/g;
|
|
@@ -28083,22 +28450,22 @@ async function bootstrap(inputs) {
|
|
|
28083
28450
|
}
|
|
28084
28451
|
async function upStack(inputs) {
|
|
28085
28452
|
const { cfg } = inputs;
|
|
28086
|
-
const workDir =
|
|
28087
|
-
|
|
28088
|
-
|
|
28089
|
-
|
|
28453
|
+
const workDir = join13(tmpdir3(), "arc-deploy", `stack-${Date.now()}`);
|
|
28454
|
+
mkdirSync10(workDir, { recursive: true });
|
|
28455
|
+
writeFileSync11(join13(workDir, "Caddyfile"), generateCaddyfile(cfg));
|
|
28456
|
+
writeFileSync11(join13(workDir, "docker-compose.yml"), generateCompose({ cfg }));
|
|
28090
28457
|
await assertExec(cfg.target, `sudo mkdir -p ${cfg.target.remoteDir} && sudo chown ${cfg.target.user}:${cfg.target.user} ${cfg.target.remoteDir}`);
|
|
28091
28458
|
for (const name of Object.keys(cfg.envs)) {
|
|
28092
28459
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/${name}`);
|
|
28093
28460
|
}
|
|
28094
|
-
await scpUpload(cfg.target,
|
|
28095
|
-
await scpUpload(cfg.target,
|
|
28461
|
+
await scpUpload(cfg.target, join13(workDir, "Caddyfile"), `${cfg.target.remoteDir}/Caddyfile`);
|
|
28462
|
+
await scpUpload(cfg.target, join13(workDir, "docker-compose.yml"), `${cfg.target.remoteDir}/docker-compose.yml`);
|
|
28096
28463
|
await assertExec(cfg.target, `cd ${cfg.target.remoteDir} && docker compose pull --ignore-pull-failures && docker compose up -d`);
|
|
28097
28464
|
}
|
|
28098
28465
|
|
|
28099
28466
|
// src/deploy/remote-sync.ts
|
|
28100
|
-
import { existsSync as
|
|
28101
|
-
import { join as
|
|
28467
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
28468
|
+
import { join as join14, relative as relative4 } from "path";
|
|
28102
28469
|
function diffManifests(local, remote) {
|
|
28103
28470
|
const remoteByName = new Map(remote.modules.map((m) => [m.name, m]));
|
|
28104
28471
|
const changedModules = local.modules.filter((m) => remoteByName.get(m.name)?.hash !== m.hash);
|
|
@@ -28115,11 +28482,11 @@ async function syncEnv(inputs) {
|
|
|
28115
28482
|
throw new Error(`Unknown env: ${env2}`);
|
|
28116
28483
|
const remotePath = `${cfg.target.remoteDir}/${env2}`;
|
|
28117
28484
|
await rsyncDir(cfg.target, projectDir, remotePath);
|
|
28118
|
-
const localManifestPath =
|
|
28119
|
-
if (!
|
|
28485
|
+
const localManifestPath = join14(ws.modulesDir, "manifest.json");
|
|
28486
|
+
if (!existsSync11(localManifestPath)) {
|
|
28120
28487
|
throw new Error(`Local build missing at ${localManifestPath}. Run arc platform build first.`);
|
|
28121
28488
|
}
|
|
28122
|
-
const localManifest = JSON.parse(
|
|
28489
|
+
const localManifest = JSON.parse(readFileSync10(localManifestPath, "utf-8"));
|
|
28123
28490
|
const localPort = 15500 + hashEnvToOffset(env2);
|
|
28124
28491
|
const tunnel = await openTunnel(cfg.target, localPort, "127.0.0.1", 2019);
|
|
28125
28492
|
try {
|
|
@@ -28134,8 +28501,8 @@ async function syncEnv(inputs) {
|
|
|
28134
28501
|
const shellFiles = collectFiles(ws.shellDir);
|
|
28135
28502
|
const form = new FormData;
|
|
28136
28503
|
for (const absPath of shellFiles) {
|
|
28137
|
-
const rel =
|
|
28138
|
-
form.append(rel, new Blob([
|
|
28504
|
+
const rel = relative4(ws.shellDir, absPath);
|
|
28505
|
+
form.append(rel, new Blob([readFileSync10(absPath)]), rel);
|
|
28139
28506
|
}
|
|
28140
28507
|
const res2 = await fetch(`${base2}/api/deploy/shell`, {
|
|
28141
28508
|
method: "POST",
|
|
@@ -28147,9 +28514,9 @@ async function syncEnv(inputs) {
|
|
|
28147
28514
|
if (diff.stylesChanged) {
|
|
28148
28515
|
const form = new FormData;
|
|
28149
28516
|
for (const name of ["styles.css", "theme.css"]) {
|
|
28150
|
-
const p =
|
|
28151
|
-
if (
|
|
28152
|
-
form.append(name, new Blob([
|
|
28517
|
+
const p = join14(ws.arcDir, name);
|
|
28518
|
+
if (existsSync11(p)) {
|
|
28519
|
+
form.append(name, new Blob([readFileSync10(p)]), name);
|
|
28153
28520
|
}
|
|
28154
28521
|
}
|
|
28155
28522
|
const res2 = await fetch(`${base2}/api/deploy/shell`, {
|
|
@@ -28162,8 +28529,8 @@ async function syncEnv(inputs) {
|
|
|
28162
28529
|
if (diff.changedModules.length > 0) {
|
|
28163
28530
|
const form = new FormData;
|
|
28164
28531
|
for (const mod of diff.changedModules) {
|
|
28165
|
-
const p =
|
|
28166
|
-
form.append(mod.file, new Blob([
|
|
28532
|
+
const p = join14(ws.modulesDir, mod.file);
|
|
28533
|
+
form.append(mod.file, new Blob([readFileSync10(p)]), mod.file);
|
|
28167
28534
|
}
|
|
28168
28535
|
const res2 = await fetch(`${base2}/api/deploy/modules`, {
|
|
28169
28536
|
method: "POST",
|
|
@@ -28190,12 +28557,12 @@ async function syncEnv(inputs) {
|
|
|
28190
28557
|
}
|
|
28191
28558
|
}
|
|
28192
28559
|
function collectFiles(dir) {
|
|
28193
|
-
if (!
|
|
28560
|
+
if (!existsSync11(dir))
|
|
28194
28561
|
return [];
|
|
28195
|
-
const { readdirSync:
|
|
28562
|
+
const { readdirSync: readdirSync6 } = __require("fs");
|
|
28196
28563
|
const out = [];
|
|
28197
|
-
for (const entry of
|
|
28198
|
-
const p =
|
|
28564
|
+
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
28565
|
+
const p = join14(dir, entry.name);
|
|
28199
28566
|
if (entry.isDirectory())
|
|
28200
28567
|
out.push(...collectFiles(p));
|
|
28201
28568
|
else if (entry.isFile())
|
|
@@ -28907,13 +29274,13 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
28907
29274
|
err(`Unknown env "${envArg}". Known: ${Object.keys(cfg.envs).join(", ")}`);
|
|
28908
29275
|
process.exit(1);
|
|
28909
29276
|
})() : Object.keys(cfg.envs);
|
|
28910
|
-
const manifestPath =
|
|
28911
|
-
const needBuild = options.rebuild || !
|
|
29277
|
+
const manifestPath = join15(ws.modulesDir, "manifest.json");
|
|
29278
|
+
const needBuild = options.rebuild || !existsSync12(manifestPath);
|
|
28912
29279
|
if (needBuild && !options.skipBuild) {
|
|
28913
29280
|
log2("Building platform...");
|
|
28914
|
-
await buildAll(ws);
|
|
29281
|
+
await buildAll(ws, { noCache: options.rebuild });
|
|
28915
29282
|
ok("Build complete");
|
|
28916
|
-
} else if (!
|
|
29283
|
+
} else if (!existsSync12(manifestPath)) {
|
|
28917
29284
|
err("No build found and --skip-build was set.");
|
|
28918
29285
|
process.exit(1);
|
|
28919
29286
|
}
|
|
@@ -28956,24 +29323,24 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
28956
29323
|
}
|
|
28957
29324
|
function readCliVersion() {
|
|
28958
29325
|
try {
|
|
28959
|
-
const pkgPath =
|
|
28960
|
-
const pkg = JSON.parse(
|
|
29326
|
+
const pkgPath = join15(import.meta.dir, "..", "..", "package.json");
|
|
29327
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
28961
29328
|
return pkg.version ?? "unknown";
|
|
28962
29329
|
} catch {
|
|
28963
29330
|
return "unknown";
|
|
28964
29331
|
}
|
|
28965
29332
|
}
|
|
28966
29333
|
async function hashDeployConfig(rootDir) {
|
|
28967
|
-
const p2 =
|
|
28968
|
-
const content =
|
|
29334
|
+
const p2 = join15(rootDir, "deploy.arc.json");
|
|
29335
|
+
const content = readFileSync11(p2);
|
|
28969
29336
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
28970
29337
|
hasher.update(content);
|
|
28971
29338
|
return hasher.digest("hex").slice(0, 16);
|
|
28972
29339
|
}
|
|
28973
29340
|
|
|
28974
29341
|
// src/commands/platform-dev.ts
|
|
28975
|
-
import { existsSync as
|
|
28976
|
-
import { join as
|
|
29342
|
+
import { existsSync as existsSync15, watch } from "fs";
|
|
29343
|
+
import { join as join18 } from "path";
|
|
28977
29344
|
|
|
28978
29345
|
// ../host/src/create-server.ts
|
|
28979
29346
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
|
|
@@ -30292,7 +30659,10 @@ async function createArcServer(config) {
|
|
|
30292
30659
|
"Access-Control-Allow-Origin": origin,
|
|
30293
30660
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
|
30294
30661
|
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Arc-Scope, X-Arc-Tokens",
|
|
30295
|
-
"Access-Control-Allow-Credentials": "true"
|
|
30662
|
+
"Access-Control-Allow-Credentials": "true",
|
|
30663
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
|
30664
|
+
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
30665
|
+
"Cross-Origin-Resource-Policy": "cross-origin"
|
|
30296
30666
|
};
|
|
30297
30667
|
}
|
|
30298
30668
|
const corsHeaders = buildCorsHeaders();
|
|
@@ -30420,12 +30790,12 @@ async function createArcServer(config) {
|
|
|
30420
30790
|
};
|
|
30421
30791
|
}
|
|
30422
30792
|
// src/platform/server.ts
|
|
30423
|
-
import { existsSync as
|
|
30424
|
-
import { join as
|
|
30793
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync12 } from "fs";
|
|
30794
|
+
import { join as join17 } from "path";
|
|
30425
30795
|
|
|
30426
30796
|
// src/platform/deploy-api.ts
|
|
30427
|
-
import { existsSync as
|
|
30428
|
-
import { dirname as dirname7, join as
|
|
30797
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync11, readFileSync as readFileSync12, writeFileSync as writeFileSync12 } from "fs";
|
|
30798
|
+
import { dirname as dirname7, join as join16, normalize as normalize2, relative as relative5, resolve } from "path";
|
|
30429
30799
|
function createDeployApiHandler(opts) {
|
|
30430
30800
|
return async (req, url, ctx) => {
|
|
30431
30801
|
const p3 = url.pathname;
|
|
@@ -30442,7 +30812,7 @@ function createDeployApiHandler(opts) {
|
|
|
30442
30812
|
if (!validateManifest(body)) {
|
|
30443
30813
|
return Response.json({ error: "Invalid manifest body" }, { status: 400, headers: ctx.corsHeaders });
|
|
30444
30814
|
}
|
|
30445
|
-
|
|
30815
|
+
writeFileSync12(join16(opts.ws.modulesDir, "manifest.json"), JSON.stringify(body, null, 2));
|
|
30446
30816
|
opts.setManifest(body);
|
|
30447
30817
|
opts.notifyReload(body);
|
|
30448
30818
|
return Response.json({ ok: true, moduleCount: body.modules.length }, { headers: ctx.corsHeaders });
|
|
@@ -30468,8 +30838,8 @@ function createDeployApiHandler(opts) {
|
|
|
30468
30838
|
const writtenShell = await writeUploadedFileList(shellFiles, opts.ws.shellDir);
|
|
30469
30839
|
const writtenRoot = [];
|
|
30470
30840
|
for (const { name, file } of rootFiles) {
|
|
30471
|
-
const target =
|
|
30472
|
-
|
|
30841
|
+
const target = join16(opts.ws.arcDir, name);
|
|
30842
|
+
writeFileSync12(target, Buffer.from(await file.arrayBuffer()));
|
|
30473
30843
|
writtenRoot.push(name);
|
|
30474
30844
|
}
|
|
30475
30845
|
return Response.json({ ok: true, written: [...writtenShell, ...writtenRoot] }, { headers: ctx.corsHeaders });
|
|
@@ -30494,16 +30864,16 @@ function isFile(v3) {
|
|
|
30494
30864
|
async function writeUploadedFileList(files, targetDir) {
|
|
30495
30865
|
const written = [];
|
|
30496
30866
|
const safeRoot = resolve(targetDir);
|
|
30497
|
-
|
|
30867
|
+
mkdirSync11(safeRoot, { recursive: true });
|
|
30498
30868
|
for (const file of files) {
|
|
30499
30869
|
const rel = normalize2(file.name);
|
|
30500
30870
|
const full = resolve(safeRoot, rel);
|
|
30501
30871
|
if (!full.startsWith(safeRoot + "/") && full !== safeRoot) {
|
|
30502
30872
|
throw new Error(`Path traversal rejected: ${file.name}`);
|
|
30503
30873
|
}
|
|
30504
|
-
|
|
30505
|
-
|
|
30506
|
-
written.push(
|
|
30874
|
+
mkdirSync11(dirname7(full), { recursive: true });
|
|
30875
|
+
writeFileSync12(full, Buffer.from(await file.arrayBuffer()));
|
|
30876
|
+
written.push(relative5(safeRoot, full) || rel);
|
|
30507
30877
|
}
|
|
30508
30878
|
return written;
|
|
30509
30879
|
}
|
|
@@ -30570,14 +30940,15 @@ var MIME = {
|
|
|
30570
30940
|
".ico": "image/x-icon",
|
|
30571
30941
|
".woff2": "font/woff2",
|
|
30572
30942
|
".woff": "font/woff",
|
|
30573
|
-
".ttf": "font/ttf"
|
|
30943
|
+
".ttf": "font/ttf",
|
|
30944
|
+
".wasm": "application/wasm"
|
|
30574
30945
|
};
|
|
30575
30946
|
function getMime(path4) {
|
|
30576
30947
|
const ext2 = path4.substring(path4.lastIndexOf("."));
|
|
30577
30948
|
return MIME[ext2] ?? "application/octet-stream";
|
|
30578
30949
|
}
|
|
30579
30950
|
function serveFile(filePath, headers = {}) {
|
|
30580
|
-
if (!
|
|
30951
|
+
if (!existsSync14(filePath))
|
|
30581
30952
|
return new Response("Not Found", { status: 404 });
|
|
30582
30953
|
return new Response(Bun.file(filePath), {
|
|
30583
30954
|
headers: { "Content-Type": getMime(filePath), ...headers }
|
|
@@ -30666,7 +31037,7 @@ function staticFilesHandler(ws, devMode, moduleAccessMap) {
|
|
|
30666
31037
|
return (_req, url, ctx) => {
|
|
30667
31038
|
const path4 = url.pathname;
|
|
30668
31039
|
if (path4.startsWith("/shell/"))
|
|
30669
|
-
return serveFile(
|
|
31040
|
+
return serveFile(join17(ws.shellDir, path4.slice(7)), ctx.corsHeaders);
|
|
30670
31041
|
if (path4.startsWith("/modules/")) {
|
|
30671
31042
|
const fileWithParams = path4.slice(9);
|
|
30672
31043
|
const filename = fileWithParams.split("?")[0];
|
|
@@ -30678,23 +31049,25 @@ function staticFilesHandler(ws, devMode, moduleAccessMap) {
|
|
|
30678
31049
|
return new Response("Forbidden", { status: 403, headers: ctx.corsHeaders });
|
|
30679
31050
|
}
|
|
30680
31051
|
}
|
|
30681
|
-
return serveFile(
|
|
31052
|
+
return serveFile(join17(ws.modulesDir, filename), {
|
|
30682
31053
|
...ctx.corsHeaders,
|
|
30683
31054
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
30684
31055
|
});
|
|
30685
31056
|
}
|
|
30686
31057
|
if (path4.startsWith("/locales/"))
|
|
30687
|
-
return serveFile(
|
|
31058
|
+
return serveFile(join17(ws.arcDir, path4.slice(1)), ctx.corsHeaders);
|
|
31059
|
+
if (path4.startsWith("/assets/"))
|
|
31060
|
+
return serveFile(join17(ws.assetsDir, path4.slice(8)), ctx.corsHeaders);
|
|
30688
31061
|
if (path4 === "/styles.css")
|
|
30689
|
-
return serveFile(
|
|
31062
|
+
return serveFile(join17(ws.arcDir, "styles.css"), ctx.corsHeaders);
|
|
30690
31063
|
if (path4 === "/theme.css")
|
|
30691
|
-
return serveFile(
|
|
31064
|
+
return serveFile(join17(ws.arcDir, "theme.css"), ctx.corsHeaders);
|
|
30692
31065
|
if ((path4 === "/manifest.json" || path4 === "/manifest.webmanifest") && ws.manifest) {
|
|
30693
31066
|
return serveFile(ws.manifest.path, ctx.corsHeaders);
|
|
30694
31067
|
}
|
|
30695
31068
|
if (path4.lastIndexOf(".") > path4.lastIndexOf("/")) {
|
|
30696
|
-
const publicFile =
|
|
30697
|
-
if (
|
|
31069
|
+
const publicFile = join17(ws.publicDir, path4.slice(1));
|
|
31070
|
+
if (existsSync14(publicFile))
|
|
30698
31071
|
return serveFile(publicFile, ctx.corsHeaders);
|
|
30699
31072
|
}
|
|
30700
31073
|
return null;
|
|
@@ -30791,7 +31164,10 @@ async function startPlatformServer(opts) {
|
|
|
30791
31164
|
const cors = {
|
|
30792
31165
|
"Access-Control-Allow-Origin": "*",
|
|
30793
31166
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
|
30794
|
-
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Arc-Tokens"
|
|
31167
|
+
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Arc-Tokens",
|
|
31168
|
+
"Cross-Origin-Opener-Policy": "same-origin",
|
|
31169
|
+
"Cross-Origin-Embedder-Policy": "require-corp",
|
|
31170
|
+
"Cross-Origin-Resource-Policy": "cross-origin"
|
|
30795
31171
|
};
|
|
30796
31172
|
const server = Bun.serve({
|
|
30797
31173
|
port,
|
|
@@ -30829,10 +31205,10 @@ async function startPlatformServer(opts) {
|
|
|
30829
31205
|
};
|
|
30830
31206
|
}
|
|
30831
31207
|
const { createBunSQLiteAdapterFactory: createBunSQLiteAdapterFactory2 } = await Promise.resolve().then(() => (init_dist(), exports_dist2));
|
|
30832
|
-
const dbPath = opts.dbPath ||
|
|
31208
|
+
const dbPath = opts.dbPath || join17(ws.arcDir, "data", "arc.db");
|
|
30833
31209
|
const dbDir = dbPath.substring(0, dbPath.lastIndexOf("/"));
|
|
30834
31210
|
if (dbDir)
|
|
30835
|
-
|
|
31211
|
+
mkdirSync12(dbDir, { recursive: true });
|
|
30836
31212
|
const arcServer = await createArcServer({
|
|
30837
31213
|
context,
|
|
30838
31214
|
dbAdapterFactory: createBunSQLiteAdapterFactory2(dbPath),
|
|
@@ -30857,10 +31233,10 @@ async function startPlatformServer(opts) {
|
|
|
30857
31233
|
}
|
|
30858
31234
|
|
|
30859
31235
|
// src/commands/platform-dev.ts
|
|
30860
|
-
async function platformDev() {
|
|
31236
|
+
async function platformDev(opts = {}) {
|
|
30861
31237
|
const ws = resolveWorkspace();
|
|
30862
31238
|
const port = 5005;
|
|
30863
|
-
let manifest = await buildAll(ws);
|
|
31239
|
+
let manifest = await buildAll(ws, { noCache: opts.noCache });
|
|
30864
31240
|
log2("Loading server context...");
|
|
30865
31241
|
const { context, moduleAccess } = await loadServerContext(ws.packages);
|
|
30866
31242
|
if (context) {
|
|
@@ -30875,7 +31251,7 @@ async function platformDev() {
|
|
|
30875
31251
|
manifest,
|
|
30876
31252
|
context,
|
|
30877
31253
|
moduleAccess,
|
|
30878
|
-
dbPath:
|
|
31254
|
+
dbPath: join18(ws.rootDir, ".arc", "data", "dev.db"),
|
|
30879
31255
|
devMode: true,
|
|
30880
31256
|
arcEntries
|
|
30881
31257
|
});
|
|
@@ -30885,53 +31261,44 @@ async function platformDev() {
|
|
|
30885
31261
|
log2("Watching for changes...");
|
|
30886
31262
|
let rebuildTimer = null;
|
|
30887
31263
|
let isRebuilding = false;
|
|
31264
|
+
const triggerRebuild = () => {
|
|
31265
|
+
if (rebuildTimer)
|
|
31266
|
+
clearTimeout(rebuildTimer);
|
|
31267
|
+
rebuildTimer = setTimeout(async () => {
|
|
31268
|
+
if (isRebuilding)
|
|
31269
|
+
return;
|
|
31270
|
+
isRebuilding = true;
|
|
31271
|
+
log2("Rebuilding...");
|
|
31272
|
+
try {
|
|
31273
|
+
manifest = await buildAll(ws);
|
|
31274
|
+
platform3.setManifest(manifest);
|
|
31275
|
+
platform3.notifyReload(manifest);
|
|
31276
|
+
ok(`Rebuilt \u2014 ${manifest.modules.length} module(s)`);
|
|
31277
|
+
} catch (e2) {
|
|
31278
|
+
console.error(`Rebuild failed: ${e2}`);
|
|
31279
|
+
} finally {
|
|
31280
|
+
isRebuilding = false;
|
|
31281
|
+
}
|
|
31282
|
+
}, 300);
|
|
31283
|
+
};
|
|
30888
31284
|
for (const pkg of ws.packages) {
|
|
30889
|
-
const srcDir =
|
|
30890
|
-
if (!
|
|
31285
|
+
const srcDir = join18(pkg.path, "src");
|
|
31286
|
+
if (!existsSync15(srcDir))
|
|
30891
31287
|
continue;
|
|
30892
31288
|
watch(srcDir, { recursive: true }, (_event, filename) => {
|
|
30893
31289
|
if (!filename || filename.includes(".arc") || filename.endsWith(".d.ts") || filename.includes("node_modules") || filename.includes("dist"))
|
|
30894
31290
|
return;
|
|
30895
31291
|
if (!filename.endsWith(".ts") && !filename.endsWith(".tsx"))
|
|
30896
31292
|
return;
|
|
30897
|
-
|
|
30898
|
-
clearTimeout(rebuildTimer);
|
|
30899
|
-
rebuildTimer = setTimeout(async () => {
|
|
30900
|
-
if (isRebuilding)
|
|
30901
|
-
return;
|
|
30902
|
-
isRebuilding = true;
|
|
30903
|
-
log2("Rebuilding...");
|
|
30904
|
-
try {
|
|
30905
|
-
manifest = await buildPackages(ws.rootDir, ws.modulesDir, ws.packages);
|
|
30906
|
-
await buildStyles(ws.rootDir, ws.arcDir);
|
|
30907
|
-
platform3.setManifest(manifest);
|
|
30908
|
-
platform3.notifyReload(manifest);
|
|
30909
|
-
ok(`Rebuilt ${manifest.modules.length} module(s)`);
|
|
30910
|
-
} catch (e2) {
|
|
30911
|
-
console.error(`Rebuild failed: ${e2}`);
|
|
30912
|
-
} finally {
|
|
30913
|
-
isRebuilding = false;
|
|
30914
|
-
}
|
|
30915
|
-
}, 300);
|
|
31293
|
+
triggerRebuild();
|
|
30916
31294
|
});
|
|
30917
31295
|
}
|
|
30918
|
-
const localesDir =
|
|
30919
|
-
if (
|
|
30920
|
-
let poTimer = null;
|
|
31296
|
+
const localesDir = join18(ws.rootDir, "locales");
|
|
31297
|
+
if (existsSync15(localesDir)) {
|
|
30921
31298
|
watch(localesDir, { recursive: false }, (_event, filename) => {
|
|
30922
31299
|
if (!filename?.endsWith(".po"))
|
|
30923
31300
|
return;
|
|
30924
|
-
|
|
30925
|
-
clearTimeout(poTimer);
|
|
30926
|
-
poTimer = setTimeout(async () => {
|
|
30927
|
-
try {
|
|
30928
|
-
compileAllCatalogs(localesDir, join16(ws.arcDir, "locales"));
|
|
30929
|
-
ok("Translations recompiled");
|
|
30930
|
-
platform3.notifyReload(manifest);
|
|
30931
|
-
} catch (e2) {
|
|
30932
|
-
console.error(`Translation compile failed: ${e2}`);
|
|
30933
|
-
}
|
|
30934
|
-
}, 200);
|
|
31301
|
+
triggerRebuild();
|
|
30935
31302
|
});
|
|
30936
31303
|
}
|
|
30937
31304
|
const cleanup = () => {
|
|
@@ -30943,17 +31310,17 @@ async function platformDev() {
|
|
|
30943
31310
|
}
|
|
30944
31311
|
|
|
30945
31312
|
// src/commands/platform-start.ts
|
|
30946
|
-
import { existsSync as
|
|
30947
|
-
import { join as
|
|
31313
|
+
import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
|
|
31314
|
+
import { join as join19 } from "path";
|
|
30948
31315
|
async function platformStart() {
|
|
30949
31316
|
const ws = resolveWorkspace();
|
|
30950
31317
|
const port = parseInt(process.env.PORT || "5005", 10);
|
|
30951
|
-
const manifestPath =
|
|
30952
|
-
if (!
|
|
31318
|
+
const manifestPath = join19(ws.modulesDir, "manifest.json");
|
|
31319
|
+
if (!existsSync16(manifestPath)) {
|
|
30953
31320
|
err("No build found. Run `arc platform build` first.");
|
|
30954
31321
|
process.exit(1);
|
|
30955
31322
|
}
|
|
30956
|
-
const manifest = JSON.parse(
|
|
31323
|
+
const manifest = JSON.parse(readFileSync13(manifestPath, "utf-8"));
|
|
30957
31324
|
log2("Loading server context...");
|
|
30958
31325
|
const { context, moduleAccess } = await loadServerContext(ws.packages);
|
|
30959
31326
|
if (context) {
|
|
@@ -30971,7 +31338,7 @@ async function platformStart() {
|
|
|
30971
31338
|
manifest,
|
|
30972
31339
|
context,
|
|
30973
31340
|
moduleAccess,
|
|
30974
|
-
dbPath:
|
|
31341
|
+
dbPath: join19(ws.rootDir, ".arc", "data", "prod.db"),
|
|
30975
31342
|
devMode: false,
|
|
30976
31343
|
deployApi,
|
|
30977
31344
|
arcEntries
|
|
@@ -30993,8 +31360,8 @@ program2.name("arc").description("CLI tool for Arc framework").version("0.0.3");
|
|
|
30993
31360
|
program2.command("dev").description("Run development mode for Arc framework").action(dev);
|
|
30994
31361
|
program2.command("build").description("Build all clients and declarations").action(build);
|
|
30995
31362
|
var platform3 = program2.command("platform").description("Platform commands \u2014 run full stack (server + UI)");
|
|
30996
|
-
platform3.command("dev").description("Start platform in dev mode (Bun server + Vite HMR)").action(platformDev);
|
|
30997
|
-
platform3.command("build").description("Build platform for production").action(platformBuild);
|
|
31363
|
+
platform3.command("dev").description("Start platform in dev mode (Bun server + Vite HMR)").option("--no-cache", "Force full rebuild on startup").action((opts) => platformDev({ noCache: opts.cache === false }));
|
|
31364
|
+
platform3.command("build").description("Build platform for production").option("--no-cache", "Force full rebuild").action((opts) => platformBuild({ noCache: opts.cache === false }));
|
|
30998
31365
|
platform3.command("start").description("Start platform in production mode (requires prior build)").action(platformStart);
|
|
30999
31366
|
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").action((env2, opts) => platformDeploy(env2, opts));
|
|
31000
31367
|
program2.parse(process.argv);
|