modelence 0.26.1-nd.dev.1 → 0.26.1-nd.dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/modelence.js +14 -13
- package/dist/bin/modelence.js.map +1 -1
- package/dist/{chunk-YJZ22HME.js → chunk-MQ7V2FCN.js} +5 -5
- package/dist/{chunk-YJZ22HME.js.map → chunk-MQ7V2FCN.js.map} +1 -1
- package/dist/{chunk-GW46X34B.js → chunk-OBZHVDVD.js} +3 -3
- package/dist/{chunk-GW46X34B.js.map → chunk-OBZHVDVD.js.map} +1 -1
- package/dist/{package-MS2HPTQM.js → package-OBUCENSQ.js} +2 -2
- package/dist/{package-MS2HPTQM.js.map → package-OBUCENSQ.js.map} +1 -1
- package/dist/server-FF6LAQCG.js +2 -0
- package/dist/{server-FILJ5I4O.js.map → server-FF6LAQCG.js.map} +1 -1
- package/dist/server.js +1 -1
- package/package.json +1 -1
- package/dist/server-FILJ5I4O.js +0 -2
package/dist/bin/modelence.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {Command}from'commander';import {readFileSync,promises,createWriteStream,openAsBlob}from'fs';import {fileURLToPath}from'url';import
|
|
3
|
-
`,{mode:384});}async function
|
|
4
|
-
`);}var y=class extends Error{constructor(o,n){super(o);this.status=n;this.name="StudioApiError";}};async function f(e,t,{method:o="GET",token:n,body:r,query:i}={}){let
|
|
5
|
-
claude plugin marketplace add ${
|
|
6
|
-
claude plugin install ${
|
|
7
|
-
Guide: ${
|
|
8
|
-
`),console.log(`Declared the Modelence Claude Code plugin in ${
|
|
2
|
+
import {Command}from'commander';import {readFileSync,promises,createWriteStream,openAsBlob}from'fs';import {fileURLToPath}from'url';import ce,{join,dirname,relative,isAbsolute,resolve,sep}from'path';import {parse}from'dotenv';import {createInterface}from'readline';import {execFile,execSync,spawnSync}from'child_process';import bt from'open';import xt from'os';import Ne from'fs/promises';import {createJiti}from'jiti';import {z as z$1}from'zod';import {build}from'tsup';import {loadConfigFromFile,build as build$1,mergeConfig}from'vite';import co from'archiver';import {promisify}from'util';import {parse as parse$1,modify,applyEdits,printParseErrorCode}from'jsonc-parser';async function A(e,{pick:t,purpose:o,pickEnvironment:n=false,appId:r}={}){let i=await fetch(`${e}/api/cli/auth`,{method:"POST"});if(!i.ok)throw new Error("Failed to create CLI authentication code");let{code:a,verificationUrl:l}=await i.json(),c=new URL(l),s=t??(n?"environment":void 0);s&&c.searchParams.set("pick",s),o&&c.searchParams.set("purpose",o),r&&c.searchParams.set("appId",r),console.log(`Please visit ${c} to authenticate`),console.log(`Code: ${a}`);try{await bt(c.toString());}catch{console.log("Could not open a browser automatically. Please open the URL above manually.");}return await Pt(e,a)}async function Pt(e,t){let r=Date.now()+6e5;for(;Date.now()<r;){try{let i=await Ct(e,t);if(i)return i}catch(i){console.error("Error polling for CLI token:",i);}await new Promise(i=>setTimeout(i,2e3));}throw new Error("Unable to authenticate CLI - timed out. Please try again.")}async function Ct(e,t){let o=await fetch(`${e}/api/cli/token?code=${t}`,{method:"GET"});if(!o.ok)throw new Error(`CLI token polling failed: ${o.statusText}`);let{token:n,expiresAt:r,target:i}=await o.json();return n?{token:n,expiresAt:r,target:i}:null}var kt="auth.json",Tt=40*60*1e3;function O(){let e=process.env.MODELENCE_HOME||join(xt.homedir(),".modelence");return join(e,kt)}async function F(){try{let e=JSON.parse(await promises.readFile(O(),"utf8"));return e&&typeof e=="object"?e:{}}catch{return {}}}async function Q(e){let t=O();await promises.mkdir(dirname(t),{recursive:true,mode:448}),await promises.writeFile(t,JSON.stringify(e,null,2)+`
|
|
3
|
+
`,{mode:384});}async function he(e){let{hosts:t={}}=await F(),o=t[e];return !o?.token||!o.expiresAt||new Date(o.expiresAt).getTime()-Tt<=Date.now()?null:o.token}async function ye(e){let{hosts:t={}}=await F();return Object.entries(t).filter(([o,n])=>(!e||o===e)&&!!n?.token).map(([o,n])=>({host:o,token:n.token}))}async function we(e,t,o){let n=await F();await Q({...n,hosts:{...n.hosts,[e]:{token:t,expiresAt:o}}});}async function L(e){if(!e){await Q({});return}let t=await F(),{[e]:o,...n}=t.hosts??{};await Q({...t,hosts:n});}var k=".modelence",M="project.json";function Ee(e=process.cwd()){return join(e,k,M)}async function T(e=process.cwd()){try{let t=await promises.readFile(Ee(e),"utf8"),o=JSON.parse(t);return o&&typeof o=="object"?o:{}}catch{return {}}}async function j(e,t=process.cwd()){let o=await T(t);await promises.mkdir(join(t,k),{recursive:true}),await promises.writeFile(Ee(t),JSON.stringify({...o,...e},null,2)+`
|
|
4
|
+
`);}var y=class extends Error{constructor(o,n){super(o);this.status=n;this.name="StudioApiError";}};async function f(e,t,{method:o="GET",token:n,body:r,query:i}={}){let a=new URL(t,e);for(let[s,p]of Object.entries(i??{}))a.searchParams.set(s,String(p));let l={};n&&(l.Authorization=`Bearer ${n}`),r!==void 0&&(l["Content-Type"]="application/json");let c=await fetch(a,{method:o,headers:l,body:r===void 0?void 0:JSON.stringify(r)});if(!c.ok){let s=await c.text(),p=s||c.statusText;try{let u=JSON.parse(s);p=u.error||u.message||p;}catch{}throw new y(p,c.status)}return await c.json()}var Se="https://cloud.modelence.com";function R(e){return e instanceof y&&e.status===401}async function be(e){return process.env.MODELENCE_TOKEN?process.env.MODELENCE_TOKEN:await he(e)}async function te(e,t,o){if(o)try{await we(e,t,o);}catch(n){console.warn("Could not save the login for next time:",n);}}async function oe(e,t){let o={environmentId:e.environmentId,appAlias:e.appAlias,envAlias:e.envAlias,host:t};try{await j({deploy:o,..."appId"in e?{appId:e.appId}:{}});}catch(n){console.warn("Could not record the deploy target in .modelence/project.json:",n);}}function Pe(e,t){if(!e.deploy||(e.deploy.host??Se)===t)return e;let{deploy:o,appId:n,...r}=e;return r}function w(e){let t=e.trim().replace(/\/+$/,""),o=/^[a-z][a-z0-9+.-]*:\/\//i.test(t)?t:`https://${t}`;try{return new URL(o).origin}catch{throw new Error(`Invalid Modelence host "${e}"; expected e.g. https://cloud.modelence.com`)}}async function Ce(e,t){if(e)return w(e);if(process.env.MODELENCE_SERVICE_ENDPOINT)return w(process.env.MODELENCE_SERVICE_ENDPOINT);let o={};try{o=parse(await promises.readFile(join(t,".modelence.env"),"utf8"));}catch{}return o.MODELENCE_SERVICE_ENDPOINT?w(o.MODELENCE_SERVICE_ENDPOINT):Se}var re=".modelence.env";async function Ft(e,t){let o="setupToken"in t?{"X-Modelence-Setup-Token":t.setupToken}:{Authorization:`Bearer ${t.cliToken}`},n=await fetch(`${e}/api/setup`,{method:"GET",headers:o});if(!n.ok){let r=await n.text();throw new Error(r||`Request failed with status ${n.status}`)}return n.json()}async function Ae(e){let t=createInterface({input:process.stdin,output:process.stdout});return new Promise(o=>{t.question(e,n=>{t.close(),o(n.trim());});})}async function Lt(){return (await Ae(`Warning: ${re} already exists. Do you want to overwrite it? (y/N) `)).toLowerCase()==="y"}function Mt(e){return String(e).replace(/"/g,'\\"')}async function jt(){let{appId:e}=await T();return typeof e=="string"&&e?e:void 0}async function Rt(e){await j({appId:e});}var ke=".claude",$=join(ke,"settings.json"),B="modelence@modelence",ie="modelence/modelence",Ut={modelence:{source:{source:"github",repo:ie}}},Bt="https://docs.modelence.com/ai-coding-agents",xe=`Install the Modelence plugin for Claude Code by hand:
|
|
5
|
+
claude plugin marketplace add ${ie}
|
|
6
|
+
claude plugin install ${B} --scope project
|
|
7
|
+
Guide: ${Bt}`;async function Vt(){let e=join(process.cwd(),$),t;try{t=await promises.readFile(e,"utf8");}catch(n){if(n.code!=="ENOENT"){console.warn(`Could not read ${$}; leaving it unchanged.`);return}}let o={};if(t!==void 0)try{o=JSON.parse(t);}catch{console.warn(`Could not parse ${$}; leaving it unchanged.`);return}o.extraKnownMarketplaces={...o.extraKnownMarketplaces,...Ut},o.enabledPlugins?.[B]===void 0&&(o.enabledPlugins={...o.enabledPlugins,[B]:true});try{await promises.mkdir(join(process.cwd(),ke),{recursive:!0}),await promises.writeFile(e,JSON.stringify(o,null,2)+`
|
|
8
|
+
`),console.log(`Declared the Modelence Claude Code plugin in ${$}`);}catch(n){console.warn(`Failed to write ${$}:`,n);}}function ne(e){return spawnSync("claude",e,{encoding:"utf8",shell:process.platform==="win32"})}async function Kt(){let e=ne(["--version"]);if(e.error||e.status!==0){console.log(xe);return}let t=(await Ae("Install the Modelence plugin for Claude Code? (Y/n) ")).toLowerCase();if(t&&t!=="y"&&t!=="yes")return;let o=ne(["plugin","marketplace","add",ie]),n=ne(["plugin","install",B,"--scope","project"]);if(n.status===0)console.log("Installed the Modelence plugin for Claude Code. Sign in once from Claude Code: run /mcp, choose modelence, then Authenticate.");else {let r=o.status!==0?o:n;console.warn(`Could not install the Modelence plugin: ${(r.stderr||r.stdout||"").trim()}`),console.warn(xe);}}async function zt(e){try{let t=e.replace(".env",".backup.env");await promises.copyFile(e,t),console.log(`Backup created at ${t}`);}catch(t){console.warn("Failed to create backup file:",t);}}async function Te(e){let t={...e,host:w(e.host)};try{let o=join(process.cwd(),re),n={},r=!1;try{let s=await promises.readFile(o,"utf8");n=parse(s),r=!0,await zt(o),await Lt()||(console.log("Setup canceled"),process.exit(0));}catch{}let i;if(t.token)i={setupToken:t.token};else {let{token:s}=await A(t.host,{pickEnvironment:!0,appId:await jt()});i={cliToken:s};}console.log("Fetching service configuration...");let a=await Ft(t.host,i),l={...n,MODELENCE_TELEMETRY_ENABLED:"false",MODELENCE_ENVIRONMENT_ID:a.environmentId,MODELENCE_SERVICE_ENDPOINT:t.host,MODELENCE_SERVICE_TOKEN:a.serviceToken,MODELENCE_CONTAINER_ID:a.containerId,MODELENCE_RUNTIME:process.env.MODELENCE_RUNTIME||"local"},c=Object.entries(l).map(([s,p])=>`${s}="${Mt(p)}"`).join(`
|
|
9
9
|
`);if(await promises.writeFile(o,c.trim()+`
|
|
10
|
-
`),console.log(`Successfully configured ${
|
|
10
|
+
`),console.log(`Successfully configured ${re} file`),a.appId)try{await Rt(a.appId),console.log(`Recorded the app ID in ${k}/${M}`);}catch(s){console.warn(`Failed to record the app ID in ${k}/${M}:`,s);}await Vt(),!t.token&&process.stdin.isTTY&&await Kt(),r&&console.log("The project now points to a different environment. Restart your dev server, and if you use an AI coding agent, start a new session."),!r&&l.MODELENCE_RUNTIME==="local"&&(console.log(`
|
|
11
11
|
Next step \u2014 run the app on this machine:
|
|
12
12
|
`),console.log(" npm install (if you haven't already)"),console.log(` npm run dev (starts the app)
|
|
13
|
-
`));}catch(o){console.error(`Setup failed: ${o instanceof Error?o.message:"Unknown error"}`),process.exit(1);}}var
|
|
13
|
+
`));}catch(o){console.error(`Setup failed: ${o instanceof Error?o.message:"Unknown error"}`),process.exit(1);}}var Gt=z$1.object({serverDir:z$1.string(),serverEntry:z$1.string(),postBuildCommand:z$1.string().optional()});async function $e(){let e=join(process.cwd(),"modelence.config.ts"),o=await createJiti(import.meta.url,{interopDefault:true,requireCache:false}).import(e);if(typeof o!="object")throw new Error("modelence.config.ts should export an object");return Gt.parse(o)}var Ie=null,se=null;function De(){if(!se)throw new Error("Configuration not loaded");return se}function E(){let{serverDir:e,serverEntry:t}=De();return join(e,t).replace(/\\/g,"/")}function _e(){return De().postBuildCommand}function K(e){let t=ae("build");return e?join(t,e).replace(/\\/g,"/"):t.replace(/\\/g,"/")}function S(e){return join(process.cwd(),e).replace(/\\/g,"/")}function ae(e){let t=S(".modelence");return e?join(t,e).replace(/\\/g,"/"):t.replace(/\\/g,"/")}async function b(){try{se=await $e();}catch(e){throw console.error(e),new Error("Unable to load modelence.config.ts")}try{let e=await Ne.readFile(join(process.cwd(),".modelence.env"),"utf-8");Ie=parse(e);}catch(e){if(e.code==="ENOENT")Ie={};else throw e}}async function Zt(){let e=_e();if(e){console.log("Running post-build command..."),execSync(e);return}await Qt(),await eo();}async function Qt(){console.log("Building client with Vite...");let e=await loadConfigFromFile({command:"build",mode:process.env.NODE_ENV||"production"}),t={build:{outDir:ce.resolve(process.cwd(),".modelence/build/client").replace(/\\/g,"/"),emptyOutDir:true,ssrManifest:true}};await build$1(mergeConfig(e?.config||{},t,true));}async function eo(){console.log("Building SSR bundle with Vite...");let e=await loadConfigFromFile({command:"build",mode:process.env.NODE_ENV||"production"}),o={build:{ssr:ce.resolve(process.cwd(),"src/client/index.tsx").replace(/\\/g,"/"),outDir:ce.resolve(process.cwd(),".modelence/build/ssr").replace(/\\/g,"/"),emptyOutDir:true,rollupOptions:{output:{format:"esm",entryFileNames:"index.mjs"}}}};await build$1(mergeConfig(e?.config||{},o,true));}async function to(){return console.log("Building server with tsup..."),new Promise(e=>{build({entry:[E()],format:"esm",sourcemap:true,minify:process.env.NODE_ENV==="production",outDir:".modelence/build",clean:true,watch:false,bundle:true,skipNodeModulesBundle:true,treeshake:true,platform:"node",outExtension:()=>({js:".mjs"}),onSuccess:async()=>{e(void 0);}});})}async function z(){console.log("Building Modelence project...");try{let e=K();await Ne.rm(e,{recursive:!0,force:!0}),await to(),await Zt(),console.log("Build completed successfully!");}catch(e){throw console.error(e),new Error("Build failed")}try{await Ne.access(ae());}catch{throw new Error("Could not find the .modelence directory. Looks like something went wrong during the build.")}}var Ue=promisify(execFile),je=200*1024*1024,lo=[".git","node_modules",".modelence/build",".modelence/tmp",".modelence/cache"],po=[/^\.modelence(\.[^/]+)?\.env$/];function Be(e){return /^\.env(?:\.|$)/.test(e)&&!/\.(example|sample|template)$/.test(e)}function uo(e){return e.split(/\r?\n/).some(t=>{if(/^\s*[#;]/.test(t))return false;let o=/https?:\/\/([^/\s]+)@/.exec(t)?.[1];if(o&&o.replace(/\$\{[A-Za-z_][A-Za-z0-9_]*\}/g,"").replace(/:/g,"")!=="")return true;let n=/^\s*[^=]*?(?:_authToken|_auth|_password|npmAuthToken|npmAuthIdent)["']?\s*[=:]\s*(.*?)\s*$/i.exec(t);if(!n)return false;let r=n[1].replace(/\s+#.*$/,"").replace(/^["']|["']$/g,"").trim();return r!==""&&!/^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(r)})}function H(e){return e.split(sep).join("/")}function mo(e){return pe(e)||Be(H(e).split("/").at(-1)??"")}function pe(e){let t=H(e),o=t.split("/");for(let r of lo)if(r.split("/").length===1){if(o.slice(0,-1).includes(r))return true}else if(t===r||t.startsWith(`${r}/`))return true;let n=o[o.length-1];return po.some(r=>r.test(n))}async function fo(e){try{let{stdout:t}=await Ue("git",["rev-parse","--is-inside-work-tree"],{cwd:e});return t.trim()==="true"}catch{return false}}async function Re(e,t){let{stdout:o}=await Ue("git",["ls-files",...t,"-z"],{cwd:e,maxBuffer:67108864});return o.split("\0").filter(n=>n.length>0)}async function Ve(e,t=""){let o=await promises.readdir(join(e,t),{withFileTypes:true}),n=[];for(let r of o){let i=t?`${t}/${r.name}`:r.name;r.isDirectory()?mo(`${i}/x`)||n.push(...await Ve(e,i)):(r.isFile()||r.isSymbolicLink())&&n.push(i);}return n}async function go(e,t){let o=join(e,t),n=await promises.readlink(o),r=resolve(dirname(o),n),i=relative(e,r);return i.startsWith("..")||isAbsolute(i)?null:{path:t,target:H(relative(dirname(o),r))||"."}}async function ho(e=process.cwd()){let t=await fo(e),o=new Set(t?await Re(e,["--cached"]):[]),n=t?[...o,...await Re(e,["--others","--exclude-standard"])]:await Ve(e),r={files:[],symlinks:[],usedGit:t,excludedFiles:[],skipped:[],committedEnvFiles:[]};for(let i of n){let a=i.split("/").at(-1)??"",l=Be(a);if(pe(i)||l&&!o.has(i)){r.excludedFiles.push(i);continue}let c;try{c=await promises.lstat(join(e,i));}catch{continue}if(c.isSymbolicLink()){if(pe(`${i}/x`)){r.excludedFiles.push(i);continue}let s=await go(e,i);s?r.symlinks.push(s):r.skipped.push({path:i,reason:"symlink to outside the project"});}else if(c.isDirectory())r.skipped.push({path:i,reason:"git submodule"});else if(c.isFile()){if([".npmrc",".yarnrc.yml",".yarnrc"].includes(a)&&uo(await promises.readFile(join(e,i),"utf8"))){r.excludedFiles.push(i);continue}r.files.push(i),l&&r.committedEnvFiles.push(i);}}return {...r,files:r.files.sort(),symlinks:r.symlinks.sort((i,a)=>i.path.localeCompare(a.path)),excludedFiles:r.excludedFiles.sort(),committedEnvFiles:r.committedEnvFiles.sort()}}async function Ke(e,t){let{files:o,symlinks:n,...r}=await ho(e);if(o.length===0)throw new Error("No files to upload");await promises.mkdir(join(t,".."),{recursive:true}),await promises.rm(t,{force:true});let i=createWriteStream(t),a=co("zip",{zlib:{level:6}}),l=new Promise((s,p)=>{i.on("close",s),i.on("error",p),a.on("error",p);});a.pipe(i);for(let s of o)a.file(join(e,s),{name:H(relative("",s))});for(let s of n)a.symlink(s.path,s.target,511);await Promise.all([a.finalize(),l]);let{size:c}=await promises.stat(t);if(c>je)throw await promises.rm(t,{force:true}),new Error(`Source is ${(c/1024/1024).toFixed(0)} MB compressed; the limit is ${je/1024/1024} MB. Add build output and large assets to .gitignore.`);return {...r,fileCount:o.length+n.length,sizeBytes:c}}var d="modelence.config.json",Eo=1,D="https://docs.modelence.com/deploy/setup",J=`Use ${D}.md to set up Modelence deployment for this project`;function Je(e){return `${e.replace(/\/$/,"")}/schema/${d}?version=${Eo}`}function G(e=process.cwd()){return join(e,d)}async function W(e=process.cwd()){let t;try{t=await promises.readFile(G(e),"utf8");}catch{return null}let o=[],n=parse$1(t,o,{allowTrailingComma:true,disallowComments:false});if(o.length>0)throw new Error(`${d} is not valid JSON: ${So(t,o[0])}`);if(!n||typeof n!="object"||Array.isArray(n))throw new Error(`${d} must contain a JSON object`);return n}function So(e,t){let o=e.slice(0,t.offset),n=o.split(`
|
|
14
14
|
`).length,r=t.offset-o.lastIndexOf(`
|
|
15
|
-
`);return `${printParseErrorCode(t.error)} at line ${n}, column ${r}`}async function
|
|
16
|
-
`);}function
|
|
17
|
-
`)}function
|
|
18
|
-
`)
|
|
15
|
+
`);return `${printParseErrorCode(t.error)} at line ${n}, column ${r}`}async function Ge(e,t=process.cwd()){await promises.writeFile(G(t),JSON.stringify(e,null,2)+`
|
|
16
|
+
`);}function We(e){let t=[],o=Object.entries(e.resources??{});for(let[n,r]of o){o.length>1&&t.push(` resource: ${n}`),t.push(` image: ${r.image??"default (node-22-slim)"}`),r.root&&r.root!=="."&&t.push(` root: ${r.root}`),t.push(...ze("build",r.build,"default (npm install)")),t.push(...ze("start",r.start,"(none)"));for(let i of r.static??[])t.push(` static: ${i.path} -> ${i.dir}/`);}for(let[n,r]of Object.entries(e.env??{}))t.push(` env: ${n} (${r.type??"text"})`);return t}function ze(e,t,o){let n=` ${`${e}:`.padEnd(8)} `;return t?t.commands.length===0?[`${n}(none)`]:t.commands.map(r=>`${n}${r}`):[`${n}${o}`]}async function Xe(e,t="."){if(typeof t!="string"||isAbsolute(t))throw new Error("root must be a relative directory inside the project.");let o=await promises.realpath(e),n=resolve(o,t);if(!qe(o,n))throw new Error("root must stay inside the project.");let r;try{r=await promises.realpath(n);}catch{throw new Error(`root "${t}" does not exist.`)}if(!qe(o,r)||!(await promises.stat(r)).isDirectory())throw new Error("root must be a directory inside the project.");return r}function qe(e,t){let o=relative(e,t);return o!==".."&&!o.startsWith(`..${sep}`)&&!isAbsolute(o)}var Ze=["$schema","resources","env"];async function Qe(e){let t=await W(e);if(!t)throw new Error(xo(e));Ao(t);for(let o of Object.values(t.resources??{}))o?.root!==void 0&&await Xe(e,o.root);console.log(`Build plan (${d}):`);for(let o of We(t))console.log(o);return t}function xo(e){return [`${d} not found in ${e}.`,"Modelence Cloud builds and runs your app exactly as this file describes (install, build and start commands, Node.js version, static directories).","Ask your coding agent to create it with this prompt:","",` ${J}`,"",`Reference: ${D}`].join(`
|
|
17
|
+
`)}function Ao(e){let t=Object.keys(e).filter(o=>!Ze.includes(o));if(t.length>0)throw new Error(`${d} has unknown key "${t[0]}" (allowed: ${Ze.join(", ")}).`);for(let o of ["resources","env"]){let n=e[o];if(n!==void 0&&(!n||typeof n!="object"||Array.isArray(n)))throw new Error(`${d}: "${o}" must be an object.`)}for(let[o,n]of Object.entries(e.resources??{})){if(!et(n))throw new Error(`${d}: "resources.${o}" must be an object.`);for(let r of ["build","start"])ko(n[r],`resources.${o}.${r}`);}}function ko(e,t){if(e!==void 0){if(!et(e)||!Array.isArray(e.commands))throw new Error(`${d}: "${t}" must be an object with a "commands" array, e.g. { "commands": ["npm ci"] }.`);e.commands.forEach((o,n)=>{if(typeof o!="string")throw new Error(`${d}: "${t}.commands.${n}" must be a string.`);if(o.trim()==="")throw new Error(`${d}: "${t}.commands.${n}" must not be empty.`)});}}function et(e){return !!e&&typeof e=="object"&&!Array.isArray(e)}var ue="json.schemaDownload.trustedDomains";async function Do(e,t,{create:o}){let n=`${new URL(t).origin}/`,r=join(e,".vscode"),i=join(r,"settings.json"),a=null;try{a=await promises.readFile(i,"utf8");}catch{}if(a===null)return !o&&!await _o(r)?"skipped":(await promises.mkdir(r,{recursive:true}),await promises.writeFile(i,JSON.stringify({[ue]:{[n]:true}},null,2)+`
|
|
18
|
+
`),"added");let l=[],c=parse$1(a,l,{allowTrailingComma:true});if(l.length>0||!c||typeof c!="object"||Array.isArray(c))return "skipped";if(c[ue]?.[n]===true)return "present";let s=modify(a,[ue,n],true,{formattingOptions:{insertSpaces:true,tabSize:2}});return await promises.writeFile(i,applyEdits(a,s)),"added"}async function _o(e){try{return await promises.access(e),!0}catch{return false}}function ot(e){if(typeof e!="string")return null;try{let t=new URL(e);return t.pathname===`/schema/${d}`?t.origin:null}catch{return null}}async function q(e,t,o){try{await Do(e,t,o)==="added"&&console.log(`Trusted ${new URL(t).origin} in .vscode/settings.json so VS Code can load the ${d} schema.`);}catch(n){console.warn("Could not update .vscode/settings.json:",n);}}async function nt(e,t){return t.prebuilt?{kind:"bundle",reason:"prebuilt-flag"}:await W(e)!==null?{kind:"source",reason:"spec-file"}:await Fo(e)?{kind:"bundle",reason:"modelence-dependency"}:{kind:"source",reason:"default"}}function rt(e){return e.reason!=="modelence-dependency"?null:`No ${d} found; this is a Modelence app, so it is built locally and uploaded as before. Add a ${d} to build it on Modelence Cloud instead.`}async function Fo(e){let t;try{t=await promises.readFile(join(e,"package.json"),"utf8");}catch{return false}let o;try{o=JSON.parse(t);}catch{return false}if(!o||typeof o!="object")return false;let n=o;return ["dependencies","devDependencies"].some(r=>{let i=n[r];return !!(i&&typeof i=="object"&&"modelence"in i)})}function it(e,t){if(e.app&&e.env)return {appAlias:e.app,envAlias:e.env};if(e.env&&t.deploy?.appAlias)return {appAlias:t.deploy.appAlias,envAlias:e.env};if(e.env&&t.appId)return {appId:t.appId,envAlias:e.env};if(e.app||e.env)throw new Error("Pass both --app and --env, or neither to pick the target in the browser.");return t.deploy?.environmentId?{environmentId:t.deploy.environmentId}:null}function st(e,t){if("environmentId"in e){let o=t.deploy;return `${o?.environmentId===e.environmentId?`${o.appAlias}/${o.envAlias}`:e.environmentId} (saved in .modelence/project.json)`}return "appAlias"in e?`${e.appAlias}/${e.envAlias}`:e.envAlias}function at(e,t){let o=t.deploy;return !o||"environmentId"in e?false:"appAlias"in e&&e.appAlias!==o.appAlias?true:e.envAlias!==o.envAlias}function Y(){return !process.env.CI&&!!process.stdin.isTTY}async function ct(e){let t=createInterface({input:process.stdin,output:process.stdout}),o=await new Promise(n=>t.question(`${e} (y/N) `,n));return t.close(),o.trim().toLowerCase()==="y"}function X(e,t,{deployAgain:o=false}={}){if(!e||e.length===0)return null;let n=e.length===1,r=t?` Set ${n?"it":"them"} at ${t}`:"";return `${e.join(", ")} ${n?"is":"are"} declared in ${d} but ${n?"has":"have"} no value in this environment.`+(r?r+(o?", then deploy again.":""):"")}var lt=3e3,Mo=30*60*1e3,jo=10*60*1e3;async function pt(e,t,o){let n=Date.now()+jo,r=false;for(;Date.now()<n;){let i;try{({status:i}=await f(e,"/api/environment/status",{token:t,query:{environmentId:o}}));}catch(a){if(a instanceof y&&a.status===404)return false;throw a}if(i==="ready")return r;if(i==="failed")throw new Error("The environment failed to provision; check it in the dashboard.");r||(console.log("Waiting for the environment to finish provisioning..."),r=true),await new Promise(a=>setTimeout(a,lt));}throw new Error("Timed out waiting for the environment to be ready.")}async function dt(e,t,o,n){let r=Date.now()+Mo,i="",a="",l=null,c=false;for(;Date.now()<r;){let s;try{s=await f(e.host,"/api/deploy/status",{token:e.token,query:{environmentId:o,buildId:n,...l?{logCursor:l}:{}}});}catch(p){if(!R(p)||c)throw p;c=true,await t();continue}for(let p of s.logs)process.stdout.write(` \u2502 ${p.replace(/\n$/,"")}
|
|
19
|
+
`);if(l=s.logCursor??l,s.status!==i){i=s.status;let p=Ro(s);p&&p!==a&&(a=p,console.log(p));}if(s.status==="deploy-completed"){s.siteUrl&&console.log(`Live at ${s.siteUrl}`);return}if(s.status==="build-failed"||s.status==="deploy-failed"){for(let u of s.errors)console.error(` ${u}`);if(s.containerLogs&&s.containerLogs.length>0){console.error("Container output:");for(let u of s.containerLogs)console.error(` \u2502 ${u.replace(/\n$/,"")}`);}let p=X(s.missingEnvVars,s.configUrl,{deployAgain:true});p&&console.error(p),process.exitCode=1;return}await new Promise(p=>setTimeout(p,lt));}console.error("Timed out waiting for the deployment; check the dashboard for its status."),process.exitCode=1;}function Ro(e){switch(e.status){case "build-pending":return "Building image...";case "deploy-pending":case "deploying":return "Image built. Deploying containers...";case "rolling-out":return "Rolling out new containers...";case "deploy-completed":return "Deployed successfully.";case "build-failed":return "Build failed.";case "deploy-failed":return "Deployment failed.";default:return null}}async function me({session:e,target:t,kind:o,archivePath:n,spec:r}){let{host:i,token:a}=e,l=()=>f(i,"/api/upload-bundle",{method:"POST",token:a,body:{...t,kind:o}}),c=await l();if(!c.environmentId)throw new Error("Modelence Cloud is too old for this CLI version (no environment id from /api/upload-bundle). Try again later, or deploy with modelence@0.25.");await pt(i,a,c.environmentId)&&(c=await l()),console.log(`Uploading to ${c.appAlias}/${c.envAlias}...`);let s=await openAsBlob(n,{type:"application/zip"}),p=await fetch(c.uploadUrl,{method:"PUT",body:s,headers:{"Content-Type":"application/zip"}});if(!p.ok)throw new Error(`Failed to upload: ${await Bo(p)}`);let u=await f(i,"/api/deploy",{method:"POST",token:a,body:{environmentId:c.environmentId,bundleName:c.bundleName,kind:o,spec:r}});console.log(`Deployment started: ${u.deploymentUrl}`);let C=X(u.missingEnvVars,u.configUrl);return C&&console.warn(`Warning: ${C}`),{environmentId:u.environmentId,buildId:u.buildId}}async function Bo(e){let t=await e.text().catch(()=>""),o=t.match(/<Code>([^<]+)<\/Code>/)?.[1],n=t.match(/<Message>([^<]+)<\/Message>/)?.[1],r=e.statusText||`HTTP ${e.status}`;return o?`${r} (${o}${n?`: ${n}`:""})`:r}async function gt(e){let t=process.cwd(),o=await Ce(e.host,t),n=await nt(t,e),r=n.kind,i=rt(n);i&&console.log(i);let a=Pe(await T(t),o),l=it(e,a),c=await be(o);if((!c||!l)&&!Y())throw new Error(zo(!!c,!!l));await Ho(l,a,e.yes);let s,p=join(t,".modelence","tmp",`${r}.zip`);if(r==="bundle")await b(),await z(),await Go(p);else {s=await Qe(t);let u=ot(s.$schema);u&&await q(t,u,{create:false}),Jo(await Ke(t,p));}try{if(!c||!l){let m=await A(o,{pick:l?void 0:"deploy",purpose:"deploy",appId:a.appId});c=m.token,await te(o,m.token,m.expiresAt),m.target&&(l={environmentId:m.target.environmentId},await oe(m.target,o));}if(!l)throw new Error("No deploy target selected. Run again and pick an environment in the browser, or pass --app and --env.");let u={host:o,token:c},C=async()=>{if(await L(o),!Y())throw new Error("Modelence Cloud rejected the token (expired or revoked), and nobody is at the terminal to sign in again. Set a fresh MODELENCE_TOKEN. A deployment that already started keeps running; check the dashboard.");console.log("Your saved login has expired; please sign in again.");let m=await A(o,{pick:l?void 0:"deploy",purpose:"deploy",appId:a.appId});await te(o,m.token,m.expiresAt),m.target&&(l={environmentId:m.target.environmentId},await oe(m.target,o)),u.token=m.token;},x;try{x=await me({session:u,target:l,kind:r,archivePath:p,spec:s});}catch(m){if(!R(m))throw m;await C(),x=await me({session:u,target:l,kind:r,archivePath:p,spec:s});}x.buildId&&await dt(u,C,x.environmentId,x.buildId);}finally{await promises.rm(p,{force:true});}}function zo(e,t){return `Nobody is at the terminal to sign in or pick a target in the browser (CI or a non-interactive shell). To deploy from here, ${[t?null:"pass --app and --env",e?null:"set MODELENCE_TOKEN"].filter(Boolean).join(" and ")}.`}async function Ho(e,t,o){if(!e)return;let n=st(e,t);if(console.log(`Deploying to ${n}`),o||!at(e,t)||!Y())return;let r=`${t.deploy?.appAlias}/${t.deploy?.envAlias}`;if(!await ct(`This project normally deploys to ${r}. Deploy to ${n} instead?`))throw new Error("Cancelled.")}var ut=10;function mt(e){let t=e.slice(0,ut).join(", "),o=e.length-ut;return o>0?`${t} and ${o} more`:t}function Jo(e){console.log(`Packed ${e.fileCount} files (${ht(e.sizeBytes)})`+(e.usedGit?" from git":"; not a git repository, so only default exclusions applied")),e.excludedFiles.length>0&&console.log(`Not uploaded (local, generated or credentials; store secrets in the target environment): ${mt(e.excludedFiles)}`),e.committedEnvFiles.length>0&&console.log(`Uploaded environment files committed to git: ${mt(e.committedEnvFiles)}`);for(let{path:t,reason:o}of e.skipped)console.warn(`Warning: ${t} is not uploaded (${o}).`);}function ht(e){return `${(e/1024/1024).toFixed(2)} MB`}async function Go(e){await promises.rm(e,{force:true}),console.log("Creating deployment bundle..."),await promises.mkdir(join(e,".."),{recursive:true});let t=createWriteStream(e),o=co("zip",{zlib:{level:9}}),n=new Promise((l,c)=>{t.on("close",l),t.on("error",c),o.on("error",c);});o.pipe(t);let r=["package.json","package-lock.json","next.config.js","next.config.ts","modelence.config.ts"],i=["public","server","scripts",join(".modelence","build"),".next"];for(let l of r)await ft(S(l))&&o.file(S(l),{name:l});for(let l of i)await ft(S(l))&&o.directory(S(l),l);await o.finalize(),await n;let a=await promises.stat(e);console.log(`Deployment bundle created (${ht(a.size)})`);}async function ft(e){try{return await promises.access(e),!0}catch{return false}}function yt(e={}){console.log("Starting Modelence dev server...");let t=E(),o=ce.resolve("./node_modules/.bin/tsx");execSync(`"${o}" watch --ignore "vite.config.ts.timestamp-*" "${t}"`,{stdio:"inherit",cwd:process.cwd(),env:{...process.env,NODE_ENV:"development",...e.takeover?{MODELENCE_TAKEOVER:"1"}:{}}});}function vt(){console.log("Starting Modelence production server...");let e=E(),t=ce.basename(e,ce.extname(e)),o=K(`${t}.mjs`);execSync(`node "${o}"`,{stdio:"inherit",cwd:process.cwd(),env:{...process.env,NODE_ENV:"production"}});}async function Et(e){let t=e.host?w(e.host):void 0,o=await ye(t);await Promise.all(o.map(n=>Xo(n.host,n.token))),await L(t),console.log(t?`Removed the saved login for ${t}.`:`Removed saved logins (${O()}).`);}async function Xo(e,t){try{await f(e,"/api/cli/logout",{method:"POST",token:t});}catch{}}var Qo="https://cloud.modelence.com";async function St(e){let t=process.cwd(),o=G(t);if(!e.force&&await en(o))throw new Error(`${d} already exists; pass --force to overwrite it.`);let n=e.host??Qo,r={$schema:Je(n),resources:{app:{type:"service",image:"node-22-slim",build:{commands:["npm ci"]},static:[]}},env:{}};await Ge(r,t),await q(t,n,{create:true}),console.log(`Wrote a ${d} template.`),console.log("Ask your coding agent to fill it in with this prompt:"),console.log(""),console.log(` ${J}`),console.log(""),console.log(`Reference: ${D}`),console.log(`Once ${d} describes your app, run \`npx modelence@latest deploy\`.`);}async function en(e){try{return await promises.access(e),!0}catch{return false}}var an=fileURLToPath(import.meta.url),cn=dirname(an),ln=JSON.parse(readFileSync(join(cn,"../../package.json"),"utf-8")),h=new Command().name("modelence").description("Modelence CLI tool").version(ln.version);h.command("setup").description("Setup Modelence environment variables").option("-t, --token <token>","Modelence setup token (omit to authorize in the browser)").option("-h, --host <host>","Modelence host","https://cloud.modelence.com").action(async e=>{await Te(e);});h.command("build").description("Build the application").action(async()=>{await b(),await z();});h.command("deploy").description("Deploy the project described by modelence.config.json to Modelence Cloud (picks the target in the browser on first run)").option("-a, --app <app>","Application alias").option("-e, --env <env>","Environment alias").option("-h, --host <host>","Modelence host").option("--prebuilt","Build locally and upload the .modelence/build bundle (Modelence apps only)").option("-y, --yes","Deploy to the given --app/--env without asking, even if it is not the saved target").action(async e=>{try{await gt(e);}catch(t){console.error(`Deploy failed: ${t instanceof Error?t.message:String(t)}`),process.exit(1);}});h.command("init").description("Create a modelence.config.json template for this project").option("--force","Overwrite an existing modelence.config.json").option("-h, --host <host>","Modelence host used for the schema URL").action(async e=>{try{await St(e);}catch(t){console.error(`Init failed: ${t instanceof Error?t.message:String(t)}`),process.exit(1);}});h.command("logout").description("Forget the saved Modelence Cloud login").option("-h, --host <host>","Only forget the login for this host").action(async e=>{await Et(e);});h.command("dev").description("Start development server").option("--takeover","Disconnect any instance currently holding the environment and connect this one").action(async e=>{await b(),yt(e);});h.command("start").description("Start production server").action(async()=>{await b(),vt();});h.parse(process.argv);//# sourceMappingURL=modelence.js.map
|
|
19
20
|
//# sourceMappingURL=modelence.js.map
|