@arch-platform/distribution 0.0.0-stage → 0.1.1
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 +21 -0
- package/README.md +111 -2
- package/bin/arch-cli.js +3 -0
- package/dist/bin-cli.js +11 -0
- package/package.json +39 -3
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
|
-
#
|
|
1
|
+
# @arch-platform/distribution
|
|
2
2
|
|
|
3
|
-
|
|
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`.
|
package/bin/arch-cli.js
ADDED
package/dist/bin-cli.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import {join,normalize,relative,isAbsolute,resolve,dirname,basename}from'path';import'url';import {cac}from'cac';import {readFile,stat,mkdir,writeFile,access,readdir,rename,cp,rm}from'fs/promises';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 Er=(s,e,t)=>()=>{if(t)throw t[0];try{return s&&(e=s(s=0)),e}catch(r){throw t=[r],r}};var a=Er(()=>{"use strict";});a();a();a();a();a();a();a();a();a();a();var I=class{compare(e,t){let r=new Map(e.map(f=>[f.path,f])),o=new Map(t.map(f=>[f.path,f])),i=[],n=[],p=[];for(let[f,d]of o){let l=r.get(f);if(!l){i.push(f);continue}(l.sizeInBytes!==d.sizeInBytes||l.integrity!==d.integrity)&&n.push(f);}for(let f of r.keys())o.has(f)||p.push(f);i.sort(),n.sort(),p.sort();let u={added:i,modified:n,deleted:p};return {isIdentical:i.length===0&&n.length===0&&p.length===0,diff:u}}};a();var H=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 o of t){let i=this.pathService.join(e,o);if(!await this.filesystem.exists(i))throw new Error(`Cannot fingerprint missing artifact output: ${o}`);if(await this.getEntryKind(i)==="file"){let f=await this.filesystem.readBuffer(i);r.push({path:o,sizeInBytes:f.byteLength,integrity:`sha256:${this.hashService.hash(f)}`});continue}let p=await this.fingerprintDirectory(i),u=p.reduce((f,d)=>f+d.sizeInBytes,0);r.push({path:o,sizeInBytes:u,integrity:`sha256:${this.hashService.hashObject({kind:"directory",entries:p})}`});}return r}async getEntryKind(e){let t=this.pathService.dirname(e),r=this.pathService.basename(e),i=(await this.filesystem.readDirectory(t)).find(n=>n.name===r);if(!i)throw new Error(`Cannot determine artifact output type: ${e}`);if(i.isSymbolicLink)throw new Error(`Symbolic links are not supported as artifact outputs: ${e}`);if(i.isFile)return "file";if(i.isDirectory)return "directory";throw new Error(`Unsupported artifact output type: ${e}`)}async fingerprintDirectory(e){let t=await this.filesystem.readDirectory(e),r=[];for(let o of t){if(o.isSymbolicLink)throw new Error(`Symbolic links are not supported in artifact outputs: ${o.path}`);let i=this.pathService.join(e,o.name),n=this.pathService.relative(e,i).replace(/\\/g,"/");if(o.isDirectory){r.push({path:n,kind:"directory",sizeInBytes:0});let u=await this.fingerprintDirectory(i);for(let f of u)r.push({...f,path:`${n}/${f.path}`});continue}if(!o.isFile)throw new Error(`Unsupported artifact entry type: ${i}`);let p=await this.filesystem.readBuffer(i);r.push({path:n,kind:"file",sizeInBytes:p.byteLength,integrity:`sha256:${this.hashService.hash(p)}`});}return r.sort((o,i)=>o.path.localeCompare(i.path))}};a();var j=class{filesystem;pathService;constructor(e,t){this.filesystem=e,this.pathService=t;}async publish(e,t,r){let o=false,i=r.temporary("tmp");try{await this.filesystem.remove(i.root),await this.filesystem.createDirectory(i.root);for(let n of t.outputs){let p=this.pathService.join(e,n),u=i.output(n);await this.filesystem.copy(p,u);}await this.filesystem.writeJson(i.manifest(),t),await this.filesystem.remove(r.root),await this.filesystem.rename(i.root,r.root),o=!0;}finally{o||await this.filesystem.remove(i.root);}}};a();var B=class{create(e,t){return {packageName:e,id:br(t)}}};function br(s){return `${s.sourceHash}-${s.configHash}-${s.depsHash}`}a();a();a();function E(s,e=2){let t=new WeakSet,r=(o,i)=>{if(i instanceof Error)return {name:i.name,message:i.message,stack:i.stack};if(typeof i=="bigint")return i.toString();if(!(typeof i>"u")){if(typeof i=="symbol")return i.toString();if(i instanceof Map)return Object.fromEntries(i);if(i instanceof Set)return [...i];if(typeof i=="object"&&i!==null){if(t.has(i))return "[Circular]";t.add(i);}return i}};try{return JSON.stringify(s,r,e)}catch{return "[unserializable]"}}a();var ut={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 "}};a();a();a();var fe=/(token|secret|password|api[-_]?key)/i;function ft(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,fe.test(e)?"***":t]))}function dt(s){if(!s)return;let e=Object.entries(s).map(([t,r])=>fe.test(t)?[t,"***"]:t==="env"&&r!==null&&typeof r=="object"?[t,ft(r)]:[t,r]);return Object.fromEntries(e)}a();["1","true","yes","on"].includes((process.env.ARCH_TRACE??"").toLowerCase());process.env.ARCH_TRACE_COMPONENT;function lt(){return ["1","true","yes","on"].includes((process.env.ARCH_TRACE??"").toLowerCase())}function mt(){return process.env.ARCH_TRACE_COMPONENT}var Je=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(!lt())return;let b=mt();if(b&&r.source?.component!==b)return}let{source:o,metadata:i}=r,n=new Date().toISOString(),p=o||i?dt({...o?{source:o}:{},...i?{metadata:i}:{}}):void 0,u=`${t}`,f=p?`[${n}] ${u}
|
|
2
|
+
${E(p,2)}`:`[${n}] ${u}`,{write:d,symbol:l}=ut[e];d(`${l}${f}`);}mergeOptions(e,t){return {...t,source:{...e,...t?.source}}}},A=new Je;var z=class{layoutFactory;publisher;filesystem;pathService;fingerprinter;comparator;logger=A.createLogger({component:"FilesystemArtifactCache"});constructor(e,t,r,o,i,n){this.layoutFactory=e,this.publisher=t,this.filesystem=r,this.pathService=o,this.fingerprinter=i,this.comparator=n;}async save(e,t,r){let o=this.layoutFactory.create(e),i=await this.fingerprinter.fingerprint(t,r),n={artifact:e,outputs:r,outputFingerprint:i,createdAt:Date.now(),schemaVersion:1};await this.publisher.publish(t,n,o);}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 o=await this.loadArtifactManifest(r.manifest());return !o||!this.hasValidFingerprints(o)?!1:await this.matchesFingerprints(t,o)}catch{return false}}async restore(e,t){let r=this.layoutFactory.create(e);try{let o=await this.loadArtifactManifest(r.manifest());if(!o||!this.hasValidFingerprints(o)||!await this.matchesFingerprints(r.root,o))return !1;for(let i of o.outputs){let n=r.output(i),p=this.pathService.join(t,i);await this.filesystem.remove(p),await this.filesystem.copy(n,p);}return await this.matchesFingerprints(t,o)}catch(o){return this.logger.error("artifact.restore.failed",{metadata:{method:"async restore",artifact:e.id,error:o instanceof Error?o.message:String(o)}}),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 o=new Set;for(let i of t){if(!i||typeof i.path!="string"||!r.has(i.path)||o.has(i.path)||!Number.isSafeInteger(i.sizeInBytes)||i.sizeInBytes<0||typeof i.integrity!="string"||!/^sha256:[a-f0-9]{64}$/.test(i.integrity))return false;o.add(i.path);}return o.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 o=await this.fingerprinter.fingerprint(e,t.outputs);if(o.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:o.length,expected:r,actual:o}}),false;let i=this.comparator.compare(r,o);return i.isIdentical||this.logger.error("artifact.cache.fingerprint.mismatch",{metadata:{artifact:t.artifact.id,root:e,expected:r,actual:o,diff:i.diff}}),i.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}};a();a();var re=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 M=class{cacheRoot;pathService;constructor(e,t){this.cacheRoot=e,this.pathService=t;}create(e){return new re(this.pathService.join(this.cacheRoot,e.packageName,e.id),this.pathService)}};a();var W=class{filesystem;pathService;constructor(e,t){this.filesystem=e,this.pathService=t;}async prepare(e,t){let r=this.pathService.resolve(e),o=t.map(i=>{if(i.trim().length===0||this.pathService.isAbsolute(i)||/^[a-zA-Z]:/.test(i)||/^(?:[/\\]{2}|[/\\])/.test(i))throw new Error(`Invalid build output path: "${i}". Outputs must be relative to the package root.`);if(i.replace(/\\/g,"/").split("/").includes(".."))throw new Error(`Invalid build output path: "${i}". Traversal segments are not allowed.`);let u=this.pathService.resolve(r,i),f=this.pathService.relative(r,u).replace(/\\/g,"/");if(f===""||f==="."||f===".."||f.startsWith("../")||this.pathService.isAbsolute(f))throw new Error(`Build output "${i}" resolves outside the allowed output area: "${u}".`);return u});for(let i of o)await this.filesystem.exists(i)||await this.filesystem.remove(i);}};a();var se=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))}};a();var ie=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)});}};a();var oe=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))}};a();var ae=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)});}};a();var G=class{fileSystem;pathService;constructor(e,t){this.fileSystem=e,this.pathService=t;}async exists(e,t){for(let r of t){let o=this.pathService.join(e,r);if(!await this.fileSystem.exists(o))return false}return true}};a();a();a();function T(s){return JSON.parse(s)}a();a();var qe={INVALID_PACKAGE_MANIFEST:"node.workspace.provider.invalid.package.manifest",NODE_WORKSPACE_PROVIDER_BOUNDARIES_LOAD_FAILED:"node.workspace.provider.boundaries.load.fail"};a();function Qe(s){return s instanceof Error&&"code"in s}function gt(s,...e){return Qe(s)&&e.includes(String(s.code))}a();function g(...s){return join(...s)}function V(s,...e){return join(s,...e)}function Xe(s){return V(s,"src")}function Ze(s){return V(s,"dist")}function et(s){return V(s,"test")}function wt(s){return dirname(s)}function ne(...s){return resolve(...s)}function de(s,e){return relative(s,e)}function xt(s){return isAbsolute(s)}function vt(s){return basename(s)}function Et(s){return normalize(s)}a();a();var Dr=new Set(["EBUSY","EPERM","EACCES"]);function bt(s){return s instanceof Error&&"code"in s&&Dr.has(String(s.code))}a();function At(s){return new Promise(e=>setTimeout(e,s))}async function le(s,e=5,t=50){let r;for(let o=0;o<e;o++)try{return await s()}catch(i){if(r=i,!bt(i))throw i;await At(t*(o+1));}throw r}A.createLogger({component:"fs-async"});async function v(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 me(s){return (await readdir(s,{withFileTypes:true})).map(e=>({path:g(s,e.name),name:e.name,isDirectory:e.isDirectory(),isFile:e.isFile(),isSymbolicLink:e.isSymbolicLink()}))}async function ce(s){return readFile(s,"utf-8")}async function Rt(s){return readFile(s)}async function ye(s){try{if(!(await stat(s)).isDirectory())throw new Error(`Cannot create directory over file: ${s}`);return}catch(e){if(!gt(e,"ENOENT"))throw e}await mkdir(s,{recursive:true});}function Ft(s,e){return le(()=>rename(s,e))}async function Tt(s,e,t={}){let r=await stat(s);return le(()=>cp(s,e,{recursive:r.isDirectory(),...t}))}async function Dt(s,e){await writeFile(s,e,"utf8");}function Ot(s){return le(()=>Hr(s))}async function Hr(s){await rm(s,{recursive:true,force:true});}a();var Y={root:process.cwd()};a();function ge(s){return {...s,path:Se(s.path)}}function Se(s){return s.replaceAll("\\","/")}a();var w=class{join(...e){return g(...e)}normalize(e){return Et(e)}relative(e,t){return de(e,t)}isAbsolute(e){return xt(e)}resolve(...e){return ne(...e)}dirname(e){return wt(e)}basename(e){return vt(e)}};a();function we(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}}a();a();a();function tt(s){return s.replaceAll("\\","/").replace(/^[A-Za-z]:/,"")}a();var C=class extends Error{operation;path;cause;constructor(e,t,r,o){super(e),this.operation=t,this.path=r,this.cause=o,this.name="FileSystemError";}};function _t(s,e="filesystem"){if(!Qe(s))return new C("Unknown filesystem error",e,void 0,s);switch(s.code){case "ENOENT":return new C(`File not found: ${rt(s.path)}`,e,s.path,s);case "EEXIST":return new C(`Path already exists: ${rt(s.path)}`,e,s.path,s);case "EISDIR":return new C(`Cannot write file over directory: ${rt(s.path)}`,e,s.path,s);default:return new C(s.message,e,s.path,s)}}function rt(s){return s?tt(s):"<unknown>"}var D=class{root;pathService;logger;constructor(e,t,r){this.root=t,this.pathService=r,this.logger=A.createLogger({component:e});}resolvePath(e){let t=Se(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 `/${Se(t)}`}logAndThrow(e,t){let r=_t(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 x=class extends D{constructor(e=Y){super("NodeAsyncFileSystemAdapter",e.root??Y.root,new w);}async readJson(e){return T(await this.read(e))}async writeJson(e,t,r){await this.write(e,E(t,2),r);}readBuffer(e){return Rt(this.resolvePath(e))}async read(e){try{return await ce(this.resolvePath(e))}catch(t){this.logAndThrow(t,"read");}}async write(e,t,r){let o=await this.exists(e);if(we(o,r))try{let i=this.resolvePath(e),n=this.pathService.dirname(i);await ye(n),await Dt(i,t);}catch(i){this.logAndThrow(i,"write");}}async copy(e,t){try{let r=this.resolvePath(e),o=this.resolvePath(t),i=this.pathService.dirname(o);await ye(i),await Tt(r,o);}catch(r){this.logAndThrow(r,"copy");}}async createDirectory(e){try{await ye(this.resolvePath(e));}catch(t){this.logAndThrow(t,"createDirectory");}}async exists(e){return v(this.resolvePath(e))}async remove(e){try{await Ot(this.resolvePath(e));}catch(t){this.logAndThrow(t,"remove");}}async readDirectory(e){let t=this.resolvePath(e);return (await me(t)).map(o=>({...ge(o),path:this.toVirtualPath(o.path)}))}async rename(e,t){try{await Ft(this.resolvePath(e),this.resolvePath(t));}catch(r){this.logAndThrow(r,"rename");}}};var U=class{createReaderForWorkspace(e){return new se(new x({root:e}))}createWriterForWorkspace(e){return new ie(new x({root:e}))}};a();var K=class{createReaderForWorkspace(e){return new oe(new x({root:e}))}createWriterForWorkspace(e){return new ae(new x({root:e}))}async assertArtifactStateExistsForWorkspace(e){let t=new x({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}".`)}};a();a();a();a();function O(s){try{return lstatSync(s),!0}catch(e){if(e instanceof Error&&"code"in e&&e.code==="ENOENT")return false;throw e}}function xe(s){try{return lstatSync(s).isDirectory()}catch{return false}}function it(s){return readFileSync(s,"utf-8")}function $t(s){return readFileSync(s)}function ve(s){return readFileSync(s,"utf8").replace(/\r\n/g,`
|
|
3
|
+
`)}function Ee(s){return readdirSync(s,{withFileTypes:true}).map(e=>({path:g(s,e.name),name:e.name,isDirectory:e.isDirectory(),isFile:e.isFile(),isSymbolicLink:e.isSymbolicLink()}))}function Lt(s){let e=it(s);return T(e)}function be(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 It(s,e){writeFileSync(s,e);}function Ht(s,e,t={}){if(O(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 jt(s,e){renameSync(s,e);}function Bt(s){rmSync(s,{recursive:true,force:true});}var _=class extends D{constructor(e=Y){super("NodeSyncFileSystemAdapter",e.root??Y.root,new w);}exists(e){return O(this.resolvePath(e))}createDirectory(e){try{be(this.resolvePath(e));}catch(t){this.logAndThrow(t,"createDirectory");}}remove(e){try{Bt(this.resolvePath(e));}catch(t){this.logAndThrow(t,"remove");}}read(e){try{return it(this.resolvePath(e))}catch(t){this.logAndThrow(t,"read");}}readBuffer(e){return $t(this.resolvePath(e))}readJson(e){return Lt(this.resolvePath(e))}readDirectory(e){return Ee(this.resolvePath(e)).map(r=>({...ge(r),path:this.toVirtualPath(r.path)}))}rename(e,t){try{jt(this.resolvePath(e),this.resolvePath(t));}catch(r){this.logAndThrow(r,"rename");}}write(e,t,r){let o=this.exists(e);if(we(o,r))try{let i=this.resolvePath(e),n=this.pathService.dirname(i);be(n),It(i,t);}catch(i){this.logAndThrow(i,"write");}}copy(e,t){try{let r=this.resolvePath(e),o=this.resolvePath(t),i=this.pathService.dirname(o);be(i),Ht(r,o);}catch(r){this.logAndThrow(r,"copy");}}writeJson(e,t,r){this.write(e,E(t,2),r);}};a();a();a();a();var J=class{hash(e){return createHash("sha256").update(e).digest("hex")}hashObject(e){return this.hash(E(e))}};var Yr=["package.json","tsconfig.json","tsconfig.build.json","tsup.config.ts"],q=class{hashService;constructor(e){this.hashService=e;}hashConfig(e){let t=[];for(let r of Yr){let o=g(e,r);if(!O(o))continue;let i=ve(o);t.push(r),t.push(i);}return this.hashService.hash(E(t,2))}};a();a();var qr=[/^\/\*\*/,/^\/\/\/\s*<reference\b/,/@ts-(?:ignore|expect-error|nocheck|check)\b/];function Qr(s){return qr.some(e=>e.test(s))}function zt(s){let e=createScanner(ScriptTarget.Latest,false,LanguageVariant.Standard,s),t=[];for(;;){let o=e.scan();if(o===SyntaxKind.EndOfFileToken)break;if(o!==SyntaxKind.SingleLineCommentTrivia&&o!==SyntaxKind.MultiLineCommentTrivia)continue;let i=e.getTokenStart(),n=e.getTokenEnd(),p=s.slice(i,n);if(Qr(p))continue;let u=n,f=" ";if(s[u]==="\r"&&s[u+1]===`
|
|
4
|
+
`?(u+=2,f=""):(s[u]===`
|
|
5
|
+
`||s[u]==="\r")&&(u+=1,f=""),u===s.length&&f===" "){let d=s[i-1];if(d===`
|
|
6
|
+
`||d==="\r"){t.push({start:i-(d===`
|
|
7
|
+
`&&s[i-2]==="\r"?2:1),end:u,text:""});continue}}t.push({start:i,end:u,text:f});}let r=s;for(let o of t.reverse())r=r.slice(0,o.start)+o.text+r.slice(o.end);return r}var Xr=new Set(["node_modules","dist",".turbo",".git"]),Zr=new Set(["tsconfig.tsbuildinfo"]),es=new Set([".ts",".tsx",".mts",".cts"]),Q=class{hashService;constructor(e){this.hashService=e;}hashSource(e){let t=ne(V(e,"src")),r=[];this.walk(t,r);let o=r.sort().map(i=>{let n=ve(i),p=this.isTypeScriptFile(i)?zt(n):n;return `${de(t,i)}\0${p}\0`}).join("");return this.hashService.hash(o)}walk(e,t){let r=Ee(e);r.sort((o,i)=>o.name.localeCompare(i.name));for(let o of r){if(Xr.has(o.name)||Zr.has(o.name))continue;let i=g(e,o.name);xe(i)?this.walk(i,t):t.push(i);}}isTypeScriptFile(e){let t=e.replaceAll("\\","/"),r=t.slice(t.lastIndexOf(".")).toLowerCase();return es.has(r)}};a();a();function Ae(s){return typeof s=="object"&&s!==null&&!Array.isArray(s)}var X=class{filesystem;logger=A.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(!Ae(t))return this.logger.warn("state.invalid.root",{metadata:{statePath:e}}),new Map;let r=Object.entries(t),o=new Map;for(let[i,n]of r){if(!this.isBuildStateEntry(n)){this.logger.warn("INVALID_BUILD_STATE_ENTRY",{metadata:{packageName:i}});continue}o.set(i,n);}return this.logger.trace("BUILD_STATE_LOADED",{metadata:{packages:[...o.keys()]}}),o}isHashResult(e){return Ae(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 Ae(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}};a();a();a();var Pe=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 Z=class{state;filesystem;changes=new Pe;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,E(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()}};a();a();a();a();var Mt=new Set([".git",".turbo","node_modules","dist","coverage"]);var Ce=class{logger=A.createLogger({component:"NodePackageProvider"});pathService=new w;async discover(e){let t=await this.findPackageRoots(g(e,"packages")),r=/^@[^/]+\//,i=(await Promise.all(t.map(n=>this.createPackageDescriptor(n)))).filter(n=>r.test(n.name));return this.resolveInternalDependencies(i)}async createPackageDescriptor(e){let t=g(e,"package.json"),[r,o,i]=await Promise.all([this.readPackageManifest(t),this.loadBoundaries(e),this.resolveLayout(e)]);return {name:r.name,rootPath:e,manifestPath:t,manifest:r,boundaries:o,internalDependencies:[],layout:i}}async findPackageRoots(e){let t=[],r=await me(e);for(let o of r){let i=g(e,o.name);if(Mt.has(o.name)||!xe(i))continue;let n=g(i,"package.json");if(await v(n)){t.push(i);continue}t.push(...await this.findPackageRoots(i));}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(o=>t.has(o)).sort()}))}async readPackageManifest(e){let t=await ce(e),r=T(t);if(!this.isPackageManifest(r))throw this.logger.error(qe.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=g(e,".boundaries.json");try{let r=await ce(t);return T(r)}catch(r){if(this.isNodeError(r)&&r.code==="ENOENT")return;throw this.logger.error(qe.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,o,i,n]=await Promise.all([v(Xe(e)),v(et(e)),v(Ze(e)),v(t)]);return {sourceDirectory:Xe(e),hasSourceDirectory:r,testsDirectory:et(e),hasTestsDirectory:o,distributionDirectory:Ze(e),hasDistributionDirectory:i,tsconfigPath:t,hasTsconfig:n}}isNodeError(e){return typeof e=="object"&&e!==null&&"code"in e}};var ts="pnpm-workspace.yaml",ee=class{packageProvider;pathService;constructor(e=new Ce,t=new w){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,ts);if(O(r))return t;let o=this.pathService.dirname(t);if(o===t)throw new Error(`Unable to locate workspace root from "${e}"`);t=o;}}async resolveWorkspaceLayout(e){let t=this.pathService.join(e,"package.json"),r=this.pathService.join(e,"tsconfig.json"),o=this.pathService.join(e,"config"),i=this.pathService.join(o,"arch.manifest.json"),n=this.pathService.join(e,"scripts"),p=this.pathService.join(this.pathService.resolve(n),"git"),[u,f,d,l]=await Promise.all([v(t),v(r),v(i),v(p)]);return {packageJsonPath:t,tsconfigPath:r,archManifestPath:i,scriptPath:p,hasPackageManifest:u,hasTsconfig:f,hasArchManifest:d,hasScriptPath:l}}};a();var te=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(/^\.?\//,"")}};a();a();var Re=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 Fe=class{build(e,t,r,o){let i=new Map;for(let n of r){if(n.status==="failed")continue;let p=e.get(n.package),u=t.get(n.package),f=o.nodes.get(n.package);!p||!u||!f||f.startedAt===void 0||f.finishedAt===void 0||i.set(n.package,{hash:u.hash,dependencies:[...p.dependencies],artifactType:p.artifactType,status:this.resolveStatus(n),reason:this.resolveReason(u),startedAt:f.startedAt,finishedAt:f.finishedAt,schemaVersion:1});}return i}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 "source":return "source-changed";case "dependency":return "dependency-changed";case "first-build":return "first-build";case "cache-version":case "config":case "output-integrity":return "cache-invalidated";case "missing-output":return "missing-output";case "dependency-failed":throw new Error("Cannot create ArtifactState for a dependency-failed change")}}};a();a();a();a();function Wt(s,e){let t=new WeakSet,r=(o,i)=>{if(i instanceof Error)return {name:i.name,message:i.message,stack:i.stack};if(typeof i=="bigint")return i.toString();if(typeof i>"u")return "[undefined]";if(typeof i=="symbol")return i.toString();if(i instanceof Map)return Object.fromEntries(i);if(i instanceof Set)return [...i];if(typeof i=="object"&&i!==null){if(t.has(i))return "[Circular]";t.add(i);}return i};try{return JSON.stringify(s,r,e)}catch{return "[unserializable]"}}a();var R={reset:"\x1B[0m",brightCyan:"\x1B[96m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightRed:"\x1B[91m"},Gt={trace:{write:console.debug,symbol:`${R.brightCyan}\xB7 ${R.reset}`},info:{write:console.log,symbol:""},success:{write:console.log,symbol:`${R.brightGreen}\u2705 ${R.reset}`},warn:{write:console.warn,symbol:`${R.brightYellow}\u26A0 ${R.reset}`},error:{write:console.error,symbol:`${R.brightRed}\u274C ${R.reset}`}};a();a();a();var Te=/(token|secret|password|api[-_]?key)/i;function Vt(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,Te.test(e)?"***":t]))}function Yt(s){if(!s)return;let e=Object.entries(s).map(([t,r])=>Te.test(t)?[t,"***"]:t==="env"&&r!==null&&typeof r=="object"?[t,Vt(r)]:[t,r]);return Object.fromEntries(e)}a();var Ut=process.env.ARCH_BUILD_TRACE==="1",Kt=process.env.ARCH_BUILD_TRACE_CACHE==="1",Jt=process.env.ARCH_BUILD_TRACE_HASH==="1";var rs="[arch]",m={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 k(s,e){return `${s}${e}${m.reset}`}function ss(s){return s.replace(/"([^"]+)":/g,`${m.cyan}"$1"${m.reset}:`).replace(/"([^"]*)"/g,`${m.green}"$1"${m.reset}`).replace(/\b(true|false)\b/g,`${m.yellow}$1${m.reset}`).replace(/\bnull\b/g,`${m.magenta}null${m.reset}`).replace(/(?<!["\w])(-?\d+(?:\.\d+)?)(?!["\w])/g,`${m.brightYellow}$1${m.reset}`)}function is(s){if(Ut)return true;switch(s){case "cache":return Kt;case "hash":return Jt;default:return false}}function he(s,e,t={}){let{prefix:r=true,metadata:o}=t,i=new Date().toISOString(),n=o?Yt(o):void 0,p=r?`${k(m.dim,rs)} `:"",u=(()=>{switch(s){case "trace":return k(m.brightCyan,e);case "info":return k(m.white,e);case "success":return k(m.brightGreen,e);case "warn":return k(m.brightYellow,e);case "error":return k(m.brightRed,e);default:return e}})(),f=k(m.gray,`[${i}]`),d=n?`${f} ${p}${u}
|
|
8
|
+
${ss(Wt(n,2))}`:`${f} ${p}${u}`,{write:l,symbol:b}=Gt[s];l(`${b}${d}`);}var S={trace(s,e={}){is(e.category)&&he("trace",s,e);},info(s,e){he("info",s,e);},success(s,e){he("success",s,e);},warn(s,e){he("warn",s,e);},error(s,e){he("error",s,e);},newline(){process.stdout.write(`
|
|
9
|
+
`);}};a();function qt(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 De=class{ctx;constructor(e){this.ctx=e;}async execute(e,t){let r=qt(e.build);for(let o of r){let i=await this.ctx.runner(o.command,o.args,{cwd:e.root});if(i.exitCode!==0)return S.error("step failed",{metadata:{package:e.name,step:o.name,exitCode:i.exitCode,stdout:i.stdout,stderr:i.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 Oe=class{create(e){return new De({runner:e.runner})}};a();function Qt(s){let e=os(s);return as(e),ns(e),e}function os(s){let e=new Map,t=new Set(s.map(o=>o.name));for(let o of s)e.set(o.name,{name:o.name,root:o.root,dependencies:r(o,t),dependents:[],outputs:[...o.outputs],artifactType:o.artifactType,build:o.build});function r(o,i){return [...o.dependencies,...o.buildDependencies].filter(n=>i.has(n))}return e}function as(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 ns(s){for(let e of s.values())Object.freeze(e.dependencies),Object.freeze(e.dependents),Object.freeze(e.outputs),Object.freeze(e);}a();var _e=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),o=this.getDependencyClosure(e),i=new Set;for(let n of o)r.has(n)&&i.add(n);return i.add(e),i}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);}}};a();a();a();var ke=class extends Error{details;constructor(e,t){super(`[Hash] ${e}`),this.details=t,this.name="HashConsistencyError";}};var Ne=class{hashService;constructor(e){this.hashService=e;}validate({input:e,result:t}){let r=this.hashService.hashObject(e);if(r!==t.hash)throw new ke(`Hash mismatch for ${e.nodeName}`,{expected:{hash:r},actual:{hash:t.hash}})}};function cs(s){return [...s].sort().join("|")}var $e=class{configHashService;sourceHashService;hashService;validator;constructor(e,t,r,o){this.configHashService=e,this.sourceHashService=t,this.hashService=r,this.validator=o;}hash(e,t){let r=this.sourceHashService.hashSource(e.root),o=this.configHashService.hashConfig(e.root),i=this.hashService.hash(cs(t.dependencyHashes)),n={nodeName:e.name,sourceHash:r,configHash:o,depsHash:i,schemaVersion:1},u={hash:this.hashService.hashObject(n),sourceHash:r,configHash:o,depsHash:i,schemaVersion:1};return this.validator.validate({input:n,result:u}),S.trace("build.hash.calculated",{category:"hash",metadata:{packageName:e.name,hash:u.hash}}),u}};a();var Le=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}}}};a();a();var Ie=class{state;outputValidator;artifactCache;artifactProvider;constructor(e,t,r,o){this.state=e,this.outputValidator=t,this.artifactCache=r,this.artifactProvider=o;}async evaluate(e,t,r,o){let i=this.state.get(e);if(!i){let d=this.artifactProvider.create(e,o),l=await this.artifactCache.exists(d);return l?(S.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"restore",changeReason:"first-build",available:l}}),{packageName:e,decision:"restore",changeReason:"first-build",available:l}):(S.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"miss",changeReason:"first-build",available:l}}),{packageName:e,decision:"miss",changeReason:"first-build",available:l})}if(i.schemaVersion!==1)return this.stale(e,"cache-version");if(i.hash.sourceHash!==o.sourceHash)return this.stale(e,"source");if(i.hash.configHash!==o.configHash)return this.stale(e,"config");if(i.hash.depsHash!==o.depsHash)return this.stale(e,"dependency");let n=this.artifactProvider.create(e,o),p=await this.outputValidator.exists(t,r);if(p&&await this.artifactCache.verifyOutputs(n,t)){let d=await this.artifactCache.exists(n);return S.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"hit",changeReason:"none"}}),{packageName:e,decision:"hit",changeReason:"none",available:d}}let u=p?"output-integrity":"missing-output",f=await this.artifactCache.exists(n);return f?(S.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"restore",changeReason:u,available:f}}),{packageName:e,decision:"restore",changeReason:u,available:f}):(S.trace("build.cache.evaluated",{category:"cache",metadata:{packageName:e,decision:"invalid",changeReason:u,available:f}}),{packageName:e,decision:"invalid",changeReason:u,available:f})}stale(e,t){return {packageName:e,decision:"stale",changeReason:t,available:true}}};a();var He=class{graph;executor;plan;writer;artifactCache;outputValidator;artifactProvider;artifactOutputPreparer;constructor(e,t,r,o,i,n,p,u){this.graph=e,this.executor=t,this.plan=r,this.writer=o,this.artifactCache=i,this.outputValidator=n,this.artifactProvider=p,this.artifactOutputPreparer=u;}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 o=this.artifactProvider.create(e.name,t.hash);return await this.artifactCache.save(o,e.root,e.outputs),this.writer.commit(e,t.hash),r}catch(r){throw S.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)}}};a();var je=class{graph;hasher;constructor(e,t){this.graph=e,this.hasher=t;}build(){let e=new Map,t=new Set,r=o=>{let i=e.get(o);if(i)return i;if(t.has(o))throw new Error(`Cycle detected at ${o}`);t.add(o);let n=this.graph.get(o);if(!n)throw new Error(`Missing node ${o}`);let p=[];for(let f of n.dependencies)p.push(r(f).hash);let u=this.hasher.hash(n,{dependencyHashes:p});return t.delete(o),e.set(o,u),u};for(let o of this.graph.keys())r(o);return e}};a();var Zt={STATE_CHANGED:"build.service.state.changed"};a();var Be=class{evaluator;constructor(e){this.evaluator=e;}async createPlan(e,t){let r=new Re;for(let[o,i]of e){let n=t.get(o);if(!n)throw new Error(`[ChangePlanner] Missing hash for "${o}"`);let p=await this.evaluator.evaluate(i.name,i.root,i.outputs,n);r.set(o,{package:o,buildAction:this.resolveBuildAction(p.decision,p.available),cache:{decision:p.decision},changeReason:p.changeReason,hash:n});}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"}}};a();var ze=class{query;contractResolver;constructor(e,t){this.query=e,this.contractResolver=t;}compile(e){let{plan:t,scope:r}=e,o=new Map;for(let i of r){let n=t.get(i);if(!n)continue;let p=this.resolveDependencies(i,r),u=this.contractResolver.resolve(i);o.set(i,this.createNode(i,p,n,u));}for(let i of o.values())for(let n of i.dependencies){let p=o.get(n);p&&p.dependents.push(i.name);}return {nodes:o}}createNode(e,t,r,o){return {name:e,dependencies:t,dependents:[],buildAction:r.buildAction,changeReason:r.changeReason,contract:o}}resolveDependencies(e,t){return this.query.getDependencies(e).filter(r=>t.has(r))}};a();var Me=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))}};a();function er(s){let e=new Map,t=new Map,r=new Map;for(let[o]of s.nodes)e.set(o,{state:"pending"}),t.set(o,"pending");return {nodes:e,nodeStates:t,triggers:r}}function N(s,e,t,r){let o=s.nodes.get(e);if(!o)throw new Error(`Execution node not found: ${e}`);let i=Date.now(),n={...o,state:t};t==="running"&&(n.startedAt=i),(t==="success"||t==="failed"||t==="cached"||t==="skipped")&&(n.finishedAt=i,n.startedAt!==void 0&&(n.duration=n.finishedAt-n.startedAt)),r&&(n.error=r),s.nodes.set(e,n),s.nodeStates.set(e,t);}a();var We=class{runner;concurrency;constructor(e,t){this.runner=e,this.concurrency=t;}async run(e,t){let r=[],o=new Map,i=this.initializeReadyQueue(e,t);for(;i.length>0||o.size>0;)this.dispatch(e,t,i,o,r),o.size>0&&await Promise.race(o.values());return r}initializeReadyQueue(e,t){let r=[];for(let[o,i]of e.nodes)i.dependencies.length>0||(N(t,o,"ready"),this.setTrigger(t,i),r.push(o));return r}dispatch(e,t,r,o,i){for(;o.size<this.concurrency&&r.length>0;){let n=r.shift();if(!n)return;let p=this.execute(n,e,t,r,i);o.set(n,p.finally(()=>{o.delete(n);}));}}async execute(e,t,r,o,i){try{N(r,e,"running");let n=await this.runner.run(e),p=r.triggers.get(e);p&&(n.execution.triggeredBy=p),i.push(n),N(r,e,"success");let u=t.nodes.get(e);u&&this.notifyDependentsReady(u,t,r,o);}catch(n){let p=n instanceof Error?n.message:String(n);N(r,e,"failed",p),S.error("[execution-plan-scheduler] execution failed",{metadata:{package:e,error:p}}),i.push({package:e,status:"failed",changeReason:"none",execution:{reason:"failed"}});let u=t.nodes.get(e);u&&this.notifyDependentsFailed(u,t,r,i);}}notifyDependentsReady(e,t,r,o){for(let i of e.dependents){let n=t.nodes.get(i);if(!n)continue;let p=r.nodes.get(i);!p||p.state!=="pending"||!n.dependencies.every(f=>r.nodes.get(f)?.state==="success")||(N(r,i,"ready"),this.setDependencyTrigger(r,n,e),o.push(i));}}notifyDependentsFailed(e,t,r,o){for(let i of e.dependents){let n=r.nodes.get(i);!n||n.state!=="pending"||(N(r,i,"skipped",`Dependency ${e.name} failed`),o.push({package:i,status:"skipped",changeReason:"dependency-failed",execution:{reason:"failed"}}));}}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-changed"});}toExecutionTriggerReason(e){switch(e){case "source":return "source-changed";case "dependency":return "dependency-changed";case "first-build":return "first-build";case "cache-version":case "config":case "missing-output":case "output-integrity":return "cache-invalidated";case "dependency-failed":return "dependency-changed";case "none":return}}};var Ge=class{context;constructor(e){this.context=e;}async run(e){let{graph:t,query:r,dagHasher:o,contractResolver:i,state:n,executor:p,artifactCache:u,artifactProvider:f,artifactOutputPreparer:d,fsOutputValidator:l,stateWriter:b,artifactStateReader:pr,artifactStateWriter:ur,artifactStateHistoryReader:fr,artifactStateHistoryWriter:dr,artifactStateBuilder:lr}=this.context,mr=new je(t,o).build(),yr=new Ie(n,l,u,f),ue=await new Be(yr).createPlan(t,mr),at=new Me(ue,r).resolve(e.scope);if(at.size===0)return this.summarize([]);let nt=new ze(r,i).compile({plan:ue,scope:at}),gr=new He(t,p,ue,b,u,l,f,d),Sr=new We(gr,e.concurrency??4),ct=er(nt),Ue=await Sr.run(nt,ct);if(Ue.every(P=>P.status!=="failed")){b.prune(new Set(t.keys()));let P=b.getChanges();(P.created.size>0||P.updated.size>0||P.deleted.size>0)&&(S.info(Zt.STATE_CHANGED,{metadata:{created:P.created.size,updated:P.updated.size,deleted:P.deleted.size}}),await b.write());let Ke=lr.build(t,ue,Ue,ct);if(Ke.size>0){let ht=await pr.read(),pt=this.buildArtifactStateHistory(ht,Ke);if(pt.size>0){let xr=await fr.read(),vr=this.mergeArtifactStateHistory(xr,pt);await dr.write(vr);}let wr=this.mergeArtifactStates(ht,Ke);await ur.write(wr);}}return this.summarize(Ue)}mergeArtifactStates(e,t){let r=new Map(e);for(let[o,i]of t)r.set(o,i);return r}mergeArtifactStateHistory(e,t){let r=new Map(e);for(let[o,i]of t){let n=r.get(o);if(!n){r.set(o,i);continue}r.set(o,{artifact:o,changes:[...n.changes,...i.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[o,i]of t){let n=e.get(o);if(!n){r.set(o,{artifact:o,changes:[{previousHash:null,currentHash:i.hash.hash,reason:i.reason,timestamp:i.finishedAt}]});continue}n.hash.hash!==i.hash.hash&&r.set(o,{artifact:o,changes:[{previousHash:n.hash.hash,currentHash:i.hash.hash,reason:i.reason,timestamp:i.finishedAt}]});}return r}};var Ve=class{runner;fsAsync=new x;workspaceProvider=new ee;artifactStateProvider=new K;artifactStateHistoryProvider=new U;workspacePackageProjector=new te;pathService=new w;hashService=new J;constructor(e){this.runner=e;}async createBuildService(e){let t=await this.workspaceProvider.discover(e),r=this.workspacePackageProjector.projectAll(t.packages),o=Qt(r),i=this.createBuildStateLoader(t.root),n=this.createArtifactStateReader(t.root),p=this.createGraphQuery(o);return new Ge({graph:o,query:p,dagHasher:this.createDagHasher(),contractResolver:this.createExecutionContractResolver(p),state:i,executor:this.createExecutor(),artifactCache:this.createArtifactCache(t.root),artifactProvider:this.createArtifactProvider(),artifactOutputPreparer:this.createArtifactOutputPreparer(),workspaceRoot:t.root,fsOutputValidator:this.createFileSystemOutputValidator(),stateWriter:this.createStateWriter(i,t.root),artifactStateReader:n,artifactStateWriter:this.createArtifactStateWriter(t.root),artifactStateBuilder:this.createArtifactStateBuilder(),artifactStateHistoryReader:this.createArtifactStateHistoryReader(t.root),artifactStateHistoryWriter:this.createArtifactStateHistoryWriter(t.root)})}createArtifactCache(e){let t=new M(this.pathService.join(e,".arch-platform-cache","artifacts"),this.pathService),r=new j(this.fsAsync,this.pathService),o=new H(this.fsAsync,this.pathService,this.hashService),i=new I;return new z(t,r,this.fsAsync,this.pathService,o,i)}createArtifactOutputPreparer(){return new W(this.fsAsync,this.pathService)}createExecutor(){return new Oe().create({runner:this.runner})}createGraphQuery(e){return new _e(e)}createExecutionContractResolver(e){return new Le(e)}createBuildStateLoader(e){let t=new _({root:e});return new X(t).load()}createStateWriter(e,t){let r=new x({root:t});return new Z(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 B}createArtifactStateBuilder(){return new Fe}createFileSystemOutputValidator(){return new G(this.fsAsync,this.pathService)}createDagHasher(){let e=new q(this.hashService),t=new Q(this.hashService),r=new Ne(this.hashService);return new $e(e,t,this.hashService,r)}};var pe=class{fromDirectory;compositionRoot;constructor(e,t){this.fromDirectory=e,this.compositionRoot=new Ve(t);}async create(){return this.compositionRoot.createBuildService(this.fromDirectory)}};a();var tr=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 o=r;return {exitCode:o.exitCode??1,stdout:o.stdout??"",stderr:o.stderr??String(r)}}};a();a();function ps(s){return typeof s=="object"&&s!==null}function rr(s,e){let t=new WeakSet;try{return JSON.stringify(s,(r,o)=>{if(ps(o)){if(t.has(o))return "[Circular]";t.add(o);}return o},e)}catch{return "[unserializable]"}}a();a();var us=/(token|secret|password|api[-_]?key)/i;function sr(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>[e,us.test(e)?"***":t]))}var fs=/(token|secret|password|api[-_]?key)/i;function ir(s){if(s)return Object.fromEntries(Object.entries(s).map(([e,t])=>fs.test(e)?[e,"***"]:e==="env"&&t&&typeof t=="object"?[e,sr(t)]:[e,t]))}a();var F={reset:"\x1B[0m",brightCyan:"\x1B[96m",brightGreen:"\x1B[92m",brightYellow:"\x1B[93m",brightRed:"\x1B[91m"},or={trace:{write:console.debug,symbol:`${F.brightCyan}\xB7 ${F.reset}`},info:{write:console.log,symbol:""},success:{write:console.log,symbol:`${F.brightGreen}\u2705 ${F.reset}`},warn:{write:console.warn,symbol:`${F.brightYellow}\u26A0 ${F.reset}`},error:{write:console.error,symbol:`${F.brightRed}\u274C ${F.reset}`}};var ds="[arch]",y={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 $(s,e){return `${s}${e}${y.reset}`}function ls(s){return s.replace(/"([^"]+)":/g,`${y.cyan}"$1"${y.reset}:`).replace(/"([^"]*)"/g,`${y.green}"$1"${y.reset}`).replace(/\b(true|false)\b/g,`${y.yellow}$1${y.reset}`).replace(/\bnull\b/g,`${y.magenta}null${y.reset}`).replace(/(?<!["\w])(-?\d+(?:\.\d+)?)(?!["\w])/g,`${y.brightYellow}$1${y.reset}`)}function Ye(s,e,t={}){let{prefix:r=true,metadata:o}=t,i=new Date().toISOString(),n=o?ir(o):void 0,p=r?`${$(y.dim,ds)} `:"",u=(()=>{switch(s){case "trace":return $(y.brightCyan,e);case "info":return $(y.white,e);case "success":return $(y.brightGreen,e);case "warn":return $(y.brightYellow,e);case "error":return $(y.brightRed,e);default:return e}})(),f=$(y.gray,`[${i}]`),d=n?`${f} ${p}${u}
|
|
10
|
+
${ls(rr(n,2))}`:`${f} ${p}${u}`,{write:l,symbol:b}=or[s];l(`${b}${d}`);}var L={info(s,e){Ye("info",s,e);},success(s,e){Ye("success",s,e);},warn(s,e){Ye("warn",s,e);},error(s,e){Ye("error",s,e);},newline(){process.stdout.write(`
|
|
11
|
+
`);}};a();function ar(s){return s.packageName?{mode:"package",packageName:s.packageName}:{mode:"workspace"}}function nr(s){s.command("build").option("--package <packageName>","Build specific package").action(async e=>{process.exitCode=await ms({packageName:e.package});});}async function ms(s){let r=await(await new pe(process.cwd(),tr).create()).run({scope:ar(s)}),o=r.failed===0;return L.newline(),L.info("ARCH Build"),L.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"),L[o?"success":"error"](o?"Status: BUILD COMPLETED":"Status: BUILD FAILED"),L.info(`Executed: ${r.executed} \xB7 Restored: ${r.restored} \xB7 Cached: ${r.cached} \xB7 Failed: ${r.failed}`),L.newline(),o?0:1}function cr(s){nr(s);}function hr(){let s=cac("arch-cli");return cr(s),s.help(),s}hr().parse();
|
package/package.json
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arch-platform/distribution",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.1.1",
|
|
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"
|
|
41
|
+
}
|
|
6
42
|
}
|