@arch-platform/distribution 0.0.0-stage → 0.1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 neo1sre
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,112 @@
1
- # Temporary Holding Version
1
+ # @arch-platform/distribution
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ CLI de distribución de ARCH para ejecutar el MVP de **build** en un workspace consumidor.
4
+
5
+ > Estado: MVP de build. Este paquete expone actualmente el comando `build`; no documenta ni promete otros comandos de ARCH.
6
+
7
+ ## Requisitos
8
+
9
+ - Node.js compatible con el workspace consumidor.
10
+ - pnpm, si el workspace se administra con pnpm.
11
+ - Un workspace que contenga los paquetes que ARCH debe compilar.
12
+ - TypeScript instalado en el paquete consumidor cuando se utiliza el builder `tsc`.
13
+
14
+ ## Instalación
15
+
16
+ Desde la raíz del workspace consumidor, una vez publicado el paquete en el registro configurado:
17
+
18
+ ```bash
19
+ pnpm add -D @arch-platform/distribution
20
+ ```
21
+
22
+ El paquete registra el ejecutable `arch-cli`.
23
+
24
+ ## Uso
25
+
26
+ Mostrar la ayuda:
27
+
28
+ ```bash
29
+ pnpm exec arch-cli --help
30
+ ```
31
+
32
+ Mostrar la ayuda de build:
33
+
34
+ ```bash
35
+ pnpm exec arch-cli build --help
36
+ ```
37
+
38
+ Compilar el workspace:
39
+
40
+ ```bash
41
+ pnpm exec arch-cli build
42
+ ```
43
+
44
+ Compilar un paquete específico:
45
+
46
+ ```bash
47
+ pnpm exec arch-cli build --package @scope/package-name
48
+ ```
49
+
50
+ `--package` recibe el nombre del paquete tal como aparece en su `package.json`.
51
+
52
+ ## Configuración del paquete
53
+
54
+ ARCH lee la configuración `arch` del `package.json` del paquete que se desea compilar. Ejemplo mínimo para un paquete TypeScript que genera `dist`:
55
+
56
+ ```json
57
+ {
58
+ "name": "@scope/package-name",
59
+ "version": "1.0.0",
60
+ "arch": {
61
+ "artifactType": "runtime",
62
+ "build": {
63
+ "builder": "tsc",
64
+ "outputs": ["dist"]
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ - `artifactType`: clasifica el artefacto; en este ejemplo, `runtime`.
71
+ - `build.builder`: identifica el builder que ARCH debe utilizar; en este ejemplo, `tsc`.
72
+ - `build.outputs`: directorios de salida del build; en este ejemplo, `dist`.
73
+
74
+ La configuración y los requisitos concretos del builder deben corresponder al paquete consumidor.
75
+
76
+ ## Resultado del comando
77
+
78
+ El CLI muestra un resumen del build con estos contadores:
79
+
80
+ - `Executed`: builds ejecutados.
81
+ - `Restored`: artefactos restaurados desde la caché.
82
+ - `Cached`: resultados reutilizados sin ejecutar el build.
83
+ - `Failed`: builds fallidos.
84
+
85
+ El comando informa `BUILD COMPLETED` cuando no hay fallos y `BUILD FAILED` cuando hay uno o más. El proceso termina con código `0` si no hubo fallos y `1` en caso contrario.
86
+
87
+ ## Caché y restauración
88
+
89
+ El MVP de build puede:
90
+
91
+ 1. Ejecutar el build inicial.
92
+ 2. Reutilizar el resultado cuando no cambian las entradas relevantes.
93
+ 3. Invalidar la caché y volver a ejecutar cuando cambia el código fuente.
94
+ 4. Restaurar el artefacto almacenado cuando la salida local falta y existe un resultado restaurable.
95
+
96
+ Los contadores del resumen permiten observar cuál de estos caminos ocurrió.
97
+
98
+ ## Alcance del MVP
99
+
100
+ Este paquete documenta únicamente la distribución del CLI y el comando `build`, incluyendo ejecución, caché, invalidación y restauración.
101
+
102
+ No implica que otros comandos o capacidades de ARCH estén disponibles a través de este paquete.
103
+
104
+ ## Desarrollo del paquete
105
+
106
+ Dentro del monorepo ARCH:
107
+
108
+ ```bash
109
+ pnpm arch build --package @arch-platform/distribution
110
+ ```
111
+
112
+ El paquete se configura para generar `dist` mediante `tsup`. El ejecutable publicado es `bin/arch-cli.js`.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+
3
+ import '../dist/bin-cli.js';
@@ -0,0 +1,11 @@
1
+ import {cac}from'cac';import {readFile,stat,mkdir,writeFile,access,readdir,rename,cp,rm}from'fs/promises';import {join,normalize,relative,isAbsolute,resolve,dirname,basename}from'path';import {lstatSync,statSync,mkdirSync,rmSync,readFileSync,readdirSync,renameSync,writeFileSync,cpSync}from'fs';import {createHash}from'crypto';import {createScanner,ScriptTarget,LanguageVariant,SyntaxKind}from'typescript';import {execa}from'execa';var _=class{compare(e,t){let r=new Map(e.map(h=>[h.path,h])),i=new Map(t.map(h=>[h.path,h])),o=[],a=[],n=[];for(let[h,p]of i){let u=r.get(h);if(!u){o.push(h);continue}(u.sizeInBytes!==p.sizeInBytes||u.integrity!==p.integrity)&&a.push(h);}for(let h of r.keys())i.has(h)||n.push(h);o.sort(),a.sort(),n.sort();let c={added:o,modified:a,deleted:n};return {isIdentical:o.length===0&&a.length===0&&n.length===0,diff:c}}};var k=class{filesystem;pathService;hashService;constructor(e,t,r){this.filesystem=e,this.pathService=t,this.hashService=r;}async fingerprint(e,t){let r=[];for(let i of t){let o=this.pathService.join(e,i);if(!await this.filesystem.exists(o))throw new Error(`Cannot fingerprint missing artifact output: ${i}`);if(await this.getEntryKind(o)==="file"){let h=await this.filesystem.readBuffer(o);r.push({path:i,sizeInBytes:h.byteLength,integrity:`sha256:${this.hashService.hash(h)}`});continue}let n=await this.fingerprintDirectory(o),c=n.reduce((h,p)=>h+p.sizeInBytes,0);r.push({path:i,sizeInBytes:c,integrity:`sha256:${this.hashService.hashObject({kind:"directory",entries:n})}`});}return r}async getEntryKind(e){let t=this.pathService.dirname(e),r=this.pathService.basename(e),o=(await this.filesystem.readDirectory(t)).find(a=>a.name===r);if(!o)throw new Error(`Cannot determine artifact output type: ${e}`);if(o.isSymbolicLink)throw new Error(`Symbolic links are not supported as artifact outputs: ${e}`);if(o.isFile)return "file";if(o.isDirectory)return "directory";throw new Error(`Unsupported artifact output type: ${e}`)}async fingerprintDirectory(e){let t=await this.filesystem.readDirectory(e),r=[];for(let i of t){if(i.isSymbolicLink)throw new Error(`Symbolic links are not supported in artifact outputs: ${i.path}`);let o=this.pathService.join(e,i.name),a=this.pathService.relative(e,o).replace(/\\/g,"/");if(i.isDirectory){r.push({path:a,kind:"directory",sizeInBytes:0});let c=await this.fingerprintDirectory(o);for(let h of c)r.push({...h,path:`${a}/${h.path}`});continue}if(!i.isFile)throw new Error(`Unsupported artifact entry type: ${o}`);let n=await this.filesystem.readBuffer(o);r.push({path:a,kind:"file",sizeInBytes:n.byteLength,integrity:`sha256:${this.hashService.hash(n)}`});}return r.sort((i,o)=>i.path.localeCompare(o.path))}};var N=class{filesystem;pathService;constructor(e,t){this.filesystem=e,this.pathService=t;}async publish(e,t,r){let i=false,o=r.temporary("tmp");try{await this.filesystem.remove(o.root),await this.filesystem.createDirectory(o.root);for(let a of t.outputs){let n=this.pathService.join(e,a),c=o.output(a);await this.filesystem.copy(n,c);}await this.filesystem.writeJson(o.manifest(),t),await this.filesystem.remove(r.root),await this.filesystem.rename(o.root,r.root),i=!0;}finally{i||await this.filesystem.remove(o.root);}}};var $=class{create(e,t){return {packageName:e,id:wr(t)}}};function wr(s){return `${s.sourceHash}-${s.configHash}-${s.depsHash}`}function w(s,e=2){let t=new WeakSet,r=(i,o)=>{if(o instanceof Error)return {name:o.name,message:o.message,stack:o.stack};if(typeof o=="bigint")return o.toString();if(!(typeof o>"u")){if(typeof o=="symbol")return o.toString();if(o instanceof Map)return Object.fromEntries(o);if(o instanceof Set)return [...o];if(typeof o=="object"&&o!==null){if(t.has(o))return "[Circular]";t.add(o);}return o}};try{return JSON.stringify(s,r,e)}catch{return "[unserializable]"}}var nt={trace:{write:console.debug,symbol:"\u{1F50D} "},debug:{write:console.debug,symbol:"\xB7 "},info:{write:console.log,symbol:"\u2139 - INFO "},success:{write:console.log,symbol:"\u2705 - SUCCESS "},warn:{write:console.warn,symbol:"\u26A0 - WARN "},error:{write:console.error,symbol:"\u274C - ERROR "}};var he=/(token|secret|password|api[-_]?key)/i;function ct(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,he.test(e)?"***":t]))}function ht(s){if(!s)return;let e=Object.entries(s).map(([t,r])=>he.test(t)?[t,"***"]:t==="env"&&r!==null&&typeof r=="object"?[t,ct(r)]:[t,r]);return Object.fromEntries(e)}["1","true","yes","on"].includes((process.env.ARCH_TRACE??"").toLowerCase());process.env.ARCH_TRACE_COMPONENT;function pt(){return ["1","true","yes","on"].includes((process.env.ARCH_TRACE??"").toLowerCase())}function ut(){return process.env.ARCH_TRACE_COMPONENT}var Ye=class{createLogger(e){return {trace:(t,r)=>{this.write("trace",t,this.mergeOptions(e,r));},debug:(t,r)=>{this.write("debug",t,this.mergeOptions(e,r));},info:(t,r)=>{this.write("info",t,this.mergeOptions(e,r));},success:(t,r)=>{this.write("success",t,this.mergeOptions(e,r));},warn:(t,r)=>{this.write("warn",t,this.mergeOptions(e,r));},error:(t,r)=>{this.write("error",t,this.mergeOptions(e,r));}}}write(e,t,r={}){if(e==="trace"){if(!pt())return;let x=ut();if(x&&r.source?.component!==x)return}let{source:i,metadata:o}=r,a=new Date().toISOString(),n=i||o?ht({...i?{source:i}:{},...o?{metadata:o}:{}}):void 0,c=`${t}`,h=n?`[${a}] ${c}
2
+ ${w(n,2)}`:`[${a}] ${c}`,{write:p,symbol:u}=nt[e];p(`${u}${h}`);}mergeOptions(e,t){return {...t,source:{...e,...t?.source}}}},v=new Ye;var L=class{layoutFactory;publisher;filesystem;pathService;fingerprinter;comparator;logger=v.createLogger({component:"FilesystemArtifactCache"});constructor(e,t,r,i,o,a){this.layoutFactory=e,this.publisher=t,this.filesystem=r,this.pathService=i,this.fingerprinter=o,this.comparator=a;}async save(e,t,r){let i=this.layoutFactory.create(e),o=await this.fingerprinter.fingerprint(t,r),a={artifact:e,outputs:r,outputFingerprint:o,createdAt:Date.now(),schemaVersion:1};await this.publisher.publish(t,a,i);}async exists(e){let t=this.layoutFactory.create(e);try{let r=await this.loadArtifactManifest(t.manifest());return !r||!this.hasValidFingerprints(r)?!1:await this.matchesFingerprints(t.root,r)}catch(r){return this.logger.error("artifact.cache.exists.failed",{metadata:{artifact:e.id,error:r instanceof Error?r.message:String(r)}}),false}}async verifyOutputs(e,t){let r=this.layoutFactory.create(e);try{let i=await this.loadArtifactManifest(r.manifest());return !i||!this.hasValidFingerprints(i)?!1:await this.matchesFingerprints(t,i)}catch{return false}}async restore(e,t){let r=this.layoutFactory.create(e);try{let i=await this.loadArtifactManifest(r.manifest());if(!i||!this.hasValidFingerprints(i)||!await this.matchesFingerprints(r.root,i))return !1;for(let o of i.outputs){let a=r.output(o),n=this.pathService.join(t,o);await this.filesystem.remove(n),await this.filesystem.copy(a,n);}return await this.matchesFingerprints(t,i)}catch(i){return this.logger.error("artifact.restore.failed",{metadata:{method:"async restore",artifact:e.id,error:i instanceof Error?i.message:String(i)}}),false}}hasValidFingerprints(e){let t=e.outputFingerprint;if(!t||t.length!==e.outputs.length)return false;let r=new Set(e.outputs);if(r.size!==e.outputs.length)return false;let i=new Set;for(let o of t){if(!o||typeof o.path!="string"||!r.has(o.path)||i.has(o.path)||!Number.isSafeInteger(o.sizeInBytes)||o.sizeInBytes<0||typeof o.integrity!="string"||!/^sha256:[a-f0-9]{64}$/.test(o.integrity))return false;i.add(o.path);}return i.size===r.size}async matchesFingerprints(e,t){let r=t.outputFingerprint;if(!r)return this.logger.error("artifact.cache.fingerprint.missing",{metadata:{artifact:t.artifact.id,root:e}}),false;let i=await this.fingerprinter.fingerprint(e,t.outputs);if(i.length!==t.outputs.length)return this.logger.error("artifact.cache.fingerprint.count-mismatch",{metadata:{artifact:t.artifact.id,root:e,expectedCount:t.outputs.length,actualCount:i.length,expected:r,actual:i}}),false;let o=this.comparator.compare(r,i);return o.isIdentical||this.logger.error("artifact.cache.fingerprint.mismatch",{metadata:{artifact:t.artifact.id,root:e,expected:r,actual:i,diff:o.diff}}),o.isIdentical}async loadArtifactManifest(e){if(!await this.filesystem.exists(e))return;let t=await this.filesystem.readJson(e);return this.isArtifactManifest(t)?t:void 0}isArtifact(e){if(!e||typeof e!="object")return false;let t=e;return typeof t.packageName=="string"&&typeof t.id=="string"}isArtifactManifest(e){if(!e||typeof e!="object")return false;let t=e;return this.isArtifact(t.artifact)&&Array.isArray(t.outputs)&&t.outputs.every(r=>typeof r=="string")&&typeof t.createdAt=="number"&&t.schemaVersion===1}};var Z=class s{root;pathService;constructor(e,t){this.root=e,this.pathService=t;}manifest(){return this.pathService.join(this.root,"manifest.json")}output(e){return this.pathService.join(this.root,e)}temporary(e){return new s(`${this.root}.${e}`,this.pathService)}};var H=class{cacheRoot;pathService;constructor(e,t){this.cacheRoot=e,this.pathService=t;}create(e){return new Z(this.pathService.join(this.cacheRoot,e.packageName,e.id),this.pathService)}};var I=class{filesystem;pathService;constructor(e,t){this.filesystem=e,this.pathService=t;}async prepare(e,t){let r=this.pathService.resolve(e),i=t.map(a=>{if(a.trim().length===0||this.pathService.isAbsolute(a)||/^[a-zA-Z]:/.test(a)||/^(?:[/\\]{2}|[/\\])/.test(a))throw new Error(`Invalid build output path: "${a}". Outputs must be relative to the package root.`);if(a.replace(/\\/g,"/").split("/").includes(".."))throw new Error(`Invalid build output path: "${a}". Traversal segments are not allowed.`);let h=this.pathService.resolve(r,a),p=this.pathService.relative(r,h).replace(/\\/g,"/");if(p===""||p==="."||p===".."||p.startsWith("../")||this.pathService.isAbsolute(p))throw new Error(`Build output "${a}" resolves outside the allowed output area: "${h}".`);return h}),o=[];for(let a of i)await this.filesystem.exists(a)&&o.push(a);for(let a of o)await this.filesystem.remove(a);}};var ee=class{filesystem;constructor(e){this.filesystem=e;}async read(){let e="/.arch-platform/history/artifact-state-history.json";if(!await this.filesystem.exists(e))return new Map;let t=await this.filesystem.readJson(e);return new Map(Object.entries(t.artifacts))}};var te=class{filesystem;constructor(e){this.filesystem=e;}async write(e){let t="/.arch-platform/history",r=`${t}/artifact-state-history.json`;await this.filesystem.createDirectory(t),await this.filesystem.writeJson(r,{schemaVersion:1,artifacts:Object.fromEntries(e)});}};var re=class{filesystem;constructor(e){this.filesystem=e;}async read(){let e="/.arch-platform/artifact-state.json";if(!await this.filesystem.exists(e))return new Map;let t=await this.filesystem.readJson(e);return new Map(Object.entries(t.artifacts))}};var se=class{filesystem;constructor(e){this.filesystem=e;}async write(e){await this.filesystem.writeJson("/.arch-platform/artifact-state.json",{schemaVersion:1,artifacts:Object.fromEntries(e)});}};var j=class{fileSystem;pathService;constructor(e,t){this.fileSystem=e,this.pathService=t;}async exists(e,t){for(let r of t){let i=this.pathService.join(e,r);if(!await this.fileSystem.exists(i))return false}return true}};function R(s){return JSON.parse(s)}var Ue={INVALID_PACKAGE_MANIFEST:"node.workspace.provider.invalid.package.manifest",NODE_WORKSPACE_PROVIDER_BOUNDARIES_LOAD_FAILED:"node.workspace.provider.boundaries.load.fail"};function Ke(s){return s instanceof Error&&"code"in s}function dt(s,...e){return Ke(s)&&e.includes(String(s.code))}function l(...s){return join(...s)}function B(s,...e){return join(s,...e)}function Je(s){return B(s,"src")}function qe(s){return B(s,"dist")}function Qe(s){return B(s,"test")}function mt(s){return dirname(s)}function ie(...s){return resolve(...s)}function pe(s,e){return relative(s,e)}function yt(s){return isAbsolute(s)}function gt(s){return basename(s)}function St(s){return normalize(s)}var Cr=new Set(["EBUSY","EPERM","EACCES"]);function wt(s){return s instanceof Error&&"code"in s&&Cr.has(String(s.code))}function xt(s){return new Promise(e=>setTimeout(e,s))}async function ue(s,e=5,t=50){let r;for(let i=0;i<e;i++)try{return await s()}catch(o){if(r=o,!wt(o))throw o;await xt(t*(i+1));}throw r}v.createLogger({component:"fs-async"});async function S(s){try{return await access(s),!0}catch(e){if(typeof e=="object"&&e!==null&&"code"in e&&e.code==="ENOENT")return false;throw e}}async function fe(s){return (await readdir(s,{withFileTypes:true})).map(e=>({path:l(s,e.name),name:e.name,isDirectory:e.isDirectory(),isFile:e.isFile(),isSymbolicLink:e.isSymbolicLink()}))}async function oe(s){return readFile(s,"utf-8")}async function bt(s){return readFile(s)}async function de(s){try{if(!(await stat(s)).isDirectory())throw new Error(`Cannot create directory over file: ${s}`);return}catch(e){if(!dt(e,"ENOENT"))throw e}await mkdir(s,{recursive:true});}function At(s,e){return ue(()=>rename(s,e))}async function Pt(s,e,t={}){let r=await stat(s);return ue(()=>cp(s,e,{recursive:r.isDirectory(),...t}))}async function Ct(s,e){await writeFile(s,e,"utf8");}function Rt(s){return ue(()=>Nr(s))}async function Nr(s){await rm(s,{recursive:true,force:true});}var z={root:process.cwd()};function le(s){return {...s,path:me(s.path)}}function me(s){return s.replaceAll("\\","/")}var y=class{join(...e){return l(...e)}normalize(e){return St(e)}relative(e,t){return pe(e,t)}isAbsolute(e){return yt(e)}resolve(...e){return ie(...e)}dirname(e){return mt(e)}basename(e){return gt(e)}};function ye(s,e){let t=e?.overwrite??"overwrite";if(!s)return true;switch(t){case "skip":return false;case "error":throw new Error("File already exists");default:return true}}function Ft(s){return s.replaceAll("\\","/").replace(/^[A-Za-z]:/,"")}var b=class extends Error{operation;path;cause;constructor(e,t,r,i){super(e),this.operation=t,this.path=r,this.cause=i,this.name="FileSystemError";}};function Ot(s,e="filesystem"){if(!Ke(s))return new b("Unknown filesystem error",e,void 0,s);switch(s.code){case "ENOENT":return new b(`File not found: ${Xe(s.path)}`,e,s.path,s);case "EEXIST":return new b(`Path already exists: ${Xe(s.path)}`,e,s.path,s);case "EISDIR":return new b(`Cannot write file over directory: ${Xe(s.path)}`,e,s.path,s);default:return new b(s.message,e,s.path,s)}}function Xe(s){return s?Ft(s):"<unknown>"}var M=class{root;pathService;logger;constructor(e,t,r){this.root=t,this.pathService=r,this.logger=v.createLogger({component:e});}resolvePath(e){let t=me(e),r=this.pathService.normalize(t);return this.isPhysicalPath(r)?r:this.pathService.join(this.root,r.replace(/^[/\\]+/,""))}toVirtualPath(e){let t=this.pathService.relative(this.root,e);if(t.startsWith(".."))throw new Error(`Path outside filesystem root: ${e}`);return `/${me(t)}`}logAndThrow(e,t){let r=Ot(e,t);throw this.logger.error(r.message,{metadata:{operation:r.operation,path:r.path,cause:r.cause}}),r}isPhysicalPath(e){if(/^[a-zA-Z]:[\\/]/.test(e)||e.startsWith("\\\\"))return true;if(!this.pathService.isAbsolute(e))return false;let t=this.pathService.relative(this.root,e);return t===""||!t.startsWith("..")&&!this.pathService.isAbsolute(t)}};var g=class extends M{constructor(e=z){super("NodeAsyncFileSystemAdapter",e.root??z.root,new y);}async readJson(e){return R(await this.read(e))}async writeJson(e,t,r){await this.write(e,w(t,2),r);}readBuffer(e){return bt(this.resolvePath(e))}async read(e){try{return await oe(this.resolvePath(e))}catch(t){this.logAndThrow(t,"read");}}async write(e,t,r){let i=await this.exists(e);if(ye(i,r))try{let o=this.resolvePath(e),a=this.pathService.dirname(o);await de(a),await Ct(o,t);}catch(o){this.logAndThrow(o,"write");}}async copy(e,t){try{let r=this.resolvePath(e),i=this.resolvePath(t),o=this.pathService.dirname(i);await de(o),await Pt(r,i);}catch(r){this.logAndThrow(r,"copy");}}async createDirectory(e){try{await de(this.resolvePath(e));}catch(t){this.logAndThrow(t,"createDirectory");}}async exists(e){return S(this.resolvePath(e))}async remove(e){try{await Rt(this.resolvePath(e));}catch(t){this.logAndThrow(t,"remove");}}async readDirectory(e){let t=this.resolvePath(e);return (await fe(t)).map(i=>({...le(i),path:this.toVirtualPath(i.path)}))}async rename(e,t){try{await At(this.resolvePath(e),this.resolvePath(t));}catch(r){this.logAndThrow(r,"rename");}}};var W=class{createReaderForWorkspace(e){return new ee(new g({root:e}))}createWriterForWorkspace(e){return new te(new g({root:e}))}};var G=class{createReaderForWorkspace(e){return new re(new g({root:e}))}createWriterForWorkspace(e){return new se(new g({root:e}))}async assertArtifactStateExistsForWorkspace(e){let t=new g({root:e}),r="/.arch-platform/artifact-state.json";if(!await t.exists(r))throw new Error(`Compliance requires artifact state file "${r}" in workspace "${e}".`)}};function F(s){try{return lstatSync(s),!0}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return false;throw e}}function ge(s){try{return lstatSync(s).isDirectory()}catch{return false}}function et(s){return readFileSync(s,"utf-8")}function _t(s){return readFileSync(s)}function Se(s){return readFileSync(s,"utf8").replace(/\r\n/g,`
3
+ `)}function we(s){return readdirSync(s,{withFileTypes:true}).map(e=>({path:l(s,e.name),name:e.name,isDirectory:e.isDirectory(),isFile:e.isFile(),isSymbolicLink:e.isSymbolicLink()}))}function kt(s){let e=et(s);return R(e)}function xe(s){try{if(!statSync(s).isDirectory())throw new Error(`Cannot create directory over file: ${s}`);return}catch(e){if(e instanceof Error&&"code"in e&&e.code!=="ENOENT")throw e}mkdirSync(s,{recursive:true});}function Nt(s,e){writeFileSync(s,e);}function $t(s,e,t={}){if(F(e)){let r=statSync(e);console.debug("fs-sync: copyPathSync - destination state",{exists:true,isDirectory:r.isDirectory(),isFile:r.isFile()});}else console.log({exists:false});cpSync(s,e,t);}function Lt(s,e){renameSync(s,e);}function Ht(s){rmSync(s,{recursive:true,force:true});}var V=class extends M{constructor(e=z){super("NodeSyncFileSystemAdapter",e.root??z.root,new y);}exists(e){return F(this.resolvePath(e))}createDirectory(e){try{xe(this.resolvePath(e));}catch(t){this.logAndThrow(t,"createDirectory");}}remove(e){try{Ht(this.resolvePath(e));}catch(t){this.logAndThrow(t,"remove");}}read(e){try{return et(this.resolvePath(e))}catch(t){this.logAndThrow(t,"read");}}readBuffer(e){return _t(this.resolvePath(e))}readJson(e){return kt(this.resolvePath(e))}readDirectory(e){return we(this.resolvePath(e)).map(r=>({...le(r),path:this.toVirtualPath(r.path)}))}rename(e,t){try{Lt(this.resolvePath(e),this.resolvePath(t));}catch(r){this.logAndThrow(r,"rename");}}write(e,t,r){let i=this.exists(e);if(ye(i,r))try{let o=this.resolvePath(e),a=this.pathService.dirname(o);xe(a),Nt(o,t);}catch(o){this.logAndThrow(o,"write");}}copy(e,t){try{let r=this.resolvePath(e),i=this.resolvePath(t),o=this.pathService.dirname(i);xe(o),$t(r,i);}catch(r){this.logAndThrow(r,"copy");}}writeJson(e,t,r){this.write(e,w(t,2),r);}};var Y=class{hash(e){return createHash("sha256").update(e).digest("hex")}hashObject(e){return this.hash(w(e))}};var Mr=["package.json","tsconfig.json","tsconfig.build.json","tsup.config.ts"],U=class{hashService;constructor(e){this.hashService=e;}hashConfig(e){let t=[];for(let r of Mr){let i=l(e,r);if(!F(i))continue;let o=Se(i);t.push(r),t.push(o);}return this.hashService.hash(w(t,2))}};var Yr=[/^\/\*\*/,/^\/\/\/\s*<reference\b/,/@ts-(?:ignore|expect-error|nocheck|check)\b/];function Ur(s){return Yr.some(e=>e.test(s))}function It(s){let e=createScanner(ScriptTarget.Latest,false,LanguageVariant.Standard,s),t=[];for(;;){let i=e.scan();if(i===SyntaxKind.EndOfFileToken)break;if(i!==SyntaxKind.SingleLineCommentTrivia&&i!==SyntaxKind.MultiLineCommentTrivia)continue;let o=e.getTokenStart(),a=e.getTokenEnd(),n=s.slice(o,a);if(Ur(n))continue;let c=a,h=" ";if(s[c]==="\r"&&s[c+1]===`
4
+ `?(c+=2,h=""):(s[c]===`
5
+ `||s[c]==="\r")&&(c+=1,h=""),c===s.length&&h===" "){let p=s[o-1];if(p===`
6
+ `||p==="\r"){t.push({start:o-(p===`
7
+ `&&s[o-2]==="\r"?2:1),end:c,text:""});continue}}t.push({start:o,end:c,text:h});}let r=s;for(let i of t.reverse())r=r.slice(0,i.start)+i.text+r.slice(i.end);return r}var Kr=new Set(["node_modules","dist",".turbo",".git"]),Jr=new Set(["tsconfig.tsbuildinfo"]),qr=new Set([".ts",".tsx",".mts",".cts"]),K=class{hashService;constructor(e){this.hashService=e;}hashSource(e){let t=ie(B(e,"src")),r=[];this.walk(t,r);let i=r.sort().map(o=>{let a=Se(o),n=this.isTypeScriptFile(o)?It(a):a;return `${pe(t,o)}\0${n}\0`}).join("");return this.hashService.hash(i)}walk(e,t){let r=we(e);r.sort((i,o)=>i.name.localeCompare(o.name));for(let i of r){if(Kr.has(i.name)||Jr.has(i.name))continue;let o=l(e,i.name);ge(o)?this.walk(o,t):t.push(o);}}isTypeScriptFile(e){let t=e.replaceAll("\\","/"),r=t.slice(t.lastIndexOf(".")).toLowerCase();return qr.has(r)}};function ve(s){return typeof s=="object"&&s!==null&&!Array.isArray(s)}var J=class{filesystem;logger=v.createLogger({component:"BuildStateLoader"});constructor(e){this.filesystem=e;}load(){let e="/.arch-platform/state.json";if(!this.filesystem.exists(e))return this.logger.trace("state.file.missing",{metadata:{statePath:e}}),new Map;let t=this.filesystem.readJson(e);if(!ve(t))return this.logger.warn("state.invalid.root",{metadata:{statePath:e}}),new Map;let r=Object.entries(t),i=new Map;for(let[o,a]of r){if(!this.isBuildStateEntry(a)){this.logger.warn("INVALID_BUILD_STATE_ENTRY",{metadata:{packageName:o}});continue}i.set(o,a);}return this.logger.trace("BUILD_STATE_LOADED",{metadata:{packages:[...i.keys()]}}),i}isHashResult(e){return ve(e)?typeof e.hash=="string"&&typeof e.sourceHash=="string"&&typeof e.depsHash=="string"&&typeof e.configHash=="string"&&typeof e.schemaVersion=="number":false}isBuildStateEntry(e){return ve(e)?this.isHashResult(e.hash)&&Array.isArray(e.outputs)&&e.outputs.every(t=>typeof t=="string")&&typeof e.timestamp=="number"&&typeof e.schemaVersion=="number":false}};var Ee=class{created=new Set;updated=new Set;deleted=new Set;get isEmpty(){return this.created.size===0&&this.updated.size===0&&this.deleted.size===0}toSnapshot(){return {created:new Set(this.created),updated:new Set(this.updated),deleted:new Set(this.deleted)}}summary(){return {created:this.created.size,updated:this.updated.size,deleted:this.deleted.size}}};var q=class{state;filesystem;changes=new Ee;constructor(e,t){this.state=e,this.filesystem=t;}async write(){let e="/.arch-platform",t=`${e}/state.json`;await this.filesystem.createDirectory(e),await this.filesystem.write(t,w(this.state,2));}commit(e,t){let r=this.state.has(e.name);this.state.set(e.name,{hash:t,outputs:[...e.outputs],timestamp:Date.now(),schemaVersion:1}),r?this.changes.updated.add(e.name):this.changes.created.add(e.name);}prune(e){for(let t of this.state.keys())e.has(t)||(this.state.delete(t),this.changes.deleted.add(t));}getChanges(){return this.changes.toSnapshot()}};var jt=new Set([".git",".turbo","node_modules","dist","coverage"]);var be=class{logger=v.createLogger({component:"NodePackageProvider"});pathService=new y;async discover(e){let t=await this.findPackageRoots(l(e,"packages")),r=/^@[^/]+\//,o=(await Promise.all(t.map(a=>this.createPackageDescriptor(a)))).filter(a=>r.test(a.name));return this.resolveInternalDependencies(o)}async createPackageDescriptor(e){let t=l(e,"package.json"),[r,i,o]=await Promise.all([this.readPackageManifest(t),this.loadBoundaries(e),this.resolveLayout(e)]);return {name:r.name,rootPath:e,manifestPath:t,manifest:r,boundaries:i,internalDependencies:[],layout:o}}async findPackageRoots(e){let t=[],r=await fe(e);for(let i of r){let o=l(e,i.name);if(jt.has(i.name)||!ge(o))continue;let a=l(o,"package.json");if(await S(a)){t.push(o);continue}t.push(...await this.findPackageRoots(o));}return t}resolveInternalDependencies(e){let t=new Set(e.map(r=>r.name));return e.map(r=>({...r,internalDependencies:Object.keys(r.manifest.dependencies??{}).filter(i=>t.has(i)).sort()}))}async readPackageManifest(e){let t=await oe(e),r=R(t);if(!this.isPackageManifest(r))throw this.logger.error(Ue.INVALID_PACKAGE_MANIFEST,{source:{component:"NodePackageProvider",operation:"readPackageManifest"},metadata:{manifestPath:e,error:`Invalid manifest: ${e}`}}),new Error(`Invalid manifest: ${e}`);return r}isPackageManifest(e){return typeof e=="object"&&e!==null&&"name"in e&&typeof e.name=="string"}async loadBoundaries(e){let t=l(e,".boundaries.json");try{let r=await oe(t);return R(r)}catch(r){if(this.isNodeError(r)&&r.code==="ENOENT")return;throw this.logger.error(Ue.NODE_WORKSPACE_PROVIDER_BOUNDARIES_LOAD_FAILED,{source:{component:"NodePackageProvider",operation:"loadBoundaries"},metadata:{boundariesPath:t,error:r}}),r}}async resolveLayout(e){let t=this.pathService.join(e,"tsconfig.json"),[r,i,o,a]=await Promise.all([S(Je(e)),S(Qe(e)),S(qe(e)),S(t)]);return {sourceDirectory:Je(e),hasSourceDirectory:r,testsDirectory:Qe(e),hasTestsDirectory:i,distributionDirectory:qe(e),hasDistributionDirectory:o,tsconfigPath:t,hasTsconfig:a}}isNodeError(e){return typeof e=="object"&&e!==null&&"code"in e}};var Qr="pnpm-workspace.yaml",Q=class{packageProvider;pathService;constructor(e=new be,t=new y){this.packageProvider=e,this.pathService=t;}async discover(e){let t=this.findWorkspaceRoot(e),r=await this.packageProvider.discover(t);return {root:t,layout:await this.resolveWorkspaceLayout(t),packages:r}}findWorkspaceRoot(e){let t=this.pathService.resolve(e);for(;;){let r=this.pathService.join(t,Qr);if(F(r))return t;let i=this.pathService.dirname(t);if(i===t)throw new Error(`Unable to locate workspace root from "${e}"`);t=i;}}async resolveWorkspaceLayout(e){let t=this.pathService.join(e,"package.json"),r=this.pathService.join(e,"tsconfig.json"),i=this.pathService.join(e,"config"),o=this.pathService.join(i,"arch.manifest.json"),a=this.pathService.join(e,"scripts"),n=this.pathService.join(this.pathService.resolve(a),"git"),[c,h,p,u]=await Promise.all([S(t),S(r),S(o),S(n)]);return {packageJsonPath:t,tsconfigPath:r,archManifestPath:o,scriptPath:n,hasPackageManifest:c,hasTsconfig:h,hasArchManifest:p,hasScriptPath:u}}};var X=class{project(e){let{manifest:t}=e;return {name:e.name,root:e.rootPath,dependencies:Object.keys(t.dependencies??{}).sort(),buildDependencies:Object.keys(t.devDependencies??{}).filter(r=>r.startsWith("@arch-platform/")).sort(),outputs:this.resolveOutputs(t),artifactType:t.arch.artifactType,build:t.arch?.build}}projectAll(e){return e.map(t=>this.project(t))}resolveOutputs(e){if(e.arch?.build?.outputs?.length)return [...e.arch.build.outputs];let t=new Set;return e.main&&t.add(this.normalizeOutput(e.main)),e.types&&t.add(this.normalizeOutput(e.types)),[...t]}normalizeOutput(e){return e.replace(/^\.?\//,"")}};var Ae=class{store=new Map;set(e,t){this.store.set(e,t);}get(e){return this.store.get(e)}has(e){return this.store.has(e)}values(){return Array.from(this.store.values())}entries(){return Array.from(this.store.entries())}[Symbol.iterator](){return this.store[Symbol.iterator]()}};var Pe=class{build(e,t,r,i){let o=new Map;for(let a of r){if(a.status==="failed"||a.execution.reason==="failed")continue;let n=e.get(a.package),c=t.get(a.package),h=i.nodes.get(a.package);!n||!c||!h||h.startedAt===void 0||h.finishedAt===void 0||o.set(a.package,{hash:c.hash,dependencies:[...n.dependencies],artifactType:n.artifactType,status:this.resolveStatus(a),reason:this.resolveReason(c),startedAt:h.startedAt,finishedAt:h.finishedAt,schemaVersion:1});}return o}resolveStatus(e){switch(e.execution.reason){case "executed":return "built";case "restored":return "restored";case "cached":return "cached";default:throw new Error(`Cannot create ArtifactState for execution reason "${e.execution.reason}"`)}}resolveReason(e){switch(e.changeReason){case "none":return "none";case "first-build":return "first-build";case "source":return "source-changed";case "config":return "config-changed";case "dependency":return "dependency-changed";case "cache-version":return "cache-version-changed";case "output-integrity":return "output-integrity-failed";case "missing-output":return "missing-output";case "dependency-failed":throw new Error("Cannot create ArtifactState for a dependency-failed change")}}};function Bt(s,e){let t=new WeakSet,r=(i,o)=>{if(o instanceof Error)return {name:o.name,message:o.message,stack:o.stack};if(typeof o=="bigint")return o.toString();if(typeof o>"u")return "[undefined]";if(typeof o=="symbol")return o.toString();if(o instanceof Map)return Object.fromEntries(o);if(o instanceof Set)return [...o];if(typeof o=="object"&&o!==null){if(t.has(o))return "[Circular]";t.add(o);}return o};try{return JSON.stringify(s,r,e)}catch{return "[unserializable]"}}var A={reset:"\x1B[0m",brightCyan:"\x1B[96m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightRed:"\x1B[91m"},zt={trace:{write:console.debug,symbol:`${A.brightCyan}\xB7 ${A.reset}`},info:{write:console.log,symbol:""},success:{write:console.log,symbol:`${A.brightGreen}\u2705 ${A.reset}`},warn:{write:console.warn,symbol:`${A.brightYellow}\u26A0 ${A.reset}`},error:{write:console.error,symbol:`${A.brightRed}\u274C ${A.reset}`}};var Ce=/(token|secret|password|api[-_]?key)/i;function Mt(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,Ce.test(e)?"***":t]))}function Wt(s){if(!s)return;let e=Object.entries(s).map(([t,r])=>Ce.test(t)?[t,"***"]:t==="env"&&r!==null&&typeof r=="object"?[t,Mt(r)]:[t,r]);return Object.fromEntries(e)}var Gt=process.env.ARCH_BUILD_TRACE==="1",Vt=process.env.ARCH_BUILD_TRACE_CACHE==="1",Yt=process.env.ARCH_BUILD_TRACE_HASH==="1";var Xr="[arch]",f={reset:"\x1B[0m",dim:"\x1B[2m",gray:"\x1B[90m",green:"\x1B[32m",yellow:"\x1B[33m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightCyan:"\x1B[96m"};function O(s,e){return `${s}${e}${f.reset}`}function Zr(s){return s.replace(/"([^"]+)":/g,`${f.cyan}"$1"${f.reset}:`).replace(/"([^"]*)"/g,`${f.green}"$1"${f.reset}`).replace(/\b(true|false)\b/g,`${f.yellow}$1${f.reset}`).replace(/\bnull\b/g,`${f.magenta}null${f.reset}`).replace(/(?<!["\w])(-?\d+(?:\.\d+)?)(?!["\w])/g,`${f.brightYellow}$1${f.reset}`)}function es(s){if(Gt)return true;switch(s){case "cache":return Vt;case "hash":return Yt;default:return false}}function ae(s,e,t={}){let{prefix:r=true,metadata:i}=t,o=new Date().toISOString(),a=i?Wt(i):void 0,n=r?`${O(f.dim,Xr)} `:"",c=(()=>{switch(s){case "trace":return O(f.brightCyan,e);case "info":return O(f.white,e);case "success":return O(f.brightGreen,e);case "warn":return O(f.brightYellow,e);case "error":return O(f.brightRed,e);default:return e}})(),h=O(f.gray,`[${o}]`),p=a?`${h} ${n}${c}
8
+ ${Zr(Bt(a,2))}`:`${h} ${n}${c}`,{write:u,symbol:x}=zt[s];u(`${x}${p}`);}var m={trace(s,e={}){es(e.category)&&ae("trace",s,e);},info(s,e){ae("info",s,e);},success(s,e){ae("success",s,e);},warn(s,e){ae("warn",s,e);},error(s,e){ae("error",s,e);},newline(){process.stdout.write(`
9
+ `);}};function Ut(s){switch(s?.builder??"tsc"){case "script":return [{name:"build",command:"pnpm",args:["run","build"]}];case "tsup":{let t=["exec","tsup"];return s?.tsconfig&&t.push("--tsconfig",s.tsconfig),[{name:"bundle",command:"pnpm",args:t}]}case "tsc-declaration":return [{name:"types",command:"pnpm",args:["exec","tsc","--build","tsconfig.build.json"]}];case "custom":if(!s?.command)throw new Error("Custom build requires command");return [{name:"custom",command:s.command,args:s.args??[]}];default:return [{name:"compile",command:"pnpm",args:["exec","tsc","--build","tsconfig.build.json"]}]}}var Re=class{ctx;constructor(e){this.ctx=e;}async execute(e,t){let r=Ut(e.build);for(let i of r){let o=await this.ctx.runner(i.command,i.args,{cwd:e.root});if(o.exitCode!==0)return m.error("step failed",{metadata:{package:e.name,step:i.name,exitCode:o.exitCode,stdout:o.stdout,stderr:o.stderr}}),{package:e.name,status:"failed",changeReason:t.changeReason,execution:{reason:"failed"}}}return {package:e.name,status:"success",changeReason:t.changeReason,execution:{reason:"executed"}}}};var Fe=class{create(e){return new Re({runner:e.runner})}};function Kt(s){let e=ts(s);return rs(e),ss(e),e}function ts(s){let e=new Map,t=new Set(s.map(i=>i.name));for(let i of s)e.set(i.name,{name:i.name,root:i.root,dependencies:r(i,t),dependents:[],outputs:[...i.outputs],artifactType:i.artifactType,build:i.build});function r(i,o){return [...i.dependencies,...i.buildDependencies].filter(a=>o.has(a))}return e}function rs(s){for(let e of s.values())for(let t of e.dependencies){let r=s.get(t);if(!r)throw new Error(`Graph invariant violated: dependency "${t}" does not exist.`);r.dependents.push(e.name);}}function ss(s){for(let e of s.values())Object.freeze(e.dependencies),Object.freeze(e.dependents),Object.freeze(e.outputs),Object.freeze(e);}var Oe=class{graph;constructor(e){this.graph=e;}getNode(e){let t=this.graph.get(e);if(!t)throw new Error(`Missing node ${e}`);return t}getDependencies(e){return this.getNode(e).dependencies}getDependents(e){return this.getNode(e).dependents}entries(){return this.graph.entries()}getDependencyClosure(e){let t=new Set;return this.visitDependencies(e,t),t}getImpactClosure(e){let t=new Set;for(let r of e)this.visitDependents(r,t);return t}resolveExecutionScope(e,t){let r=this.getImpactClosure(t),i=this.getDependencyClosure(e),o=new Set;for(let a of i)r.has(a)&&o.add(a);return o.add(e),o}visitDependencies(e,t){if(!t.has(e)){t.add(e);for(let r of this.getDependencies(e))this.visitDependencies(r,t);}}visitDependents(e,t){if(!t.has(e)){t.add(e);for(let r of this.getDependents(e))this.visitDependents(r,t);}}};var Te=class extends Error{details;constructor(e,t){super(`[Hash] ${e}`),this.details=t,this.name="HashConsistencyError";}};var De=class{hashService;constructor(e){this.hashService=e;}validate({input:e,result:t}){let r=this.hashService.hashObject(e);if(r!==t.hash)throw new Te(`Hash mismatch for ${e.nodeName}`,{expected:{hash:r},actual:{hash:t.hash}})}};function is(s){return [...s].sort().join("|")}var _e=class{configHashService;sourceHashService;hashService;validator;constructor(e,t,r,i){this.configHashService=e,this.sourceHashService=t,this.hashService=r,this.validator=i;}hash(e,t){let r=this.sourceHashService.hashSource(e.root),i=this.configHashService.hashConfig(e.root),o=this.hashService.hash(is(t.dependencyHashes)),a={nodeName:e.name,sourceHash:r,configHash:i,depsHash:o,schemaVersion:1},c={hash:this.hashService.hashObject(a),sourceHash:r,configHash:i,depsHash:o,schemaVersion:1};return this.validator.validate({input:a,result:c}),m.trace("build.hash.calculated",{category:"hash",metadata:{packageName:e.name,hash:c.hash}}),c}};var ke=class{query;constructor(e){this.query=e;}resolve(e){let t=this.query.getNode(e);return {id:e,inputs:{packages:t.dependencies,files:[],env:void 0},outputs:{files:[]},cache:{strategy:"content-hash",key:void 0},run:{executor:"custom",command:void 0}}}};var Ne=class{state;outputValidator;artifactCache;artifactProvider;constructor(e,t,r,i){this.state=e,this.outputValidator=t,this.artifactCache=r,this.artifactProvider=i;}async evaluate(e,t,r,i){let o=this.state.get(e);if(!o){let p=this.artifactProvider.create(e,i),u=await this.artifactCache.exists(p);return u?(m.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"restore",changeReason:"first-build",available:u}}),{packageName:e,decision:"restore",changeReason:"first-build",available:u}):(m.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"miss",changeReason:"first-build",available:u}}),{packageName:e,decision:"miss",changeReason:"first-build",available:u})}if(o.schemaVersion!==1)return this.stale(e,"cache-version");if(o.hash.sourceHash!==i.sourceHash)return this.stale(e,"source");if(o.hash.configHash!==i.configHash)return this.stale(e,"config");if(o.hash.depsHash!==i.depsHash)return this.stale(e,"dependency");let a=this.artifactProvider.create(e,i),n=await this.outputValidator.exists(t,r);if(n&&await this.artifactCache.verifyOutputs(a,t)){let p=await this.artifactCache.exists(a),u=!p;return u&&(await this.artifactCache.save(a,t,r),p=await this.artifactCache.exists(a)),m.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"hit",changeReason:"none",available:p,cacheRepaired:u}}),{packageName:e,decision:"hit",changeReason:"none",available:p}}let c=n?"output-integrity":"missing-output",h=await this.artifactCache.exists(a);return h?(m.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"restore",changeReason:c,available:h}}),{packageName:e,decision:"restore",changeReason:c,available:h}):(m.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"invalid",changeReason:c,available:h}}),{packageName:e,decision:"invalid",changeReason:c,available:h})}stale(e,t){return {packageName:e,decision:"stale",changeReason:t,available:true}}};var $e=class{graph;executor;plan;writer;artifactCache;outputValidator;artifactProvider;artifactOutputPreparer;constructor(e,t,r,i,o,a,n,c){this.graph=e,this.executor=t,this.plan=r,this.writer=i,this.artifactCache=o,this.outputValidator=a,this.artifactProvider=n,this.artifactOutputPreparer=c;}async run(e){let t=this.requireNode(e),r=this.requirePlan(e);return this.executeBuildAction(t,r)}requireNode(e){let t=this.graph.get(e);if(!t)throw new Error(`Missing node ${e}`);return t}requirePlan(e){let t=this.plan.get(e);if(!t)throw new Error(`Missing plan ${e}`);return t}createResult(e,t,r){return {package:e.package,status:t,changeReason:e.changeReason,execution:{reason:r}}}async executeAndCache(e,t){try{await this.artifactOutputPreparer.prepare(e.root,e.outputs);let r=await this.executor.execute(e,t);if(r.status!=="success")return r;if(e.outputs.length>0&&!await this.outputValidator.exists(e.root,e.outputs))throw new Error(["Build completed but declared outputs are missing.",`package=${e.name}`,`outputs=${e.outputs.join(", ")}`].join(" "));let i=this.artifactProvider.create(e.name,t.hash);return await this.artifactCache.save(i,e.root,e.outputs),this.writer.commit(e,t.hash),r}catch(r){throw m.error("[build] executeAndCache failed:",{metadata:{package:e.name,root:e.root,error:r}}),r}}async restore(e,t){let r=this.artifactProvider.create(e.name,t.hash);return await this.artifactCache.restore(r,e.root)?(this.writer.commit(e,t.hash),this.createResult(t,"skipped","restored")):this.executeAndCache(e,t)}async executeBuildAction(e,t){switch(t.buildAction){case "restore":return this.restore(e,t);case "skip":return this.createResult(t,"skipped","cached");case "execute":return this.executeAndCache(e,t)}}};var Le=class{graph;hasher;constructor(e,t){this.graph=e,this.hasher=t;}build(){let e=new Map,t=new Set,r=i=>{let o=e.get(i);if(o)return o;if(t.has(i))throw new Error(`Cycle detected at ${i}`);t.add(i);let a=this.graph.get(i);if(!a)throw new Error(`Missing node ${i}`);let n=[];for(let h of a.dependencies)n.push(r(h).hash);let c=this.hasher.hash(a,{dependencyHashes:n});return t.delete(i),e.set(i,c),c};for(let i of this.graph.keys())r(i);return e}};var qt={STATE_CHANGED:"build.service.state.changed"};var He=class{evaluator;constructor(e){this.evaluator=e;}async createPlan(e,t){let r=new Ae;for(let[i,o]of e){let a=t.get(i);if(!a)throw new Error(`[ChangePlanner] Missing hash for "${i}"`);let n=await this.evaluator.evaluate(o.name,o.root,o.outputs,a);r.set(i,{package:i,buildAction:this.resolveBuildAction(n.decision,n.available),cache:{decision:n.decision},changeReason:n.changeReason,hash:a});}return r}resolveBuildAction(e,t){if(t&&e!=="hit")return "restore";switch(e){case "restore":return "restore";case "hit":return "skip";case "miss":case "stale":case "invalid":return "execute"}}};var Ie=class{query;contractResolver;constructor(e,t){this.query=e,this.contractResolver=t;}compile(e){let{plan:t,scope:r}=e,i=new Map;for(let o of r){let a=t.get(o);if(!a)continue;let n=this.resolveDependencies(o,r),c=this.contractResolver.resolve(o);i.set(o,this.createNode(o,n,a,c));}for(let o of i.values())for(let a of o.dependencies){let n=i.get(a);n&&n.dependents.push(o.name);}return {nodes:i}}createNode(e,t,r,i){return {name:e,dependencies:t,dependents:[],buildAction:r.buildAction,changeReason:r.changeReason,contract:i}}resolveDependencies(e,t){return this.query.getDependencies(e).filter(r=>t.has(r))}};var je=class{plan;query;constructor(e,t){this.plan=e,this.query=t;}resolve(e){let t=this.getAffectedNodes();switch(e?.mode){case "workspace":return t;case "package":return this.query.resolveExecutionScope(e.packageName,t);default:return t}}getAffectedNodes(){return new Set([...this.plan.entries()].map(([e])=>e))}};function Qt(s){let e=new Map,t=new Map,r=new Map;for(let[i]of s.nodes)e.set(i,{state:"pending"}),t.set(i,"pending");return {nodes:e,nodeStates:t,triggers:r}}function P(s,e,t,r){let i=s.nodes.get(e);if(!i)throw new Error(`Execution node not found: ${e}`);let o=Date.now(),a={...i,state:t};t==="running"&&(a.startedAt=o),(t==="success"||t==="failed"||t==="cached"||t==="skipped")&&(a.finishedAt=o,a.startedAt!==void 0&&(a.duration=a.finishedAt-a.startedAt)),r&&(a.error=r),s.nodes.set(e,a),s.nodeStates.set(e,t);}var Be=class{runner;concurrency;constructor(e,t){this.runner=e,this.concurrency=t;}async run(e,t){let r=[],i=new Map,o=this.initializeReadyQueue(e,t);for(;o.length>0||i.size>0;)this.dispatch(e,t,o,i,r),i.size>0&&await Promise.race(i.values());return r}initializeReadyQueue(e,t){let r=[];for(let i of e.nodes.values())i.dependencies.length>0||(P(t,i.name,"ready"),this.setTrigger(t,i),r.push(i.name));return r}dispatch(e,t,r,i,o){for(;i.size<this.concurrency&&r.length>0;){let a=r.shift();if(!a)return;let n=this.execute(a,e,t,r,o);i.set(a,n.finally(()=>{i.delete(a);}));}}async execute(e,t,r,i,o){try{P(r,e,"running");let a=await this.runner.run(e),n=r.triggers.get(e);if(n&&(a.execution.triggeredBy=n),o.push(a),a.status==="failed"){P(r,e,"failed");let h=t.nodes.get(e);h&&this.notifyDependentsFailed(h,t,r,o);return}P(r,e,"success");let c=t.nodes.get(e);c&&this.notifyDependentsReady(c,t,r,i);}catch(a){let n=a instanceof Error?a.message:String(a);P(r,e,"failed",n),m.error("[execution-plan-scheduler] execution failed",{metadata:{package:e,error:n}}),o.push({package:e,status:"failed",changeReason:"none",execution:{reason:"failed"}});let c=t.nodes.get(e);c&&this.notifyDependentsFailed(c,t,r,o);}}notifyDependentsReady(e,t,r,i){for(let o of e.dependents){let a=t.nodes.get(o);if(!a)continue;let n=r.nodes.get(o);!n||n.state!=="pending"||!a.dependencies.every(h=>r.nodes.get(h)?.state==="success")||(P(r,o,"ready"),this.setDependencyTrigger(r,a,e),i.push(o));}}notifyDependentsFailed(e,t,r,i){let o=[...e.dependents];for(;o.length>0;){let a=o.shift(),n=r.nodes.get(a);if(!n||n.state!=="pending")continue;P(r,a,"skipped",`Dependency ${e.name} failed`),i.push({package:a,status:"skipped",changeReason:"dependency-failed",execution:{reason:"failed"}});let c=t.nodes.get(a);c&&o.push(...c.dependents);}}setTrigger(e,t){let r=this.toExecutionTriggerReason(t.changeReason);r&&e.triggers.set(t.name,{package:t.name,reason:r});}setDependencyTrigger(e,t,r){e.triggers.set(t.name,{package:r.name,reason:"dependency-ready"});}toExecutionTriggerReason(e){switch(e){case "source":return "source-changed";case "config":return "config-changed";case "dependency":return "dependency-changed";case "first-build":return "first-build";case "cache-version":return "cache-version-changed";case "output-integrity":return "output-integrity-failed";case "missing-output":return "missing-output";case "dependency-failed":case "none":return}}};var ze=class{context;constructor(e){this.context=e;}async run(e){let{graph:t,query:r,dagHasher:i,contractResolver:o,state:a,executor:n,artifactCache:c,artifactProvider:h,artifactOutputPreparer:p,fsOutputValidator:u,stateWriter:x,artifactStateReader:nr,artifactStateWriter:cr,artifactStateHistoryReader:hr,artifactStateHistoryWriter:pr,artifactStateBuilder:ur}=this.context,fr=new Le(t,i).build(),dr=new Ne(a,u,c,h),ce=await new He(dr).createPlan(t,fr),rt=new je(ce,r).resolve(e.scope);if(rt.size===0)return this.summarize([]);let st=new Ie(r,o).compile({plan:ce,scope:rt}),lr=new $e(t,n,ce,x,c,u,h,p),mr=new Be(lr,e.concurrency??4),it=Qt(st),Ge=await mr.run(st,it);if(Ge.every(E=>E.status!=="failed")){x.prune(new Set(t.keys()));let E=x.getChanges();(E.created.size>0||E.updated.size>0||E.deleted.size>0)&&(m.info(qt.STATE_CHANGED,{metadata:{created:E.created.size,updated:E.updated.size,deleted:E.deleted.size}}),await x.write());let Ve=ur.build(t,ce,Ge,it);if(Ve.size>0){let ot=await nr.read(),at=this.buildArtifactStateHistory(ot,Ve);if(at.size>0){let gr=await hr.read(),Sr=this.mergeArtifactStateHistory(gr,at);await pr.write(Sr);}let yr=this.mergeArtifactStates(ot,Ve);await cr.write(yr);}}return this.summarize(Ge)}mergeArtifactStates(e,t){let r=new Map(e);for(let[i,o]of t)r.set(i,o);return r}mergeArtifactStateHistory(e,t){let r=new Map(e);for(let[i,o]of t){let a=r.get(i);if(!a){r.set(i,o);continue}r.set(i,{artifact:i,changes:[...a.changes,...o.changes]});}return r}summarize(e){return {results:e,executed:e.filter(t=>t.execution.reason==="executed").length,restored:e.filter(t=>t.execution.reason==="restored").length,cached:e.filter(t=>t.execution.reason==="cached").length,failed:e.filter(t=>t.status==="failed").length}}buildArtifactStateHistory(e,t){let r=new Map;for(let[i,o]of t){let a=e.get(i);if(!a){r.set(i,{artifact:i,changes:[{previousHash:null,currentHash:o.hash.hash,reason:o.reason,timestamp:o.finishedAt}]});continue}a.hash.hash!==o.hash.hash&&r.set(i,{artifact:i,changes:[{previousHash:a.hash.hash,currentHash:o.hash.hash,reason:o.reason,timestamp:o.finishedAt}]});}return r}};var Me=class{runner;fsAsync=new g;workspaceProvider=new Q;artifactStateProvider=new G;artifactStateHistoryProvider=new W;workspacePackageProjector=new X;pathService=new y;hashService=new Y;constructor(e){this.runner=e;}async createBuildService(e){let t=await this.workspaceProvider.discover(e),r=this.workspacePackageProjector.projectAll(t.packages),i=Kt(r),o=this.createBuildStateLoader(t.root),a=this.createArtifactStateReader(t.root),n=this.createGraphQuery(i);return new ze({graph:i,query:n,dagHasher:this.createDagHasher(),contractResolver:this.createExecutionContractResolver(n),state:o,executor:this.createExecutor(),artifactCache:this.createArtifactCache(t.root),artifactProvider:this.createArtifactProvider(),artifactOutputPreparer:this.createArtifactOutputPreparer(),workspaceRoot:t.root,fsOutputValidator:this.createFileSystemOutputValidator(),stateWriter:this.createStateWriter(o,t.root),artifactStateReader:a,artifactStateWriter:this.createArtifactStateWriter(t.root),artifactStateBuilder:this.createArtifactStateBuilder(),artifactStateHistoryReader:this.createArtifactStateHistoryReader(t.root),artifactStateHistoryWriter:this.createArtifactStateHistoryWriter(t.root)})}createArtifactCache(e){let t=new H(this.pathService.join(e,".arch-platform-cache","artifacts"),this.pathService),r=new N(this.fsAsync,this.pathService),i=new k(this.fsAsync,this.pathService,this.hashService),o=new _;return new L(t,r,this.fsAsync,this.pathService,i,o)}createArtifactOutputPreparer(){return new I(this.fsAsync,this.pathService)}createExecutor(){return new Fe().create({runner:this.runner})}createGraphQuery(e){return new Oe(e)}createExecutionContractResolver(e){return new ke(e)}createBuildStateLoader(e){let t=new V({root:e});return new J(t).load()}createStateWriter(e,t){let r=new g({root:t});return new q(e,r)}createArtifactStateReader(e){return this.artifactStateProvider.createReaderForWorkspace(e)}createArtifactStateWriter(e){return this.artifactStateProvider.createWriterForWorkspace(e)}createArtifactStateHistoryReader(e){return this.artifactStateHistoryProvider.createReaderForWorkspace(e)}createArtifactStateHistoryWriter(e){return this.artifactStateHistoryProvider.createWriterForWorkspace(e)}createArtifactProvider(){return new $}createArtifactStateBuilder(){return new Pe}createFileSystemOutputValidator(){return new j(this.fsAsync,this.pathService)}createDagHasher(){let e=new U(this.hashService),t=new K(this.hashService),r=new De(this.hashService);return new _e(e,t,this.hashService,r)}};var ne=class{fromDirectory;compositionRoot;constructor(e,t){this.fromDirectory=e,this.compositionRoot=new Me(t);}async create(){return this.compositionRoot.createBuildService(this.fromDirectory)}};var Xt=async(s,e,t)=>{try{let r=await execa(s,e,{cwd:t.cwd,encoding:"utf8"});return {exitCode:r.exitCode??0,stdout:r.stdout??"",stderr:r.stderr??""}}catch(r){let i=r;return {exitCode:i.exitCode??1,stdout:i.stdout??"",stderr:i.stderr??String(r)}}};function as(s){return typeof s=="object"&&s!==null}function Zt(s,e){let t=new WeakSet;try{return JSON.stringify(s,(r,i)=>{if(as(i)){if(t.has(i))return "[Circular]";t.add(i);}return i},e)}catch{return "[unserializable]"}}var ns=/(token|secret|password|api[-_]?key)/i;function er(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,ns.test(e)?"***":t]))}var cs=/(token|secret|password|api[-_]?key)/i;function tr(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>cs.test(e)?[e,"***"]:e==="env"&&t&&typeof t=="object"?[e,er(t)]:[e,t]))}var C={reset:"\x1B[0m",brightCyan:"\x1B[96m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightRed:"\x1B[91m"},rr={trace:{write:console.debug,symbol:`${C.brightCyan}\xB7 ${C.reset}`},info:{write:console.log,symbol:""},success:{write:console.log,symbol:`${C.brightGreen}\u2705 ${C.reset}`},warn:{write:console.warn,symbol:`${C.brightYellow}\u26A0 ${C.reset}`},error:{write:console.error,symbol:`${C.brightRed}\u274C ${C.reset}`}};var hs="[arch]",d={reset:"\x1B[0m",dim:"\x1B[2m",gray:"\x1B[90m",green:"\x1B[32m",yellow:"\x1B[33m",magenta:"\x1B[35m",cyan:"\x1B[36m",white:"\x1B[37m",brightRed:"\x1B[91m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightCyan:"\x1B[96m"};function T(s,e){return `${s}${e}${d.reset}`}function ps(s){return s.replace(/"([^"]+)":/g,`${d.cyan}"$1"${d.reset}:`).replace(/"([^"]*)"/g,`${d.green}"$1"${d.reset}`).replace(/\b(true|false)\b/g,`${d.yellow}$1${d.reset}`).replace(/\bnull\b/g,`${d.magenta}null${d.reset}`).replace(/(?<!["\w])(-?\d+(?:\.\d+)?)(?!["\w])/g,`${d.brightYellow}$1${d.reset}`)}function We(s,e,t={}){let{prefix:r=true,metadata:i}=t,o=new Date().toISOString(),a=i?tr(i):void 0,n=r?`${T(d.dim,hs)} `:"",c=(()=>{switch(s){case "trace":return T(d.brightCyan,e);case "info":return T(d.white,e);case "success":return T(d.brightGreen,e);case "warn":return T(d.brightYellow,e);case "error":return T(d.brightRed,e);default:return e}})(),h=T(d.gray,`[${o}]`),p=a?`${h} ${n}${c}
10
+ ${ps(Zt(a,2))}`:`${h} ${n}${c}`,{write:u,symbol:x}=rr[s];u(`${x}${p}`);}var D={info(s,e){We("info",s,e);},success(s,e){We("success",s,e);},warn(s,e){We("warn",s,e);},error(s,e){We("error",s,e);},newline(){process.stdout.write(`
11
+ `);}};function sr(s){return s.packageName?{mode:"package",packageName:s.packageName}:{mode:"workspace"}}function ir(s){s.command("build").option("--package <packageName>","Build specific package").action(async e=>{process.exitCode=await us({packageName:e.package});});}async function us(s){let r=await(await new ne(process.cwd(),Xt).create()).run({scope:sr(s)}),i=r.failed===0;return D.newline(),D.info("ARCH Build"),D.info("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"),D[i?"success":"error"](i?"Status: BUILD COMPLETED":"Status: BUILD FAILED"),D.info(`Executed: ${r.executed} \xB7 Restored: ${r.restored} \xB7 Cached: ${r.cached} \xB7 Failed: ${r.failed}`),D.newline(),i?0:1}function or(s){ir(s);}function ar(){let s=cac("arch-cli");return or(s),s.help(),s}ar().parse();
package/package.json CHANGED
@@ -1,6 +1,42 @@
1
1
  {
2
2
  "name": "@arch-platform/distribution",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.2",
4
+ "description": "ARCH Platform CLI for building workspace packages with artifact caching and restoration.",
5
+ "author": "neo1sre",
6
+ "license": "SEE LICENSE IN LICENSE",
7
+ "private": false,
8
+ "type": "module",
9
+ "sideEffects": false,
10
+ "files": [
11
+ "dist",
12
+ "bin",
13
+ "README.md",
14
+ "LICENSE"
15
+ ],
16
+ "arch": {
17
+ "artifactType": "runtime",
18
+ "build": {
19
+ "builder": "tsup",
20
+ "outputs": [
21
+ "dist"
22
+ ]
23
+ },
24
+ "kind": "app"
25
+ },
26
+ "bin": {
27
+ "arch-cli": "./bin/arch-cli.js"
28
+ },
29
+ "dependencies": {
30
+ "cac": "6.7.14",
31
+ "execa": "9.6.1",
32
+ "typescript": "5.9.3"
33
+ },
34
+ "devDependencies": {
35
+ "@arch-platform/build-core": "0.1.0"
36
+ },
37
+ "scripts": {
38
+ "build": "tsup",
39
+ "clean": "arch clean --package @arch-platform/distribution",
40
+ "typecheck": "arch typecheck --package @arch-platform/distribution"
41
+ }
6
42
  }