@nano-edge/cli
Version:
A simple CLI used to deploy an app to NanoEdge
4 lines (3 loc) • 3.89 kB
JavaScript
import x from"yargs";import{hideBin as $}from"yargs/helpers";import{existsSync as u,mkdirSync as D,readdirSync as S,readFileSync as k,writeFileSync as O}from"node:fs";import{create as z}from"tar";var g="@nano-edge/cli",v="1.11.1";import{z as m}from"zod";function d(e,o){return{validate(i){let t=o.safeParse(i);if(t.error){let{formErrors:r,fieldErrors:f}=t.error.flatten(),p=[];if(r.length)for(let c of r)p.push(`invalid input '${e}': ${c}`);if(Object.keys(f))for(let[c,y]of Object.entries(f))if(y)for(let w of y)p.push(`invalid input '${e}.${c}': ${w}`);else p.push(`invalid input '${e}.${c}'`);throw new Error(p.join(`
`))}return t.data}}}import{relative as _}from"node:path";import{initClient as T,tsRestFetchApi as j}from"@ts-rest/core";import{initContract as A}from"@ts-rest/core";import{z as n}from"zod";import{jwtDecode as N}from"jwt-decode";var b=n.string().regex(/^[a-z]{1,12}$/),s=n.string().jwt().transform(e=>({raw:e,payload:N(e)})).pipe(n.object({raw:n.string().jwt(),payload:n.object({iss:n.string(),deployment:b})})),l=A().router({putDeployment:{method:"PUT",path:"/deployments/:deployment",pathParams:n.object({deployment:b}),body:n.any(),responses:{200:n.string()}}},{baseHeaders:n.object({authorization:s}),strictStatusCodes:!0});l.putDeployment.contentType="application/gzip";function E(e){let o=s.parse(e),i=T(l,{baseUrl:`${o.payload.iss}/api`,baseHeaders:{authorization:o.raw},throwOnUnknownStatus:!0,jsonQuery:!0,validateResponse:!0,api:t=>(t.route.contentType&&t.route.contentType!=="application/json"&&(t.body=t.rawBody,t.headers["content-type"]=t.route.contentType),t.body?.[Symbol.asyncIterator]&&(t.fetchOptions={...t.fetchOptions,duplex:"half"}),j(t))});return{putDeployment(t){return i.putDeployment({params:{deployment:o.payload.deployment},body:t})}}}var a=x($(process.argv)).scriptName(`npx ${g}`).version(v).alias("v","version").help().alias("h","help").epilogue("Note: All options can also be set using environment variables by adding the prefix NANO_EDGE_ to the CONSTANT_CASE version of the option name. Alternatively, options can be defined in a configuration file (default: nano-edge.config.json). You can specify a different config file using the --config option.").recommendCommands().demandCommand().strict();a.wrap(a.terminalWidth());a.env("NANO_EDGE");a.config("config","Path to JSON config file",e=>{let o=k(e,"utf-8");try{return JSON.parse(o)}catch(i){throw new Error(`Failed to parse config ${_(".",e)}: ${i.toString()}`)}}).default("config",u("nano-edge.config.json")?"nano-edge.config.json":void 0).alias("c","config");a.command({command:"deploy",describe:"deploy a pre-built application",builder:e=>e.example("$0 deploy --env.GREETING=hi","provide an environment variable").example("$0 deploy --root=out","assumes that the built application is in the 'out' directory").example("NANO_EDGE_AUTH_TOKEN=xxx $0 deploy","provide the auth-token via environment variable").option("auth-token",{describe:"Token used to identify and authenticate against the nano-edge instance. Recommendation: provide the token via environment variable 'NANO_EDGE_AUTH_TOKEN'.",type:"string",demandOption:!0,coerce:o=>d("auth-token",s).validate(o)}).option("env",{describe:"An object of environment variables deployed alongside the application.",coerce:o=>d("env",m.record(m.string(),m.coerce.string())).validate(o)}).option("root",{describe:"The root directory containing the pre-built application.",type:"string",default:"dist",coerce:o=>d("root",m.string().refine(u,{message:`Directory '${o}' does not exist`})).validate(o)}),async handler(e){if(e.env){let r=`${e.root}/functions`;u(r)||D(r,{recursive:!0}),O(`${r}/env.json`,JSON.stringify(e.env))}let o=z({gzip:!0,cwd:e.root,follow:!0,portable:!0},S(e.root)),t=await E(e.authToken.raw).putDeployment(o);if(t.status===200)console.log(t.body);else throw new Error(t.body)}});await a.parse();