@arcote.tech/arc-cli 0.5.5 → 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 +792 -428
- 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
|
@@ -13620,6 +13620,9 @@ class AuthAdapter {
|
|
|
13620
13620
|
localStorage.removeItem(TOKEN_PREFIX + scope);
|
|
13621
13621
|
}
|
|
13622
13622
|
}
|
|
13623
|
+
setDecoded(decoded, scope = "default") {
|
|
13624
|
+
this.scopes.set(scope, { raw: "", decoded });
|
|
13625
|
+
}
|
|
13623
13626
|
loadPersisted() {
|
|
13624
13627
|
if (!hasLocalStorage())
|
|
13625
13628
|
return;
|
|
@@ -13816,7 +13819,8 @@ class EventWire {
|
|
|
13816
13819
|
localId: e2.localId,
|
|
13817
13820
|
type: e2.type,
|
|
13818
13821
|
payload: e2.payload,
|
|
13819
|
-
createdAt: e2.createdAt
|
|
13822
|
+
createdAt: e2.createdAt,
|
|
13823
|
+
authContext: e2.authContext
|
|
13820
13824
|
}))
|
|
13821
13825
|
}));
|
|
13822
13826
|
}
|
|
@@ -13968,11 +13972,13 @@ class LocalEventPublisher2 {
|
|
|
13968
13972
|
}
|
|
13969
13973
|
async publish(event) {
|
|
13970
13974
|
const allChanges = [];
|
|
13975
|
+
const eventAuthContext = event.authContext ?? null;
|
|
13971
13976
|
const storedEvent = {
|
|
13972
13977
|
_id: event.id,
|
|
13973
13978
|
type: event.type,
|
|
13974
13979
|
payload: JSON.stringify(event.payload),
|
|
13975
|
-
createdAt: event.createdAt.toISOString()
|
|
13980
|
+
createdAt: event.createdAt.toISOString(),
|
|
13981
|
+
authContext: eventAuthContext ? JSON.stringify(eventAuthContext) : null
|
|
13976
13982
|
};
|
|
13977
13983
|
allChanges.push({
|
|
13978
13984
|
store: EVENT_TABLES.events,
|
|
@@ -14645,11 +14651,14 @@ class AggregateBase {
|
|
|
14645
14651
|
if (!adapters.eventPublisher) {
|
|
14646
14652
|
throw new Error(`Cannot emit event "${arcEvent.name}": no eventPublisher adapter available`);
|
|
14647
14653
|
}
|
|
14654
|
+
const decoded = adapters.authAdapter?.getDecoded() ?? null;
|
|
14655
|
+
const authContext = decoded ? { tokenName: decoded.tokenName, params: decoded.params } : null;
|
|
14648
14656
|
const eventInstance = {
|
|
14649
14657
|
type: arcEvent.name,
|
|
14650
14658
|
payload,
|
|
14651
14659
|
id: `${Date.now()}_${Math.random().toString(36).slice(2)}`,
|
|
14652
|
-
createdAt: new Date
|
|
14660
|
+
createdAt: new Date,
|
|
14661
|
+
authContext
|
|
14653
14662
|
};
|
|
14654
14663
|
await adapters.eventPublisher.publish(eventInstance);
|
|
14655
14664
|
}
|
|
@@ -15347,7 +15356,8 @@ class StreamingEventPublisher {
|
|
|
15347
15356
|
localId: event3.id,
|
|
15348
15357
|
type: event3.type,
|
|
15349
15358
|
payload: event3.payload,
|
|
15350
|
-
createdAt: event3.createdAt.toISOString()
|
|
15359
|
+
createdAt: event3.createdAt.toISOString(),
|
|
15360
|
+
authContext: event3.authContext ?? null
|
|
15351
15361
|
}
|
|
15352
15362
|
]);
|
|
15353
15363
|
}
|
|
@@ -17221,11 +17231,14 @@ var init_dist = __esm(() => {
|
|
|
17221
17231
|
if (!adapters.eventPublisher) {
|
|
17222
17232
|
throw new Error(`Event "${this.data.name}" cannot be emitted: no eventPublisher adapter available`);
|
|
17223
17233
|
}
|
|
17234
|
+
const decoded = adapters.authAdapter?.getDecoded() ?? null;
|
|
17235
|
+
const authContext = decoded ? { tokenName: decoded.tokenName, params: decoded.params } : null;
|
|
17224
17236
|
const event = {
|
|
17225
17237
|
type: this.data.name,
|
|
17226
17238
|
payload,
|
|
17227
17239
|
id: this.eventId.generate(),
|
|
17228
|
-
createdAt: new Date
|
|
17240
|
+
createdAt: new Date,
|
|
17241
|
+
authContext
|
|
17229
17242
|
};
|
|
17230
17243
|
await adapters.eventPublisher.publish(event);
|
|
17231
17244
|
}
|
|
@@ -17511,31 +17524,15 @@ var init_dist = __esm(() => {
|
|
|
17511
17524
|
if (adapters.authAdapter?.isAuthenticated()) {
|
|
17512
17525
|
return adapters;
|
|
17513
17526
|
}
|
|
17514
|
-
const
|
|
17515
|
-
|
|
17516
|
-
...this.data.mutationElements
|
|
17517
|
-
];
|
|
17518
|
-
let tokenName = null;
|
|
17519
|
-
for (const element of allElements) {
|
|
17520
|
-
const protections = element.__aggregateProtections ?? element.data?.protections;
|
|
17521
|
-
if (protections?.length > 0) {
|
|
17522
|
-
tokenName = protections[0].token.name;
|
|
17523
|
-
break;
|
|
17524
|
-
}
|
|
17525
|
-
}
|
|
17526
|
-
if (!tokenName || !event2.payload) {
|
|
17527
|
+
const authContext = event2.authContext;
|
|
17528
|
+
if (!authContext) {
|
|
17527
17529
|
return adapters;
|
|
17528
17530
|
}
|
|
17529
17531
|
const scopedAuth = new AuthAdapter;
|
|
17530
|
-
scopedAuth.
|
|
17531
|
-
|
|
17532
|
-
|
|
17533
|
-
|
|
17534
|
-
tokenName,
|
|
17535
|
-
params: event2.payload
|
|
17536
|
-
}
|
|
17537
|
-
}]
|
|
17538
|
-
]);
|
|
17532
|
+
scopedAuth.setDecoded({
|
|
17533
|
+
tokenName: authContext.tokenName,
|
|
17534
|
+
params: authContext.params
|
|
17535
|
+
});
|
|
17539
17536
|
return { ...adapters, authAdapter: scopedAuth };
|
|
17540
17537
|
}
|
|
17541
17538
|
destroy() {
|
|
@@ -26348,19 +26345,20 @@ ${colors3.yellow}Type declaration errors:${colors3.reset}`);
|
|
|
26348
26345
|
}
|
|
26349
26346
|
|
|
26350
26347
|
// src/platform/shared.ts
|
|
26351
|
-
import { copyFileSync, existsSync as
|
|
26352
|
-
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";
|
|
26353
26350
|
|
|
26354
26351
|
// src/builder/module-builder.ts
|
|
26355
26352
|
import { execSync } from "child_process";
|
|
26356
26353
|
import {
|
|
26357
|
-
existsSync as
|
|
26358
|
-
mkdirSync as
|
|
26359
|
-
readFileSync as
|
|
26360
|
-
readdirSync as
|
|
26361
|
-
|
|
26354
|
+
existsSync as existsSync7,
|
|
26355
|
+
mkdirSync as mkdirSync6,
|
|
26356
|
+
readFileSync as readFileSync7,
|
|
26357
|
+
readdirSync as readdirSync4,
|
|
26358
|
+
rmSync,
|
|
26359
|
+
writeFileSync as writeFileSync6
|
|
26362
26360
|
} from "fs";
|
|
26363
|
-
import { dirname as dirname5, join as
|
|
26361
|
+
import { dirname as dirname5, join as join8, relative as relative3 } from "path";
|
|
26364
26362
|
|
|
26365
26363
|
// src/i18n/index.ts
|
|
26366
26364
|
import { existsSync as existsSync4, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
|
|
@@ -26633,43 +26631,154 @@ async function finalizeTranslations(rootDir, outDir, collector) {
|
|
|
26633
26631
|
}
|
|
26634
26632
|
}
|
|
26635
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
|
+
|
|
26636
26777
|
// src/builder/module-builder.ts
|
|
26637
26778
|
var CONTEXT_CLIENTS = [
|
|
26638
26779
|
{ name: "server", target: "bun", defines: { ONLY_SERVER: "true", ONLY_BROWSER: "false", ONLY_CLIENT: "false" } },
|
|
26639
26780
|
{ name: "browser", target: "browser", defines: { ONLY_SERVER: "false", ONLY_BROWSER: "true", ONLY_CLIENT: "true" } }
|
|
26640
26781
|
];
|
|
26641
|
-
async function buildContextPackage(pkg) {
|
|
26642
|
-
const entrypoint = pkg.entrypoint;
|
|
26643
|
-
const outDir = join6(pkg.path, "dist");
|
|
26644
|
-
const peerDeps = Object.keys(pkg.packageJson.peerDependencies || {});
|
|
26645
|
-
const deps = Object.keys(pkg.packageJson.dependencies || {});
|
|
26646
|
-
const externals = [...peerDeps, ...deps];
|
|
26647
|
-
const allDeclErrors = [];
|
|
26648
|
-
for (const client of CONTEXT_CLIENTS) {
|
|
26649
|
-
const result = await Bun.build({
|
|
26650
|
-
entrypoints: [entrypoint],
|
|
26651
|
-
outdir: join6(outDir, client.name, "main"),
|
|
26652
|
-
target: client.target,
|
|
26653
|
-
format: "esm",
|
|
26654
|
-
naming: "index.[ext]",
|
|
26655
|
-
external: externals,
|
|
26656
|
-
define: client.defines
|
|
26657
|
-
});
|
|
26658
|
-
if (!result.success) {
|
|
26659
|
-
console.error(`Context ${client.name} build failed:`);
|
|
26660
|
-
for (const log2 of result.logs)
|
|
26661
|
-
console.error(log2);
|
|
26662
|
-
throw new Error(`${client.name} build failed for ${pkg.name}`);
|
|
26663
|
-
}
|
|
26664
|
-
const globalsContent = Object.entries(client.defines).map(([k, v]) => `declare const ${k}: ${v};`).join(`
|
|
26665
|
-
`);
|
|
26666
|
-
const declResult = await buildTypeDeclarations([entrypoint], join6(outDir, client.name), dirname5(entrypoint), globalsContent);
|
|
26667
|
-
if (!declResult.success && declResult.errors.length > 0) {
|
|
26668
|
-
allDeclErrors.push(...declResult.errors.map((e) => `[${pkg.name}/${client.name}] ${e}`));
|
|
26669
|
-
}
|
|
26670
|
-
}
|
|
26671
|
-
return { declarationErrors: allDeclErrors };
|
|
26672
|
-
}
|
|
26673
26782
|
var SHELL_EXTERNALS = [
|
|
26674
26783
|
"react",
|
|
26675
26784
|
"react-dom",
|
|
@@ -26683,57 +26792,41 @@ var SHELL_EXTERNALS = [
|
|
|
26683
26792
|
"@arcote.tech/arc-workspace",
|
|
26684
26793
|
"@arcote.tech/platform"
|
|
26685
26794
|
];
|
|
26686
|
-
function sha256Hex(bytes) {
|
|
26687
|
-
const hasher = new Bun.CryptoHasher("sha256");
|
|
26688
|
-
hasher.update(bytes);
|
|
26689
|
-
return hasher.digest("hex");
|
|
26690
|
-
}
|
|
26691
|
-
function sha256OfFiles(paths) {
|
|
26692
|
-
const hasher = new Bun.CryptoHasher("sha256");
|
|
26693
|
-
const sorted = [...paths].sort();
|
|
26694
|
-
for (const p of sorted) {
|
|
26695
|
-
if (!existsSync5(p))
|
|
26696
|
-
continue;
|
|
26697
|
-
hasher.update(readFileSync5(p));
|
|
26698
|
-
hasher.update("\x00");
|
|
26699
|
-
}
|
|
26700
|
-
return hasher.digest("hex");
|
|
26701
|
-
}
|
|
26702
26795
|
function discoverPackages(rootDir) {
|
|
26703
|
-
const rootPkg = JSON.parse(
|
|
26796
|
+
const rootPkg = JSON.parse(readFileSync7(join8(rootDir, "package.json"), "utf-8"));
|
|
26704
26797
|
const workspaceGlobs = rootPkg.workspaces ?? [];
|
|
26705
26798
|
const results = [];
|
|
26706
26799
|
for (const glob2 of workspaceGlobs) {
|
|
26707
26800
|
const base2 = glob2.replace("/*", "");
|
|
26708
|
-
const baseDir =
|
|
26709
|
-
if (!
|
|
26801
|
+
const baseDir = join8(rootDir, base2);
|
|
26802
|
+
if (!existsSync7(baseDir))
|
|
26710
26803
|
continue;
|
|
26711
26804
|
let entries;
|
|
26712
26805
|
try {
|
|
26713
|
-
entries =
|
|
26806
|
+
entries = readdirSync4(baseDir);
|
|
26714
26807
|
} catch {
|
|
26715
26808
|
continue;
|
|
26716
26809
|
}
|
|
26717
26810
|
for (const entry of entries) {
|
|
26718
|
-
const pkgPath =
|
|
26719
|
-
if (!
|
|
26811
|
+
const pkgPath = join8(baseDir, entry, "package.json");
|
|
26812
|
+
if (!existsSync7(pkgPath))
|
|
26720
26813
|
continue;
|
|
26721
|
-
const pkg = JSON.parse(
|
|
26814
|
+
const pkg = JSON.parse(readFileSync7(pkgPath, "utf-8"));
|
|
26722
26815
|
if (pkg.name?.startsWith("@arcote.tech/"))
|
|
26723
26816
|
continue;
|
|
26724
|
-
const pkgDir =
|
|
26817
|
+
const pkgDir = join8(baseDir, entry);
|
|
26725
26818
|
const candidates = [
|
|
26726
|
-
|
|
26727
|
-
|
|
26728
|
-
|
|
26729
|
-
|
|
26819
|
+
join8(pkgDir, "src", "index.ts"),
|
|
26820
|
+
join8(pkgDir, "src", "index.tsx"),
|
|
26821
|
+
join8(pkgDir, "index.ts"),
|
|
26822
|
+
join8(pkgDir, "index.tsx")
|
|
26730
26823
|
];
|
|
26731
|
-
const entrypoint = candidates.find((c) =>
|
|
26824
|
+
const entrypoint = candidates.find((c) => existsSync7(c)) ?? null;
|
|
26732
26825
|
if (!entrypoint)
|
|
26733
26826
|
continue;
|
|
26734
26827
|
results.push({
|
|
26735
26828
|
name: pkg.name,
|
|
26736
|
-
path:
|
|
26829
|
+
path: join8(baseDir, entry),
|
|
26737
26830
|
entrypoint,
|
|
26738
26831
|
packageJson: pkg
|
|
26739
26832
|
});
|
|
@@ -26752,95 +26845,198 @@ function isContextPackage(pkg) {
|
|
|
26752
26845
|
}
|
|
26753
26846
|
return false;
|
|
26754
26847
|
}
|
|
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
|
-
|
|
26781
|
-
|
|
26782
|
-
|
|
26783
|
-
|
|
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 };
|
|
26784
26883
|
}
|
|
26785
|
-
console.log(`
|
|
26786
|
-
const
|
|
26787
|
-
const
|
|
26788
|
-
|
|
26789
|
-
setup(build2) {
|
|
26790
|
-
build2.onResolve({ filter: /^@arcote\.tech\// }, (args) => {
|
|
26791
|
-
return { path: args.path, external: true };
|
|
26792
|
-
});
|
|
26793
|
-
}
|
|
26794
|
-
};
|
|
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];
|
|
26795
26888
|
const result = await Bun.build({
|
|
26796
|
-
entrypoints,
|
|
26797
|
-
outdir: outDir,
|
|
26798
|
-
|
|
26889
|
+
entrypoints: [pkg.entrypoint],
|
|
26890
|
+
outdir: join8(outDir, "main"),
|
|
26891
|
+
target: client.target,
|
|
26799
26892
|
format: "esm",
|
|
26800
|
-
|
|
26801
|
-
external:
|
|
26802
|
-
|
|
26803
|
-
naming: "[name].[ext]",
|
|
26804
|
-
define: {
|
|
26805
|
-
ONLY_SERVER: "false",
|
|
26806
|
-
ONLY_BROWSER: "true",
|
|
26807
|
-
ONLY_CLIENT: "true"
|
|
26808
|
-
}
|
|
26893
|
+
naming: "index.[ext]",
|
|
26894
|
+
external: externals,
|
|
26895
|
+
define: client.defines
|
|
26809
26896
|
});
|
|
26810
26897
|
if (!result.success) {
|
|
26811
|
-
console.error(
|
|
26898
|
+
console.error(`Context ${client.name} build failed:`);
|
|
26812
26899
|
for (const log2 of result.logs)
|
|
26813
26900
|
console.error(log2);
|
|
26814
|
-
throw new Error(
|
|
26815
|
-
}
|
|
26816
|
-
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
const
|
|
26820
|
-
|
|
26821
|
-
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
};
|
|
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" }
|
|
26828
26939
|
});
|
|
26829
|
-
|
|
26830
|
-
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
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 });
|
|
26837
27038
|
}
|
|
26838
|
-
|
|
26839
|
-
mkdirSync5(outDir, { recursive: true });
|
|
26840
|
-
const inputCss = join6(outDir, "_input.css");
|
|
26841
|
-
const outputCss = join6(outDir, "styles.css");
|
|
26842
|
-
const rootRel = relative2(outDir, rootDir).replace(/\\/g, "/");
|
|
26843
|
-
writeFileSync5(inputCss, `@import "tailwindcss";
|
|
27039
|
+
var TAILWIND_INPUT_TEMPLATE = (rootRel) => `@import "tailwindcss";
|
|
26844
27040
|
@import "tw-animate-css";
|
|
26845
27041
|
|
|
26846
27042
|
@source "${rootRel}/packages/*/*.{ts,tsx}";
|
|
@@ -26898,12 +27094,61 @@ async function buildStyles(rootDir, outDir) {
|
|
|
26898
27094
|
min-height: 100vh;
|
|
26899
27095
|
}
|
|
26900
27096
|
}
|
|
26901
|
-
|
|
26902
|
-
|
|
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);
|
|
26903
27140
|
execSync(`bunx @tailwindcss/cli -i ${inputCss} -o ${outputCss} --minify`, {
|
|
26904
27141
|
cwd: rootDir,
|
|
26905
27142
|
stdio: "inherit"
|
|
26906
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 });
|
|
26907
27152
|
}
|
|
26908
27153
|
|
|
26909
27154
|
// src/platform/shared.ts
|
|
@@ -26923,9 +27168,9 @@ function resolveWorkspace() {
|
|
|
26923
27168
|
process.exit(1);
|
|
26924
27169
|
}
|
|
26925
27170
|
const rootDir = dirname6(packageJsonPath);
|
|
26926
|
-
const rootPkg = JSON.parse(
|
|
27171
|
+
const rootPkg = JSON.parse(readFileSync8(packageJsonPath, "utf-8"));
|
|
26927
27172
|
const appName = rootPkg.name ?? "Arc App";
|
|
26928
|
-
const arcDir =
|
|
27173
|
+
const arcDir = join9(rootDir, ".arc", "platform");
|
|
26929
27174
|
log2("Scanning workspaces...");
|
|
26930
27175
|
const packages = discoverPackages(rootDir);
|
|
26931
27176
|
ok(`Found ${packages.length} package(s): ${packages.map((p) => p.name).join(", ")}`);
|
|
@@ -26935,10 +27180,10 @@ function resolveWorkspace() {
|
|
|
26935
27180
|
}
|
|
26936
27181
|
let manifest;
|
|
26937
27182
|
for (const name of ["manifest.json", "manifest.webmanifest"]) {
|
|
26938
|
-
const manifestPath =
|
|
26939
|
-
if (
|
|
27183
|
+
const manifestPath = join9(rootDir, name);
|
|
27184
|
+
if (existsSync8(manifestPath)) {
|
|
26940
27185
|
try {
|
|
26941
|
-
const data = JSON.parse(
|
|
27186
|
+
const data = JSON.parse(readFileSync8(manifestPath, "utf-8"));
|
|
26942
27187
|
const icons = data.icons;
|
|
26943
27188
|
manifest = {
|
|
26944
27189
|
path: manifestPath,
|
|
@@ -26957,61 +27202,135 @@ function resolveWorkspace() {
|
|
|
26957
27202
|
rootPkg,
|
|
26958
27203
|
appName,
|
|
26959
27204
|
arcDir,
|
|
26960
|
-
modulesDir:
|
|
26961
|
-
shellDir:
|
|
26962
|
-
|
|
27205
|
+
modulesDir: join9(arcDir, "modules"),
|
|
27206
|
+
shellDir: join9(arcDir, "shell"),
|
|
27207
|
+
assetsDir: join9(arcDir, "assets"),
|
|
27208
|
+
publicDir: join9(rootDir, "public"),
|
|
26963
27209
|
packages,
|
|
26964
27210
|
manifest
|
|
26965
27211
|
};
|
|
26966
27212
|
}
|
|
26967
|
-
async function buildAll(ws) {
|
|
26968
|
-
|
|
26969
|
-
const
|
|
26970
|
-
ok(`Built ${manifest.modules.length} module(s)`);
|
|
26971
|
-
log2("Building styles...");
|
|
26972
|
-
await buildStyles(ws.rootDir, ws.arcDir);
|
|
26973
|
-
ok("Styles built");
|
|
27213
|
+
async function buildAll(ws, opts = {}) {
|
|
27214
|
+
const cache = loadBuildCache(ws.arcDir);
|
|
27215
|
+
const noCache = opts.noCache ?? false;
|
|
26974
27216
|
const themePath = ws.rootPkg.arc?.theme;
|
|
26975
|
-
|
|
26976
|
-
|
|
26977
|
-
|
|
26978
|
-
|
|
26979
|
-
|
|
26980
|
-
|
|
26981
|
-
|
|
26982
|
-
|
|
26983
|
-
|
|
26984
|
-
|
|
26985
|
-
const finalManifest =
|
|
26986
|
-
|
|
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));
|
|
26987
27229
|
return finalManifest;
|
|
26988
27230
|
}
|
|
26989
|
-
function
|
|
26990
|
-
const
|
|
26991
|
-
const
|
|
26992
|
-
|
|
26993
|
-
|
|
26994
|
-
|
|
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 ?? "";
|
|
26995
27240
|
return {
|
|
26996
|
-
modules
|
|
26997
|
-
shellHash
|
|
26998
|
-
stylesHash
|
|
26999
|
-
buildTime:
|
|
27241
|
+
modules,
|
|
27242
|
+
shellHash,
|
|
27243
|
+
stylesHash,
|
|
27244
|
+
buildTime: new Date().toISOString()
|
|
27000
27245
|
};
|
|
27001
27246
|
}
|
|
27002
|
-
function
|
|
27003
|
-
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))
|
|
27004
27289
|
return [];
|
|
27005
27290
|
const out = [];
|
|
27006
|
-
for (const entry of
|
|
27007
|
-
|
|
27008
|
-
|
|
27009
|
-
|
|
27010
|
-
|
|
27011
|
-
|
|
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
|
+
}
|
|
27012
27304
|
}
|
|
27013
27305
|
return out;
|
|
27014
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
|
+
}
|
|
27015
27334
|
function collectArcPeerDeps(packages) {
|
|
27016
27335
|
const seen = new Set;
|
|
27017
27336
|
for (const pkg of ["@arcote.tech/arc", "@arcote.tech/arc-ds", "@arcote.tech/arc-react", "@arcote.tech/platform"]) {
|
|
@@ -27029,14 +27348,10 @@ function collectArcPeerDeps(packages) {
|
|
|
27029
27348
|
return [short, pkg];
|
|
27030
27349
|
});
|
|
27031
27350
|
}
|
|
27032
|
-
|
|
27033
|
-
|
|
27034
|
-
|
|
27035
|
-
|
|
27036
|
-
const reactEntries = [
|
|
27037
|
-
[
|
|
27038
|
-
"react",
|
|
27039
|
-
`import React from "react";
|
|
27351
|
+
var REACT_ENTRIES = [
|
|
27352
|
+
[
|
|
27353
|
+
"react",
|
|
27354
|
+
`import React from "react";
|
|
27040
27355
|
export default React;
|
|
27041
27356
|
export const {
|
|
27042
27357
|
Children, Component, Fragment, Profiler, PureComponent, StrictMode, Suspense,
|
|
@@ -27046,84 +27361,133 @@ export const {
|
|
|
27046
27361
|
useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore,
|
|
27047
27362
|
useTransition, version, useActionState, useOptimistic,
|
|
27048
27363
|
} = React;`
|
|
27049
|
-
|
|
27050
|
-
|
|
27051
|
-
|
|
27052
|
-
|
|
27053
|
-
|
|
27054
|
-
|
|
27055
|
-
|
|
27056
|
-
|
|
27057
|
-
|
|
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";
|
|
27058
27373
|
export default ReactDOM;
|
|
27059
27374
|
export const { createPortal, flushSync } = ReactDOM;`
|
|
27060
|
-
|
|
27061
|
-
|
|
27062
|
-
|
|
27063
|
-
|
|
27064
|
-
|
|
27065
|
-
|
|
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`);
|
|
27066
27417
|
const reactEps = [];
|
|
27067
|
-
for (const [name, code] of
|
|
27068
|
-
const f =
|
|
27069
|
-
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);
|
|
27070
27421
|
reactEps.push(f);
|
|
27071
27422
|
}
|
|
27072
|
-
const
|
|
27423
|
+
const r = await Bun.build({
|
|
27073
27424
|
entrypoints: reactEps,
|
|
27074
|
-
outdir:
|
|
27425
|
+
outdir: shellDir,
|
|
27075
27426
|
splitting: true,
|
|
27076
27427
|
format: "esm",
|
|
27077
27428
|
target: "browser",
|
|
27078
27429
|
naming: "[name].[ext]"
|
|
27079
27430
|
});
|
|
27080
|
-
if (!
|
|
27081
|
-
for (const l of
|
|
27431
|
+
if (!r.success) {
|
|
27432
|
+
for (const l of r.logs)
|
|
27082
27433
|
console.error(l);
|
|
27083
27434
|
throw new Error("Shell React build failed");
|
|
27084
27435
|
}
|
|
27085
|
-
const
|
|
27086
|
-
|
|
27087
|
-
|
|
27088
|
-
|
|
27089
|
-
|
|
27090
|
-
|
|
27091
|
-
const
|
|
27092
|
-
|
|
27093
|
-
|
|
27094
|
-
|
|
27095
|
-
|
|
27096
|
-
|
|
27097
|
-
|
|
27098
|
-
const
|
|
27099
|
-
|
|
27100
|
-
|
|
27101
|
-
|
|
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}";
|
|
27102
27457
|
`);
|
|
27103
|
-
|
|
27104
|
-
|
|
27105
|
-
|
|
27106
|
-
|
|
27107
|
-
|
|
27108
|
-
|
|
27109
|
-
|
|
27110
|
-
|
|
27111
|
-
|
|
27112
|
-
|
|
27113
|
-
|
|
27114
|
-
ONLY_SERVER: "false",
|
|
27115
|
-
ONLY_BROWSER: "true",
|
|
27116
|
-
ONLY_CLIENT: "true"
|
|
27117
|
-
}
|
|
27118
|
-
});
|
|
27119
|
-
if (!r2.success) {
|
|
27120
|
-
for (const l of r2.logs)
|
|
27121
|
-
console.error(l);
|
|
27122
|
-
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"
|
|
27123
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}`);
|
|
27124
27475
|
}
|
|
27125
|
-
const
|
|
27126
|
-
|
|
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 });
|
|
27127
27491
|
}
|
|
27128
27492
|
async function loadServerContext(packages) {
|
|
27129
27493
|
const ctxPackages = packages.filter((p) => isContextPackage(p.packageJson));
|
|
@@ -27132,13 +27496,13 @@ async function loadServerContext(packages) {
|
|
|
27132
27496
|
globalThis.ONLY_SERVER = true;
|
|
27133
27497
|
globalThis.ONLY_BROWSER = false;
|
|
27134
27498
|
globalThis.ONLY_CLIENT = false;
|
|
27135
|
-
const platformDir =
|
|
27136
|
-
const platformPkg = JSON.parse(
|
|
27137
|
-
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");
|
|
27138
27502
|
await import(platformEntry);
|
|
27139
27503
|
for (const ctx of ctxPackages) {
|
|
27140
|
-
const serverDist =
|
|
27141
|
-
if (!
|
|
27504
|
+
const serverDist = join9(ctx.path, "dist", "server", "main", "index.js");
|
|
27505
|
+
if (!existsSync8(serverDist)) {
|
|
27142
27506
|
err(`Context server dist not found: ${serverDist}`);
|
|
27143
27507
|
continue;
|
|
27144
27508
|
}
|
|
@@ -27162,26 +27526,26 @@ async function loadServerContext(packages) {
|
|
|
27162
27526
|
}
|
|
27163
27527
|
|
|
27164
27528
|
// src/commands/platform-build.ts
|
|
27165
|
-
async function platformBuild() {
|
|
27529
|
+
async function platformBuild(opts = {}) {
|
|
27166
27530
|
const ws = resolveWorkspace();
|
|
27167
|
-
const manifest = await buildAll(ws);
|
|
27531
|
+
const manifest = await buildAll(ws, { noCache: opts.noCache });
|
|
27168
27532
|
ok(`Platform built \u2014 ${manifest.modules.length} module(s)`);
|
|
27169
27533
|
}
|
|
27170
27534
|
|
|
27171
27535
|
// src/commands/platform-deploy.ts
|
|
27172
|
-
import { existsSync as
|
|
27173
|
-
import { join as
|
|
27536
|
+
import { existsSync as existsSync12, readFileSync as readFileSync11 } from "fs";
|
|
27537
|
+
import { join as join15 } from "path";
|
|
27174
27538
|
|
|
27175
27539
|
// src/deploy/bootstrap.ts
|
|
27176
|
-
import { mkdirSync as
|
|
27540
|
+
import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync11 } from "fs";
|
|
27177
27541
|
import { tmpdir as tmpdir3 } from "os";
|
|
27178
|
-
import { join as
|
|
27542
|
+
import { join as join13 } from "path";
|
|
27179
27543
|
|
|
27180
27544
|
// src/deploy/ansible.ts
|
|
27181
27545
|
var {spawn: spawn2 } = globalThis.Bun;
|
|
27182
|
-
import { mkdirSync as
|
|
27546
|
+
import { mkdirSync as mkdirSync8, writeFileSync as writeFileSync8 } from "fs";
|
|
27183
27547
|
import { tmpdir } from "os";
|
|
27184
|
-
import { join as
|
|
27548
|
+
import { join as join10 } from "path";
|
|
27185
27549
|
|
|
27186
27550
|
// src/deploy/assets.ts
|
|
27187
27551
|
var TERRAFORM_MAIN_TF = `terraform {
|
|
@@ -27438,18 +27802,18 @@ var ASSETS = {
|
|
|
27438
27802
|
}
|
|
27439
27803
|
};
|
|
27440
27804
|
async function materializeAssets(targetDir, files) {
|
|
27441
|
-
const { mkdirSync:
|
|
27442
|
-
const { join:
|
|
27443
|
-
|
|
27805
|
+
const { mkdirSync: mkdirSync8, writeFileSync: writeFileSync8 } = await import("fs");
|
|
27806
|
+
const { join: join10 } = await import("path");
|
|
27807
|
+
mkdirSync8(targetDir, { recursive: true });
|
|
27444
27808
|
for (const [name, content] of Object.entries(files)) {
|
|
27445
|
-
|
|
27809
|
+
writeFileSync8(join10(targetDir, name), content);
|
|
27446
27810
|
}
|
|
27447
27811
|
}
|
|
27448
27812
|
|
|
27449
27813
|
// src/deploy/ansible.ts
|
|
27450
27814
|
async function runAnsible(inputs) {
|
|
27451
|
-
const workDir =
|
|
27452
|
-
|
|
27815
|
+
const workDir = join10(tmpdir(), "arc-deploy", `ansible-${Date.now()}`);
|
|
27816
|
+
mkdirSync8(workDir, { recursive: true });
|
|
27453
27817
|
await materializeAssets(workDir, ASSETS.ansible);
|
|
27454
27818
|
const user = inputs.asRoot ? "root" : inputs.target.user;
|
|
27455
27819
|
const port = inputs.ansible?.sshPort ?? inputs.target.port;
|
|
@@ -27463,7 +27827,7 @@ async function runAnsible(inputs) {
|
|
|
27463
27827
|
""
|
|
27464
27828
|
].join(`
|
|
27465
27829
|
`);
|
|
27466
|
-
|
|
27830
|
+
writeFileSync8(join10(workDir, "inventory.ini"), inventory);
|
|
27467
27831
|
const extraVars = [
|
|
27468
27832
|
`username=${inputs.target.user}`,
|
|
27469
27833
|
`ssh_port=${port}`
|
|
@@ -27588,15 +27952,15 @@ function generateCompose({ cfg }) {
|
|
|
27588
27952
|
|
|
27589
27953
|
// src/deploy/terraform.ts
|
|
27590
27954
|
var {spawn: spawn3 } = globalThis.Bun;
|
|
27591
|
-
import { existsSync as
|
|
27955
|
+
import { existsSync as existsSync9, mkdirSync as mkdirSync9, writeFileSync as writeFileSync9 } from "fs";
|
|
27592
27956
|
import { tmpdir as tmpdir2 } from "os";
|
|
27593
|
-
import { join as
|
|
27957
|
+
import { join as join11 } from "path";
|
|
27594
27958
|
async function runTerraform(inputs) {
|
|
27595
|
-
const workDir =
|
|
27596
|
-
|
|
27959
|
+
const workDir = join11(tmpdir2(), "arc-deploy", `tf-${Date.now()}`);
|
|
27960
|
+
mkdirSync9(workDir, { recursive: true });
|
|
27597
27961
|
await materializeAssets(workDir, ASSETS.terraform);
|
|
27598
27962
|
const sshPubKey = inputs.tf.sshPublicKey ?? expandHome("~/.ssh/id_ed25519.pub");
|
|
27599
|
-
if (!
|
|
27963
|
+
if (!existsSync9(expandHome(sshPubKey))) {
|
|
27600
27964
|
throw new Error(`SSH public key not found at ${sshPubKey}. Set provision.terraform.sshPublicKey in deploy.arc.json.`);
|
|
27601
27965
|
}
|
|
27602
27966
|
const tfvars = [
|
|
@@ -27609,7 +27973,7 @@ async function runTerraform(inputs) {
|
|
|
27609
27973
|
].join(`
|
|
27610
27974
|
`) + `
|
|
27611
27975
|
`;
|
|
27612
|
-
|
|
27976
|
+
writeFileSync9(join11(workDir, "terraform.tfvars"), tfvars);
|
|
27613
27977
|
await runTf(workDir, ["init", "-input=false", "-no-color"]);
|
|
27614
27978
|
await runTf(workDir, [
|
|
27615
27979
|
"apply",
|
|
@@ -27661,21 +28025,21 @@ function expandHome(p) {
|
|
|
27661
28025
|
}
|
|
27662
28026
|
|
|
27663
28027
|
// src/deploy/config.ts
|
|
27664
|
-
import { existsSync as
|
|
27665
|
-
import { join as
|
|
28028
|
+
import { existsSync as existsSync10, readFileSync as readFileSync9, writeFileSync as writeFileSync10 } from "fs";
|
|
28029
|
+
import { join as join12 } from "path";
|
|
27666
28030
|
var DEPLOY_CONFIG_FILE = "deploy.arc.json";
|
|
27667
28031
|
function deployConfigPath(rootDir) {
|
|
27668
|
-
return
|
|
28032
|
+
return join12(rootDir, DEPLOY_CONFIG_FILE);
|
|
27669
28033
|
}
|
|
27670
28034
|
function deployConfigExists(rootDir) {
|
|
27671
|
-
return
|
|
28035
|
+
return existsSync10(deployConfigPath(rootDir));
|
|
27672
28036
|
}
|
|
27673
28037
|
function loadDeployConfig(rootDir) {
|
|
27674
28038
|
const path4 = deployConfigPath(rootDir);
|
|
27675
|
-
if (!
|
|
28039
|
+
if (!existsSync10(path4)) {
|
|
27676
28040
|
throw new Error(`Missing ${DEPLOY_CONFIG_FILE} at ${path4}`);
|
|
27677
28041
|
}
|
|
27678
|
-
const raw =
|
|
28042
|
+
const raw = readFileSync9(path4, "utf-8");
|
|
27679
28043
|
let parsed;
|
|
27680
28044
|
try {
|
|
27681
28045
|
parsed = JSON.parse(raw);
|
|
@@ -27686,7 +28050,7 @@ function loadDeployConfig(rootDir) {
|
|
|
27686
28050
|
return validateDeployConfig(expanded);
|
|
27687
28051
|
}
|
|
27688
28052
|
function saveDeployConfig(rootDir, cfg) {
|
|
27689
|
-
|
|
28053
|
+
writeFileSync10(deployConfigPath(rootDir), JSON.stringify(cfg, null, 2) + `
|
|
27690
28054
|
`);
|
|
27691
28055
|
}
|
|
27692
28056
|
var VAR_REGEX = /\$\{([A-Z0-9_]+)\}|\$([A-Z0-9_]+)/g;
|
|
@@ -28086,22 +28450,22 @@ async function bootstrap(inputs) {
|
|
|
28086
28450
|
}
|
|
28087
28451
|
async function upStack(inputs) {
|
|
28088
28452
|
const { cfg } = inputs;
|
|
28089
|
-
const workDir =
|
|
28090
|
-
|
|
28091
|
-
|
|
28092
|
-
|
|
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 }));
|
|
28093
28457
|
await assertExec(cfg.target, `sudo mkdir -p ${cfg.target.remoteDir} && sudo chown ${cfg.target.user}:${cfg.target.user} ${cfg.target.remoteDir}`);
|
|
28094
28458
|
for (const name of Object.keys(cfg.envs)) {
|
|
28095
28459
|
await assertExec(cfg.target, `mkdir -p ${cfg.target.remoteDir}/${name}`);
|
|
28096
28460
|
}
|
|
28097
|
-
await scpUpload(cfg.target,
|
|
28098
|
-
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`);
|
|
28099
28463
|
await assertExec(cfg.target, `cd ${cfg.target.remoteDir} && docker compose pull --ignore-pull-failures && docker compose up -d`);
|
|
28100
28464
|
}
|
|
28101
28465
|
|
|
28102
28466
|
// src/deploy/remote-sync.ts
|
|
28103
|
-
import { existsSync as
|
|
28104
|
-
import { join as
|
|
28467
|
+
import { existsSync as existsSync11, readFileSync as readFileSync10 } from "fs";
|
|
28468
|
+
import { join as join14, relative as relative4 } from "path";
|
|
28105
28469
|
function diffManifests(local, remote) {
|
|
28106
28470
|
const remoteByName = new Map(remote.modules.map((m) => [m.name, m]));
|
|
28107
28471
|
const changedModules = local.modules.filter((m) => remoteByName.get(m.name)?.hash !== m.hash);
|
|
@@ -28118,11 +28482,11 @@ async function syncEnv(inputs) {
|
|
|
28118
28482
|
throw new Error(`Unknown env: ${env2}`);
|
|
28119
28483
|
const remotePath = `${cfg.target.remoteDir}/${env2}`;
|
|
28120
28484
|
await rsyncDir(cfg.target, projectDir, remotePath);
|
|
28121
|
-
const localManifestPath =
|
|
28122
|
-
if (!
|
|
28485
|
+
const localManifestPath = join14(ws.modulesDir, "manifest.json");
|
|
28486
|
+
if (!existsSync11(localManifestPath)) {
|
|
28123
28487
|
throw new Error(`Local build missing at ${localManifestPath}. Run arc platform build first.`);
|
|
28124
28488
|
}
|
|
28125
|
-
const localManifest = JSON.parse(
|
|
28489
|
+
const localManifest = JSON.parse(readFileSync10(localManifestPath, "utf-8"));
|
|
28126
28490
|
const localPort = 15500 + hashEnvToOffset(env2);
|
|
28127
28491
|
const tunnel = await openTunnel(cfg.target, localPort, "127.0.0.1", 2019);
|
|
28128
28492
|
try {
|
|
@@ -28137,8 +28501,8 @@ async function syncEnv(inputs) {
|
|
|
28137
28501
|
const shellFiles = collectFiles(ws.shellDir);
|
|
28138
28502
|
const form = new FormData;
|
|
28139
28503
|
for (const absPath of shellFiles) {
|
|
28140
|
-
const rel =
|
|
28141
|
-
form.append(rel, new Blob([
|
|
28504
|
+
const rel = relative4(ws.shellDir, absPath);
|
|
28505
|
+
form.append(rel, new Blob([readFileSync10(absPath)]), rel);
|
|
28142
28506
|
}
|
|
28143
28507
|
const res2 = await fetch(`${base2}/api/deploy/shell`, {
|
|
28144
28508
|
method: "POST",
|
|
@@ -28150,9 +28514,9 @@ async function syncEnv(inputs) {
|
|
|
28150
28514
|
if (diff.stylesChanged) {
|
|
28151
28515
|
const form = new FormData;
|
|
28152
28516
|
for (const name of ["styles.css", "theme.css"]) {
|
|
28153
|
-
const p =
|
|
28154
|
-
if (
|
|
28155
|
-
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);
|
|
28156
28520
|
}
|
|
28157
28521
|
}
|
|
28158
28522
|
const res2 = await fetch(`${base2}/api/deploy/shell`, {
|
|
@@ -28165,8 +28529,8 @@ async function syncEnv(inputs) {
|
|
|
28165
28529
|
if (diff.changedModules.length > 0) {
|
|
28166
28530
|
const form = new FormData;
|
|
28167
28531
|
for (const mod of diff.changedModules) {
|
|
28168
|
-
const p =
|
|
28169
|
-
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);
|
|
28170
28534
|
}
|
|
28171
28535
|
const res2 = await fetch(`${base2}/api/deploy/modules`, {
|
|
28172
28536
|
method: "POST",
|
|
@@ -28193,12 +28557,12 @@ async function syncEnv(inputs) {
|
|
|
28193
28557
|
}
|
|
28194
28558
|
}
|
|
28195
28559
|
function collectFiles(dir) {
|
|
28196
|
-
if (!
|
|
28560
|
+
if (!existsSync11(dir))
|
|
28197
28561
|
return [];
|
|
28198
|
-
const { readdirSync:
|
|
28562
|
+
const { readdirSync: readdirSync6 } = __require("fs");
|
|
28199
28563
|
const out = [];
|
|
28200
|
-
for (const entry of
|
|
28201
|
-
const p =
|
|
28564
|
+
for (const entry of readdirSync6(dir, { withFileTypes: true })) {
|
|
28565
|
+
const p = join14(dir, entry.name);
|
|
28202
28566
|
if (entry.isDirectory())
|
|
28203
28567
|
out.push(...collectFiles(p));
|
|
28204
28568
|
else if (entry.isFile())
|
|
@@ -28910,13 +29274,13 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
28910
29274
|
err(`Unknown env "${envArg}". Known: ${Object.keys(cfg.envs).join(", ")}`);
|
|
28911
29275
|
process.exit(1);
|
|
28912
29276
|
})() : Object.keys(cfg.envs);
|
|
28913
|
-
const manifestPath =
|
|
28914
|
-
const needBuild = options.rebuild || !
|
|
29277
|
+
const manifestPath = join15(ws.modulesDir, "manifest.json");
|
|
29278
|
+
const needBuild = options.rebuild || !existsSync12(manifestPath);
|
|
28915
29279
|
if (needBuild && !options.skipBuild) {
|
|
28916
29280
|
log2("Building platform...");
|
|
28917
|
-
await buildAll(ws);
|
|
29281
|
+
await buildAll(ws, { noCache: options.rebuild });
|
|
28918
29282
|
ok("Build complete");
|
|
28919
|
-
} else if (!
|
|
29283
|
+
} else if (!existsSync12(manifestPath)) {
|
|
28920
29284
|
err("No build found and --skip-build was set.");
|
|
28921
29285
|
process.exit(1);
|
|
28922
29286
|
}
|
|
@@ -28959,24 +29323,24 @@ async function platformDeploy(envArg, options = {}) {
|
|
|
28959
29323
|
}
|
|
28960
29324
|
function readCliVersion() {
|
|
28961
29325
|
try {
|
|
28962
|
-
const pkgPath =
|
|
28963
|
-
const pkg = JSON.parse(
|
|
29326
|
+
const pkgPath = join15(import.meta.dir, "..", "..", "package.json");
|
|
29327
|
+
const pkg = JSON.parse(readFileSync11(pkgPath, "utf-8"));
|
|
28964
29328
|
return pkg.version ?? "unknown";
|
|
28965
29329
|
} catch {
|
|
28966
29330
|
return "unknown";
|
|
28967
29331
|
}
|
|
28968
29332
|
}
|
|
28969
29333
|
async function hashDeployConfig(rootDir) {
|
|
28970
|
-
const p2 =
|
|
28971
|
-
const content =
|
|
29334
|
+
const p2 = join15(rootDir, "deploy.arc.json");
|
|
29335
|
+
const content = readFileSync11(p2);
|
|
28972
29336
|
const hasher = new Bun.CryptoHasher("sha256");
|
|
28973
29337
|
hasher.update(content);
|
|
28974
29338
|
return hasher.digest("hex").slice(0, 16);
|
|
28975
29339
|
}
|
|
28976
29340
|
|
|
28977
29341
|
// src/commands/platform-dev.ts
|
|
28978
|
-
import { existsSync as
|
|
28979
|
-
import { join as
|
|
29342
|
+
import { existsSync as existsSync15, watch } from "fs";
|
|
29343
|
+
import { join as join18 } from "path";
|
|
28980
29344
|
|
|
28981
29345
|
// ../host/src/create-server.ts
|
|
28982
29346
|
var import_jsonwebtoken = __toESM(require_jsonwebtoken(), 1);
|
|
@@ -30295,7 +30659,10 @@ async function createArcServer(config) {
|
|
|
30295
30659
|
"Access-Control-Allow-Origin": origin,
|
|
30296
30660
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
|
30297
30661
|
"Access-Control-Allow-Headers": "Content-Type, Authorization, X-Arc-Scope, X-Arc-Tokens",
|
|
30298
|
-
"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"
|
|
30299
30666
|
};
|
|
30300
30667
|
}
|
|
30301
30668
|
const corsHeaders = buildCorsHeaders();
|
|
@@ -30423,12 +30790,12 @@ async function createArcServer(config) {
|
|
|
30423
30790
|
};
|
|
30424
30791
|
}
|
|
30425
30792
|
// src/platform/server.ts
|
|
30426
|
-
import { existsSync as
|
|
30427
|
-
import { join as
|
|
30793
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync12 } from "fs";
|
|
30794
|
+
import { join as join17 } from "path";
|
|
30428
30795
|
|
|
30429
30796
|
// src/platform/deploy-api.ts
|
|
30430
|
-
import { existsSync as
|
|
30431
|
-
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";
|
|
30432
30799
|
function createDeployApiHandler(opts) {
|
|
30433
30800
|
return async (req, url, ctx) => {
|
|
30434
30801
|
const p3 = url.pathname;
|
|
@@ -30445,7 +30812,7 @@ function createDeployApiHandler(opts) {
|
|
|
30445
30812
|
if (!validateManifest(body)) {
|
|
30446
30813
|
return Response.json({ error: "Invalid manifest body" }, { status: 400, headers: ctx.corsHeaders });
|
|
30447
30814
|
}
|
|
30448
|
-
|
|
30815
|
+
writeFileSync12(join16(opts.ws.modulesDir, "manifest.json"), JSON.stringify(body, null, 2));
|
|
30449
30816
|
opts.setManifest(body);
|
|
30450
30817
|
opts.notifyReload(body);
|
|
30451
30818
|
return Response.json({ ok: true, moduleCount: body.modules.length }, { headers: ctx.corsHeaders });
|
|
@@ -30471,8 +30838,8 @@ function createDeployApiHandler(opts) {
|
|
|
30471
30838
|
const writtenShell = await writeUploadedFileList(shellFiles, opts.ws.shellDir);
|
|
30472
30839
|
const writtenRoot = [];
|
|
30473
30840
|
for (const { name, file } of rootFiles) {
|
|
30474
|
-
const target =
|
|
30475
|
-
|
|
30841
|
+
const target = join16(opts.ws.arcDir, name);
|
|
30842
|
+
writeFileSync12(target, Buffer.from(await file.arrayBuffer()));
|
|
30476
30843
|
writtenRoot.push(name);
|
|
30477
30844
|
}
|
|
30478
30845
|
return Response.json({ ok: true, written: [...writtenShell, ...writtenRoot] }, { headers: ctx.corsHeaders });
|
|
@@ -30497,16 +30864,16 @@ function isFile(v3) {
|
|
|
30497
30864
|
async function writeUploadedFileList(files, targetDir) {
|
|
30498
30865
|
const written = [];
|
|
30499
30866
|
const safeRoot = resolve(targetDir);
|
|
30500
|
-
|
|
30867
|
+
mkdirSync11(safeRoot, { recursive: true });
|
|
30501
30868
|
for (const file of files) {
|
|
30502
30869
|
const rel = normalize2(file.name);
|
|
30503
30870
|
const full = resolve(safeRoot, rel);
|
|
30504
30871
|
if (!full.startsWith(safeRoot + "/") && full !== safeRoot) {
|
|
30505
30872
|
throw new Error(`Path traversal rejected: ${file.name}`);
|
|
30506
30873
|
}
|
|
30507
|
-
|
|
30508
|
-
|
|
30509
|
-
written.push(
|
|
30874
|
+
mkdirSync11(dirname7(full), { recursive: true });
|
|
30875
|
+
writeFileSync12(full, Buffer.from(await file.arrayBuffer()));
|
|
30876
|
+
written.push(relative5(safeRoot, full) || rel);
|
|
30510
30877
|
}
|
|
30511
30878
|
return written;
|
|
30512
30879
|
}
|
|
@@ -30573,14 +30940,15 @@ var MIME = {
|
|
|
30573
30940
|
".ico": "image/x-icon",
|
|
30574
30941
|
".woff2": "font/woff2",
|
|
30575
30942
|
".woff": "font/woff",
|
|
30576
|
-
".ttf": "font/ttf"
|
|
30943
|
+
".ttf": "font/ttf",
|
|
30944
|
+
".wasm": "application/wasm"
|
|
30577
30945
|
};
|
|
30578
30946
|
function getMime(path4) {
|
|
30579
30947
|
const ext2 = path4.substring(path4.lastIndexOf("."));
|
|
30580
30948
|
return MIME[ext2] ?? "application/octet-stream";
|
|
30581
30949
|
}
|
|
30582
30950
|
function serveFile(filePath, headers = {}) {
|
|
30583
|
-
if (!
|
|
30951
|
+
if (!existsSync14(filePath))
|
|
30584
30952
|
return new Response("Not Found", { status: 404 });
|
|
30585
30953
|
return new Response(Bun.file(filePath), {
|
|
30586
30954
|
headers: { "Content-Type": getMime(filePath), ...headers }
|
|
@@ -30669,7 +31037,7 @@ function staticFilesHandler(ws, devMode, moduleAccessMap) {
|
|
|
30669
31037
|
return (_req, url, ctx) => {
|
|
30670
31038
|
const path4 = url.pathname;
|
|
30671
31039
|
if (path4.startsWith("/shell/"))
|
|
30672
|
-
return serveFile(
|
|
31040
|
+
return serveFile(join17(ws.shellDir, path4.slice(7)), ctx.corsHeaders);
|
|
30673
31041
|
if (path4.startsWith("/modules/")) {
|
|
30674
31042
|
const fileWithParams = path4.slice(9);
|
|
30675
31043
|
const filename = fileWithParams.split("?")[0];
|
|
@@ -30681,23 +31049,25 @@ function staticFilesHandler(ws, devMode, moduleAccessMap) {
|
|
|
30681
31049
|
return new Response("Forbidden", { status: 403, headers: ctx.corsHeaders });
|
|
30682
31050
|
}
|
|
30683
31051
|
}
|
|
30684
|
-
return serveFile(
|
|
31052
|
+
return serveFile(join17(ws.modulesDir, filename), {
|
|
30685
31053
|
...ctx.corsHeaders,
|
|
30686
31054
|
"Cache-Control": devMode ? "no-cache" : "max-age=31536000,immutable"
|
|
30687
31055
|
});
|
|
30688
31056
|
}
|
|
30689
31057
|
if (path4.startsWith("/locales/"))
|
|
30690
|
-
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);
|
|
30691
31061
|
if (path4 === "/styles.css")
|
|
30692
|
-
return serveFile(
|
|
31062
|
+
return serveFile(join17(ws.arcDir, "styles.css"), ctx.corsHeaders);
|
|
30693
31063
|
if (path4 === "/theme.css")
|
|
30694
|
-
return serveFile(
|
|
31064
|
+
return serveFile(join17(ws.arcDir, "theme.css"), ctx.corsHeaders);
|
|
30695
31065
|
if ((path4 === "/manifest.json" || path4 === "/manifest.webmanifest") && ws.manifest) {
|
|
30696
31066
|
return serveFile(ws.manifest.path, ctx.corsHeaders);
|
|
30697
31067
|
}
|
|
30698
31068
|
if (path4.lastIndexOf(".") > path4.lastIndexOf("/")) {
|
|
30699
|
-
const publicFile =
|
|
30700
|
-
if (
|
|
31069
|
+
const publicFile = join17(ws.publicDir, path4.slice(1));
|
|
31070
|
+
if (existsSync14(publicFile))
|
|
30701
31071
|
return serveFile(publicFile, ctx.corsHeaders);
|
|
30702
31072
|
}
|
|
30703
31073
|
return null;
|
|
@@ -30794,7 +31164,10 @@ async function startPlatformServer(opts) {
|
|
|
30794
31164
|
const cors = {
|
|
30795
31165
|
"Access-Control-Allow-Origin": "*",
|
|
30796
31166
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
|
|
30797
|
-
"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"
|
|
30798
31171
|
};
|
|
30799
31172
|
const server = Bun.serve({
|
|
30800
31173
|
port,
|
|
@@ -30832,10 +31205,10 @@ async function startPlatformServer(opts) {
|
|
|
30832
31205
|
};
|
|
30833
31206
|
}
|
|
30834
31207
|
const { createBunSQLiteAdapterFactory: createBunSQLiteAdapterFactory2 } = await Promise.resolve().then(() => (init_dist(), exports_dist2));
|
|
30835
|
-
const dbPath = opts.dbPath ||
|
|
31208
|
+
const dbPath = opts.dbPath || join17(ws.arcDir, "data", "arc.db");
|
|
30836
31209
|
const dbDir = dbPath.substring(0, dbPath.lastIndexOf("/"));
|
|
30837
31210
|
if (dbDir)
|
|
30838
|
-
|
|
31211
|
+
mkdirSync12(dbDir, { recursive: true });
|
|
30839
31212
|
const arcServer = await createArcServer({
|
|
30840
31213
|
context,
|
|
30841
31214
|
dbAdapterFactory: createBunSQLiteAdapterFactory2(dbPath),
|
|
@@ -30860,10 +31233,10 @@ async function startPlatformServer(opts) {
|
|
|
30860
31233
|
}
|
|
30861
31234
|
|
|
30862
31235
|
// src/commands/platform-dev.ts
|
|
30863
|
-
async function platformDev() {
|
|
31236
|
+
async function platformDev(opts = {}) {
|
|
30864
31237
|
const ws = resolveWorkspace();
|
|
30865
31238
|
const port = 5005;
|
|
30866
|
-
let manifest = await buildAll(ws);
|
|
31239
|
+
let manifest = await buildAll(ws, { noCache: opts.noCache });
|
|
30867
31240
|
log2("Loading server context...");
|
|
30868
31241
|
const { context, moduleAccess } = await loadServerContext(ws.packages);
|
|
30869
31242
|
if (context) {
|
|
@@ -30878,7 +31251,7 @@ async function platformDev() {
|
|
|
30878
31251
|
manifest,
|
|
30879
31252
|
context,
|
|
30880
31253
|
moduleAccess,
|
|
30881
|
-
dbPath:
|
|
31254
|
+
dbPath: join18(ws.rootDir, ".arc", "data", "dev.db"),
|
|
30882
31255
|
devMode: true,
|
|
30883
31256
|
arcEntries
|
|
30884
31257
|
});
|
|
@@ -30888,53 +31261,44 @@ async function platformDev() {
|
|
|
30888
31261
|
log2("Watching for changes...");
|
|
30889
31262
|
let rebuildTimer = null;
|
|
30890
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
|
+
};
|
|
30891
31284
|
for (const pkg of ws.packages) {
|
|
30892
|
-
const srcDir =
|
|
30893
|
-
if (!
|
|
31285
|
+
const srcDir = join18(pkg.path, "src");
|
|
31286
|
+
if (!existsSync15(srcDir))
|
|
30894
31287
|
continue;
|
|
30895
31288
|
watch(srcDir, { recursive: true }, (_event, filename) => {
|
|
30896
31289
|
if (!filename || filename.includes(".arc") || filename.endsWith(".d.ts") || filename.includes("node_modules") || filename.includes("dist"))
|
|
30897
31290
|
return;
|
|
30898
31291
|
if (!filename.endsWith(".ts") && !filename.endsWith(".tsx"))
|
|
30899
31292
|
return;
|
|
30900
|
-
|
|
30901
|
-
clearTimeout(rebuildTimer);
|
|
30902
|
-
rebuildTimer = setTimeout(async () => {
|
|
30903
|
-
if (isRebuilding)
|
|
30904
|
-
return;
|
|
30905
|
-
isRebuilding = true;
|
|
30906
|
-
log2("Rebuilding...");
|
|
30907
|
-
try {
|
|
30908
|
-
manifest = await buildPackages(ws.rootDir, ws.modulesDir, ws.packages);
|
|
30909
|
-
await buildStyles(ws.rootDir, ws.arcDir);
|
|
30910
|
-
platform3.setManifest(manifest);
|
|
30911
|
-
platform3.notifyReload(manifest);
|
|
30912
|
-
ok(`Rebuilt ${manifest.modules.length} module(s)`);
|
|
30913
|
-
} catch (e2) {
|
|
30914
|
-
console.error(`Rebuild failed: ${e2}`);
|
|
30915
|
-
} finally {
|
|
30916
|
-
isRebuilding = false;
|
|
30917
|
-
}
|
|
30918
|
-
}, 300);
|
|
31293
|
+
triggerRebuild();
|
|
30919
31294
|
});
|
|
30920
31295
|
}
|
|
30921
|
-
const localesDir =
|
|
30922
|
-
if (
|
|
30923
|
-
let poTimer = null;
|
|
31296
|
+
const localesDir = join18(ws.rootDir, "locales");
|
|
31297
|
+
if (existsSync15(localesDir)) {
|
|
30924
31298
|
watch(localesDir, { recursive: false }, (_event, filename) => {
|
|
30925
31299
|
if (!filename?.endsWith(".po"))
|
|
30926
31300
|
return;
|
|
30927
|
-
|
|
30928
|
-
clearTimeout(poTimer);
|
|
30929
|
-
poTimer = setTimeout(async () => {
|
|
30930
|
-
try {
|
|
30931
|
-
compileAllCatalogs(localesDir, join16(ws.arcDir, "locales"));
|
|
30932
|
-
ok("Translations recompiled");
|
|
30933
|
-
platform3.notifyReload(manifest);
|
|
30934
|
-
} catch (e2) {
|
|
30935
|
-
console.error(`Translation compile failed: ${e2}`);
|
|
30936
|
-
}
|
|
30937
|
-
}, 200);
|
|
31301
|
+
triggerRebuild();
|
|
30938
31302
|
});
|
|
30939
31303
|
}
|
|
30940
31304
|
const cleanup = () => {
|
|
@@ -30946,17 +31310,17 @@ async function platformDev() {
|
|
|
30946
31310
|
}
|
|
30947
31311
|
|
|
30948
31312
|
// src/commands/platform-start.ts
|
|
30949
|
-
import { existsSync as
|
|
30950
|
-
import { join as
|
|
31313
|
+
import { existsSync as existsSync16, readFileSync as readFileSync13 } from "fs";
|
|
31314
|
+
import { join as join19 } from "path";
|
|
30951
31315
|
async function platformStart() {
|
|
30952
31316
|
const ws = resolveWorkspace();
|
|
30953
31317
|
const port = parseInt(process.env.PORT || "5005", 10);
|
|
30954
|
-
const manifestPath =
|
|
30955
|
-
if (!
|
|
31318
|
+
const manifestPath = join19(ws.modulesDir, "manifest.json");
|
|
31319
|
+
if (!existsSync16(manifestPath)) {
|
|
30956
31320
|
err("No build found. Run `arc platform build` first.");
|
|
30957
31321
|
process.exit(1);
|
|
30958
31322
|
}
|
|
30959
|
-
const manifest = JSON.parse(
|
|
31323
|
+
const manifest = JSON.parse(readFileSync13(manifestPath, "utf-8"));
|
|
30960
31324
|
log2("Loading server context...");
|
|
30961
31325
|
const { context, moduleAccess } = await loadServerContext(ws.packages);
|
|
30962
31326
|
if (context) {
|
|
@@ -30974,7 +31338,7 @@ async function platformStart() {
|
|
|
30974
31338
|
manifest,
|
|
30975
31339
|
context,
|
|
30976
31340
|
moduleAccess,
|
|
30977
|
-
dbPath:
|
|
31341
|
+
dbPath: join19(ws.rootDir, ".arc", "data", "prod.db"),
|
|
30978
31342
|
devMode: false,
|
|
30979
31343
|
deployApi,
|
|
30980
31344
|
arcEntries
|
|
@@ -30996,8 +31360,8 @@ program2.name("arc").description("CLI tool for Arc framework").version("0.0.3");
|
|
|
30996
31360
|
program2.command("dev").description("Run development mode for Arc framework").action(dev);
|
|
30997
31361
|
program2.command("build").description("Build all clients and declarations").action(build);
|
|
30998
31362
|
var platform3 = program2.command("platform").description("Platform commands \u2014 run full stack (server + UI)");
|
|
30999
|
-
platform3.command("dev").description("Start platform in dev mode (Bun server + Vite HMR)").action(platformDev);
|
|
31000
|
-
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 }));
|
|
31001
31365
|
platform3.command("start").description("Start platform in production mode (requires prior build)").action(platformStart);
|
|
31002
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));
|
|
31003
31367
|
program2.parse(process.argv);
|