@arcote.tech/arc-cli 0.6.1 → 0.6.2

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 CHANGED
@@ -26446,7 +26446,7 @@ ${colors3.yellow}Type declaration errors:${colors3.reset}`);
26446
26446
  }
26447
26447
 
26448
26448
  // src/platform/shared.ts
26449
- import { copyFileSync as copyFileSync2, existsSync as existsSync10, mkdirSync as mkdirSync10, readFileSync as readFileSync11, readdirSync as readdirSync6, rmSync as rmSync3, writeFileSync as writeFileSync10 } from "fs";
26449
+ import { copyFileSync, existsSync as existsSync10, mkdirSync as mkdirSync10, readFileSync as readFileSync11, readdirSync as readdirSync6, rmSync as rmSync3, writeFileSync as writeFileSync10 } from "fs";
26450
26450
  import { dirname as dirname6, join as join12 } from "path";
26451
26451
 
26452
26452
  // src/builder/module-builder.ts
@@ -27254,7 +27254,7 @@ async function buildStyles(rootDir, arcDir, packages, themePath, cache, noCache)
27254
27254
 
27255
27255
  // src/builder/dependency-collector.ts
27256
27256
  import { createHash } from "crypto";
27257
- import { copyFileSync, existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
27257
+ import { existsSync as existsSync9, mkdirSync as mkdirSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
27258
27258
  import { basename as basename3, join as join10 } from "path";
27259
27259
  var FRAMEWORK_PEERS = [
27260
27260
  "@arcote.tech/arc",
@@ -27276,16 +27276,22 @@ function collectFrameworkDeps(arcDir, rootDir, packages) {
27276
27276
  const manifestPath = join10(arcDir, "package.json");
27277
27277
  writeFileSync8(manifestPath, JSON.stringify(manifest, null, 2) + `
27278
27278
  `);
27279
- const rootLock = join10(rootDir, "bun.lock");
27280
27279
  const targetLock = join10(arcDir, "bun.lock");
27281
- if (existsSync9(rootLock)) {
27282
- copyFileSync(rootLock, targetLock);
27283
- }
27284
- const hash = sha256OfFiles2([manifestPath, targetLock]);
27280
+ writeFileSync8(targetLock, "");
27281
+ const hash = sha256ConcatHex([manifestPath, targetLock]);
27285
27282
  writeFileSync8(join10(arcDir, ".deps-hash"), hash + `
27286
27283
  `);
27287
27284
  return { hash, manifestPath };
27288
27285
  }
27286
+ function sha256ConcatHex(paths) {
27287
+ const hash = createHash("sha256");
27288
+ for (const p of paths) {
27289
+ if (existsSync9(p)) {
27290
+ hash.update(readFileSync9(p));
27291
+ }
27292
+ }
27293
+ return hash.digest("hex");
27294
+ }
27289
27295
  function collectModuleDeps(arcDir, pkg) {
27290
27296
  const safeName = basename3(pkg.path);
27291
27297
  const moduleDir = join10(arcDir, "modules", safeName);
@@ -27613,7 +27619,7 @@ async function copyBrowserAssets(ws, cache, noCache) {
27613
27619
  for (const asset of assets) {
27614
27620
  const dest = join12(ws.assetsDir, asset.to);
27615
27621
  mkdirSync10(dirname6(dest), { recursive: true });
27616
- copyFileSync2(asset.src, dest);
27622
+ copyFileSync(asset.src, dest);
27617
27623
  outputHashes[asset.to] = sha256Hex(readFileSync11(dest));
27618
27624
  }
27619
27625
  updateCache(cache, unitId, inputHash, { outputHashes });
@@ -28786,10 +28792,7 @@ async function syncEnv(inputs) {
28786
28792
  console.log("[arc] Pushing framework deps...");
28787
28793
  const form = new FormData;
28788
28794
  form.append("package.json", new Blob([readFileSync13(join17(ws.arcDir, "package.json"))]), "package.json");
28789
- const lockPath = join17(ws.arcDir, "bun.lock");
28790
- if (existsSync13(lockPath)) {
28791
- form.append("bun.lock", new Blob([readFileSync13(lockPath)]), "bun.lock");
28792
- }
28795
+ form.append("bun.lock", new Blob([""]), "bun.lock");
28793
28796
  const res = await fetch(`${base2()}/api/deploy/framework`, {
28794
28797
  method: "POST",
28795
28798
  body: form
@@ -31191,7 +31194,7 @@ function createDeployApiHandler(opts) {
31191
31194
  writeFileSync15(join19(opts.ws.arcDir, "package.json"), Buffer.from(await pkgFile.arrayBuffer()));
31192
31195
  writeFileSync15(join19(opts.ws.arcDir, "bun.lock"), Buffer.from(await lockFile.arrayBuffer()));
31193
31196
  const start = Date.now();
31194
- const installOk = await runBun(["install", "--production", "--frozen-lockfile"], opts.ws.arcDir);
31197
+ const installOk = await runBun(["install", "--production"], opts.ws.arcDir);
31195
31198
  if (!installOk) {
31196
31199
  return Response.json({ error: "bun install failed" }, { status: 500, headers: cors });
31197
31200
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arcote.tech/arc-cli",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "CLI tool for Arc framework",
5
5
  "module": "index.ts",
6
6
  "main": "dist/index.js",
@@ -12,12 +12,12 @@
12
12
  "build": "bun build --target=bun ./src/index.ts --outdir=dist --external @arcote.tech/arc --external @arcote.tech/arc-ds --external @arcote.tech/arc-react --external @arcote.tech/platform && chmod +x dist/index.js"
13
13
  },
14
14
  "dependencies": {
15
- "@arcote.tech/arc": "^0.6.1",
16
- "@arcote.tech/arc-ds": "^0.6.1",
17
- "@arcote.tech/arc-react": "^0.6.1",
18
- "@arcote.tech/arc-host": "^0.6.1",
19
- "@arcote.tech/arc-adapter-db-sqlite": "^0.6.1",
20
- "@arcote.tech/platform": "^0.6.1",
15
+ "@arcote.tech/arc": "^0.6.2",
16
+ "@arcote.tech/arc-ds": "^0.6.2",
17
+ "@arcote.tech/arc-react": "^0.6.2",
18
+ "@arcote.tech/arc-host": "^0.6.2",
19
+ "@arcote.tech/arc-adapter-db-sqlite": "^0.6.2",
20
+ "@arcote.tech/platform": "^0.6.2",
21
21
  "@clack/prompts": "^0.9.0",
22
22
  "commander": "^11.1.0",
23
23
  "chokidar": "^3.5.3",
@@ -1,5 +1,5 @@
1
1
  import { createHash } from "node:crypto";
2
- import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
3
3
  import { basename, join } from "path";
4
4
  import type { WorkspacePackage } from "./module-builder";
5
5
 
@@ -59,20 +59,32 @@ export function collectFrameworkDeps(
59
59
  const manifestPath = join(arcDir, "package.json");
60
60
  writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + "\n");
61
61
 
62
- // Copy workspace bun.lock so the container can use --frozen-lockfile for
63
- // deterministic framework installs. Per-module installs run without it (no
64
- // per-module lockfile in MVP).
65
- const rootLock = join(rootDir, "bun.lock");
62
+ // Empty bun.lock placeholder. We CAN'T copy the workspace bun.lock it
63
+ // contains the full dep graph (workspaces, dev deps) but our framework
64
+ // manifest is just the singleton peers. `bun install --frozen-lockfile`
65
+ // would reject as "lockfile had changes". An empty lockfile is harmless
66
+ // when server runs `bun install --production` without freeze.
66
67
  const targetLock = join(arcDir, "bun.lock");
67
- if (existsSync(rootLock)) {
68
- copyFileSync(rootLock, targetLock);
69
- }
68
+ writeFileSync(targetLock, "");
70
69
 
71
- const hash = sha256OfFiles([manifestPath, targetLock]);
70
+ // Hash MUST match the server-side computation in deploy-api.ts
71
+ // (sha256 over concat of raw bytes) — otherwise every deploy would think
72
+ // framework changed and re-install in a loop.
73
+ const hash = sha256ConcatHex([manifestPath, targetLock]);
72
74
  writeFileSync(join(arcDir, ".deps-hash"), hash + "\n");
73
75
  return { hash, manifestPath };
74
76
  }
75
77
 
78
+ function sha256ConcatHex(paths: string[]): string {
79
+ const hash = createHash("sha256");
80
+ for (const p of paths) {
81
+ if (existsSync(p)) {
82
+ hash.update(readFileSync(p));
83
+ }
84
+ }
85
+ return hash.digest("hex");
86
+ }
87
+
76
88
  // ---------------------------------------------------------------------------
77
89
  // Per-module deps
78
90
  // ---------------------------------------------------------------------------
@@ -116,14 +116,12 @@ export async function syncEnv(inputs: SyncInputs): Promise<SyncOutcome> {
116
116
  new Blob([readFileSync(join(ws.arcDir, "package.json"))]),
117
117
  "package.json",
118
118
  );
119
- const lockPath = join(ws.arcDir, "bun.lock");
120
- if (existsSync(lockPath)) {
121
- form.append(
122
- "bun.lock",
123
- new Blob([readFileSync(lockPath)]),
124
- "bun.lock",
125
- );
126
- }
119
+ // Ship a placeholder bun.lock (server validates its presence) but
120
+ // intentionally empty — workspace bun.lock has the full dep graph and
121
+ // would trip --frozen-lockfile against our slim framework package.json.
122
+ // The server side runs `bun install --production` without freeze, so an
123
+ // empty lock is harmless: bun re-resolves against package.json.
124
+ form.append("bun.lock", new Blob([""]), "bun.lock");
127
125
  const res = await fetch(`${base()}/api/deploy/framework`, {
128
126
  method: "POST",
129
127
  body: form,
@@ -98,8 +98,12 @@ export function createDeployApiHandler(opts: DeployApiOptions): ArcHttpHandler {
98
98
  );
99
99
 
100
100
  const start = Date.now();
101
+ // No --frozen-lockfile: workspace bun.lock from the source project
102
+ // contains the full dep graph, but our framework manifest is a subset.
103
+ // Bun would reject as "lockfile had changes". Let bun re-resolve against
104
+ // the framework-only package.json.
101
105
  const installOk = await runBun(
102
- ["install", "--production", "--frozen-lockfile"],
106
+ ["install", "--production"],
103
107
  opts.ws.arcDir,
104
108
  );
105
109
  if (!installOk) {