@arkenv/cli 0.2.2 → 0.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +30 -14
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -84,7 +84,7 @@ ${o}${e}
|
|
|
84
84
|
`}case`submit`:{let e=o?` ${(0,a.styleText)(`dim`,o)}`:``;return`${n}${t?(0,a.styleText)(`gray`,z):``}${e}`}case`cancel`:{let e=o?` ${(0,a.styleText)([`strikethrough`,`dim`],o)}`:``,r=t?(0,a.styleText)(`gray`,z):``;return`${n}${r}${e}${o.trim()?`
|
|
85
85
|
${r}`:``}`}default:return`${n}${t?`${(0,a.styleText)(`cyan`,z)} `:``}${i}
|
|
86
86
|
${t?(0,a.styleText)(`cyan`,B):``}
|
|
87
|
-
`}}}).prompt();var tt=class{info(e){process.stdout.write(`${y.default.blue(`ℹ ${e}`)}\n`)}warn(e){process.stderr.write(`${y.default.yellow(`⚠ ${e}`)}\n`)}error(e){process.stderr.write(`${y.default.red(`✘ ${e}`)}\n`)}success(e){process.stdout.write(`${y.default.green(`✔ ${e}`)}\n`)}step(e){process.stdout.write(`○ ${e}\n`)}note(e,t){Xe(e,t)}log(e){process.stdout.write(`${e}\n`)}spinner(){return Qe()}json(e){process.stdout.write(`${JSON.stringify(e,null,2)}\n`)}cancel(e){process.stderr.write(`${y.default.red(`✘ ${e}`)}\n`)}fatal(e,t){if(process.stderr.write(`${y.default.red(`✘ ${e}`)}\n`),t){let e=`${y.default.red(t instanceof Error?t.stack??String(t):String(t))}\n`;process.stderr.write(e)}throw t instanceof Error?t:Error(e)}finish(e,t){qe(e)}async flush(){return new Promise(e=>{process.stderr.write(``,()=>e())})}},nt=class{constructor(e){this.options=e,this.originalStdoutWrite=process.stdout.write,e.isJson?this.reporter=new b:e.isQuiet?this.reporter=new x:this.reporter=new tt}info(e){this.reporter.info(e)}warn(e){this.reporter.warn(e)}error(e){this.reporter.error(e)}success(e){this.reporter.success(e)}step(e){this.reporter.step(e)}note(e,t){this.reporter.note(e,t)}log(e){this.reporter.log(e)}spinner(){return this.reporter.spinner()}json(e){this.reporter.json(e)}get stdio(){return this.options.isJson?[process.stdin,process.stderr,process.stderr]:`inherit`}interactiveStdout(e){!this.options.isJson||this.options.isYes||(e?process.stdout.write=process.stderr.write.bind(process.stderr):process.stdout.write=this.originalStdoutWrite)}cancel(e){this.reporter.cancel(e)}fatal(e,t){this.reporter.fatal(e,t)}finish(e,t){this.reporter.finish(e,t)}async flush(){await this.reporter.flush()}};async function rt(e=process.cwd(),t){if(t?.compilerOptions?.types){let e=t.compilerOptions.types;if(e.includes(`vite`)||e.includes(`vite/client`))return`vite`}try{let t=r.default.join(e,`package.json`),i=await n.default.readFile(t,`utf-8`),a=JSON.parse(i);if({...a.dependencies,...a.devDependencies}.vite)return`vite`}catch{}try{return await n.default.access(r.default.join(e,`vite.config.ts`)),`vite`}catch{}try{return await n.default.access(r.default.join(e,`vite.config.js`)),`vite`}catch{}return(await it(e,t)).length>0?`bun-fullstack`:`vanilla`}async function it(e=process.cwd(),t){let i=[];try{let t=r.default.join(e,`bunfig.toml`),a=await n.default.readFile(t,`utf-8`);(a.includes(`[serve]`)||a.includes(`[serve.static]`))&&i.push(`serve`),a.includes(`[build]`)&&i.push(`build`)}catch{}if(i.includes(`serve`)&&i.includes(`build`))return i;let{walk:a}=await Promise.resolve().then(()=>st),o=await a(e),s=i.includes(`serve`),c=i.includes(`build`);for(let e of o)try{let t=await n.default.readFile(e,`utf-8`);if(!s&&(t.includes(`Bun.serve`)||t.includes(`serve(`))&&(/from\s+['"]bun['"]/.test(t)||t.includes(`Bun.serve`))&&(s=!0,i.push(`serve`)),!c&&(t.includes(`Bun.build`)||t.includes(`build(`))&&(/from\s+['"]bun['"]/.test(t)||t.includes(`Bun.build`))&&(c=!0,i.push(`build`)),s&&c)break}catch{}return i}async function at(e=process.cwd(),t){let i=process.env.npm_config_user_agent?.toString()||``;if(i.includes(`pnpm`))return`pnpm`;if(i.includes(`yarn`))return`yarn`;if(i.includes(`bun`))return`bun`;if(i.includes(`npm`))return`npm`;let a=t?.path?r.default.dirname(t.path):e;for(;a!==r.default.parse(a).root;){try{let e=r.default.join(a,`package.json`),t=await n.default.readFile(e,`utf-8`),i=JSON.parse(t);if(i.packageManager){if(i.packageManager.startsWith(`pnpm`))return`pnpm`;if(i.packageManager.startsWith(`yarn`))return`yarn`;if(i.packageManager.startsWith(`bun`))return`bun`}}catch{}let e=[];try{e=await n.default.readdir(a)}catch{}if(e.includes(`pnpm-lock.yaml`))return`pnpm`;if(e.includes(`yarn.lock`))return`yarn`;if(e.includes(`bun.lockb`))return`bun`;if(e.includes(`package-lock.json`))return`npm`;a=r.default.dirname(a)}return`npm`}async function ot(e=process.cwd(),t){let i=t;if(!i){let{findTsConfig:t,loadTsConfig:n}=await Promise.resolve().then(()=>pt),r=await t(e);r&&(i=await n(r))}if(i?.compilerOptions?.rootDir){let t=i.compilerOptions.rootDir,n=r.default.relative(e,t);return n&&n!==`.`&&!n.startsWith(`..`)&&!r.default.isAbsolute(n)?`./${n}/env.ts`:`./env.ts`}try{return await n.default.access(r.default.join(e,`src`)),`./src/env.ts`}catch{return`./env.ts`}}var st=e.n({getEnvExampleKeys:()=>ft,parseEnvExample:()=>lt,resolveImportPaths:()=>ut,scanProjectEnvKeys:()=>dt,walk:()=>ct});async function ct(e,t=[]){try{let i=await n.default.readdir(e,{withFileTypes:!0});for(let n of i)if(n.isDirectory()){let i=n.name;if(i===`node_modules`||i===`dist`||i===`build`||i===`.git`||i===`.turbo`||i===`scratch`)continue;await ct(r.default.join(e,i),t)}else n.isFile()&&/\.(ts|tsx|js|jsx)$/.test(n.name)&&!n.name.endsWith(`.d.ts`)&&t.push(r.default.join(e,n.name))}catch{}return t}function lt(e){let t=[],n=e.split(/\r?\n/);for(let e of n){let n=e.trim();if(!n||n.startsWith(`#`))continue;let r=n.match(/^([A-Z_][A-Z0-9_]*)\s*=/i);r?.[1]&&t.push(r[1])}return Array.from(new Set(t))}function ut(e,t,n){if(e.startsWith(`.`))return[r.default.resolve(r.default.dirname(n),e)];if(r.default.isAbsolute(e))return[e];let i=t.compilerOptions||{},a=i.baseUrl||r.default.dirname(t.path),o=i.paths||{},s=[];for(let[e,t]of Object.entries(o)){let n=e.endsWith(`*`),r=e.replace(/\*$/,``);s.push({cleanPattern:r,targets:Array.isArray(t)?t:[t],hadStar:n})}s.sort((e,t)=>t.cleanPattern.length-e.cleanPattern.length);for(let{cleanPattern:t,targets:n,hadStar:i}of s)if(i&&e.startsWith(t)||!i&&e===t){let i=e.slice(t.length);return n.map(e=>{let t=`${e.replace(/\*$/,``)}${i}`;return r.default.resolve(a,t)})}return i.baseUrl?[r.default.resolve(a,e)]:[]}async function dt(e,t,i){let a=[],o=await ct(e),s=i?i.replace(/\.(ts|js|tsx|jsx)$/,``):null;for(let e of o)try{let i=await n.default.readFile(e,`utf-8`),o=i.matchAll(/process\.env\.([A-Z_][A-Z0-9_]*)/g);for(let e of o)e[1]&&a.push(e[1]);let c=i.matchAll(/import\.meta\.env\.([A-Z_][A-Z0-9_]*)/g);for(let e of c)e[1]&&a.push(e[1]);if(s){let n=i.matchAll(/import\s+[^;]*from\s+['"]([^'"]+)['"]/g);for(let o of n){let n=o[1],c=[];if(t?c=ut(n,t,e):n.startsWith(`.`)&&(c=[r.default.resolve(r.default.dirname(e),n)]),c.some(e=>e.replace(/\.(ts|js|tsx|jsx)$/,``)===s)){let e=i.matchAll(/\benv\.([A-Z_][A-Z0-9_]*)/g);for(let t of e)t[1]&&a.push(t[1])}}}}catch{}return Array.from(new Set(a))}async function ft(e=process.cwd(),t,i){let a=r.default.join(e,`.env.example`);try{let e=lt(await n.default.readFile(a,`utf-8`));if(e.length>0)return{keys:e,source:`.env.example`}}catch{}let o=await dt(e,t,i);return o.length>0?{keys:o,source:`project`}:null}var pt=e.n({checkTsConfig:()=>ht,findTsConfig:()=>q,loadTsConfig:()=>J});const mt=(0,l.createRequire)(require(`url`).pathToFileURL(__filename).href).resolve;async function q(e=process.cwd()){let t=[`tsconfig.app.json`,`tsconfig.json`,`tsconfig.base.json`,`tsconfig.node.json`],i=e;for(;i!==r.default.parse(i).root;){for(let e of t){let t=r.default.join(i,e);try{return await n.default.access(t),t}catch{}}i=r.default.dirname(i)}return null}async function J(e,t=new Set){let i=r.default.resolve(e);if(t.has(i))throw Error(`Circular extends dependency detected in tsconfig.json: ${i}`);t.add(i);let a=``;try{a=await n.default.readFile(e,`utf-8`)}catch{return{path:e,compilerOptions:{}}}let o=(0,u.parse)(a)||{},s=o.compilerOptions||{},c={};if(o.extends){let n=Array.isArray(o.extends)?o.extends:[o.extends];for(let i of n){let n;if(i.startsWith(`.`)||r.default.isAbsolute(i))n=r.default.resolve(r.default.dirname(e),i);else try{n=mt(i,{paths:[r.default.dirname(e)]})}catch{n=r.default.resolve(r.default.dirname(e),`node_modules`,i)}let a={...(await J(n,t)).compilerOptions};a.baseUrl&&=r.default.resolve(r.default.dirname(n),a.baseUrl),a.rootDir&&=r.default.resolve(r.default.dirname(n),a.rootDir),c={...c,...a}}}let l={...s};return l.baseUrl&&=r.default.resolve(r.default.dirname(e),l.baseUrl),l.rootDir&&=r.default.resolve(r.default.dirname(e),l.rootDir),c={...c,...l},{...o,path:e,compilerOptions:c}}async function ht(e=process.cwd()){let t=await q(e);if(!t)return{status:`not_found`};let n=r.default.basename(t);try{let e=await J(t);return e?.compilerOptions?.strict===!0?{status:`strict`,file:n,parsed:e}:{status:`not_strict`,file:n,parsed:e}}catch{return{status:`not_found`}}}function gt(e,t){let n=e.replace(/^v/,``).split(`.`).map(Number),r=t.replace(/^v/,``).split(`.`).map(Number);for(let e=0;e<3;e++){let t=n[e]||0,i=r[e]||0;if(t>i)return 1;if(t<i)return-1}return 0}function _t(e){let t=e.trim().match(/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?/);return t?[t[1],t[2]??`0`,t[3]??`0`].join(`.`):null}function vt(e,t){let n=e.trim(),r=n.match(/^[\^~]?\s*(v?\d+(?:\.\d+){0,2})$/);if(r){let e=_t(r[1]);return e!==null&>(e,t)>=0}let i=n.match(/(?:>=|>|<=|<|=)\s*v?\d+(?:\.\d+){0,2}/g);return!i||i.join(` `)!==n.replace(/\s+/g,` `)?!1:i.some(e=>{let n=e.match(/^(>=|>|<=|<|=)\s*(v?\d+(?:\.\d+){0,2})$/);if(!n)return!1;let[,r,i]=n,a=_t(i);return a&&(r===`>=`||r===`>`||r===`=`)?gt(a,t)>=0:!1})}async function yt(e=process.cwd()){let t=[],i=process.version,a=`22.0.0`;gt(i,a)===-1?t.push({status:`fail`,requirement:`Node.js Version`,message:`Node.js version must be >= ${a}.`,current:i,expected:`>= ${a}`}):t.push({status:`pass`,requirement:`Node.js Version`,message:`Node.js version is compatible.`});let o=null;try{let i=r.default.join(e,`package.json`),a=await n.default.readFile(i,`utf-8`);o=JSON.parse(a),t.push({status:`pass`,requirement:`package.json`,message:`package.json found.`})}catch{t.push({status:`warn`,requirement:`package.json`,message:`package.json not found in the current directory.`})}if(o){let e={...o.dependencies,...o.devDependencies}.typescript,n=`5.1.0`;e?vt(e,n)?t.push({status:`pass`,requirement:`TypeScript Version`,message:`TypeScript version is compatible.`}):t.push({status:`fail`,requirement:`TypeScript Version`,message:`TypeScript version should be >= ${n}.`,current:e,expected:`>= ${n}`}):t.push({status:`warn`,requirement:`TypeScript Version`,message:`TypeScript not found in package.json dependencies.`})}let s=await ht(e);if(s.status===`not_found`)t.push({status:`warn`,requirement:`tsconfig.json`,message:`tsconfig.json not found.`});else{let e=s.parsed.compilerOptions||{};e.strict===!0?t.push({status:`pass`,requirement:`TypeScript Strict Mode`,message:`Strict mode is enabled.`}):t.push({status:`fail`,requirement:`TypeScript Strict Mode`,message:`Strict mode must be enabled.`,current:`false`,expected:`true`});let n=e.moduleResolution?.toLowerCase(),r=e.module?.toLowerCase();[`bundler`,`node16`,`nodenext`].includes(n||``)||!n&&(r===`node16`||r===`nodenext`)?t.push({status:`pass`,requirement:`TypeScript moduleResolution`,message:`moduleResolution is set to ${n||`implicit`}.`}):t.push({status:`fail`,requirement:`TypeScript moduleResolution`,message:`moduleResolution must be set to 'bundler', 'node16', or 'nodenext'.`,current:n||`default`,expected:`bundler, node16, or nodenext`})}return t}var bt=class{async isEmptyDirectory(e=process.cwd()){try{return(await n.default.readdir(e)).length===0}catch{return!1}}async hasPackageJson(e=process.cwd()){try{return await n.default.access(r.default.join(e,`package.json`)),!0}catch{return!1}}async findTsConfig(e=process.cwd()){return q(e)}async loadTsConfig(e,t=new Set){return J(e,t)}async getEnvExampleKeys(e=process.cwd(),t,n){return ft(e,t,n)}async suggestDefaultEnvPath(e=process.cwd(),t){return ot(e,t)}async checkTsConfig(e=process.cwd()){return ht(e)}async checkRequirements(e=process.cwd()){return yt(e)}async detectFramework(e=process.cwd(),t){return rt(e,t)}async detectBunFeatures(e=process.cwd(),t){return it(e,t)}async detectPackageManager(e=process.cwd(),t){return at(e,t)}};const Y=e=>y.default.cyan(e),xt=y.default.blue(`⛯`);function St(e){try{let t=(0,f.parseModule)(e.code),n=e.code,r=t.exports.default;if(r&&typeof r==`object`&&`$type`in r&&r.$type===`function-call`){let e=r;if((e.$callee||JSON.stringify(r))===`defineConfig`&&e.$args){let t=e.$args[0];if(t&&typeof t==`object`&&`$type`in t&&(t.$type===`arrow-function-expression`||t.$type===`function-expression`))return{success:!1,updated:!1,error:`The 'defineConfig' callback form is currently not supported for automatic mutation. Please add the plugin manually.`};r=t}}if(!r||typeof r!=`object`||typeof r==`object`&&`$type`in r)return{success:!1,updated:!1,error:`Could not find default export object in Vite config`};if(r.plugins||=[],Array.isArray(r.plugins))if(!/\barkenv(?:Vite)?Plugin\b/.test(n))t.imports.$add({from:`@arkenv/vite-plugin`,local:`arkenvVitePlugin`,imported:`default`}),e.envImportPath&&t.imports.$add({from:e.envImportPath,imported:`Env`}),r.plugins.push(`__ARK_PLUGIN_PLACEHOLDER__`);else return{success:!0,updated:!1};else return{success:!1,updated:!1,error:`The 'plugins' property in your Vite config is not an array.`};let i=(0,f.generateCode)(t,{format:(0,f.detectCodeFormat)(n)}).code,a=e.envImportPath?`arkenvVitePlugin(Env)`:`arkenvVitePlugin()`;return i=i.replace(/['"]__ARK_PLUGIN_PLACEHOLDER__['"]/g,a),{success:!0,updated:!0,code:i}}catch(e){return{success:!1,updated:!1,error:`Failed to parse Vite config: ${e instanceof Error?e.message:String(e)}`}}}async function Ct(e=process.cwd()){for(let t of[`vite.config.ts`,`vite.config.js`,`vite.config.mts`,`vite.config.mjs`]){let i=r.default.resolve(e,t);try{return await n.default.access(i),i}catch{}}return null}async function wt(e=process.cwd()){for(let t of[`bunfig.toml`,`bun.setup.ts`,`bun.setup.js`]){let i=r.default.resolve(e,t);try{return await n.default.access(i),i}catch{}}return null}async function Tt(e,t,n){try{let r=St({code:await e.readFile(t),envImportPath:n});return r.success&&r.updated&&r.code&&await e.writeFile(t,r.code),r.success?r.updated===void 0?{success:!0}:{success:!0,updated:r.updated}:{success:!1,error:r.error}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async function Et(e,t){if(!t||t.length===0)return{success:!0,instructions:i.default`
|
|
87
|
+
`}}}).prompt();var tt=class{info(e){process.stdout.write(`${y.default.blue(`ℹ ${e}`)}\n`)}warn(e){process.stderr.write(`${y.default.yellow(`⚠ ${e}`)}\n`)}error(e){process.stderr.write(`${y.default.red(`✘ ${e}`)}\n`)}success(e){process.stdout.write(`${y.default.green(`✔ ${e}`)}\n`)}step(e){process.stdout.write(`○ ${e}\n`)}note(e,t){Xe(e,t)}log(e){process.stdout.write(`${e}\n`)}spinner(){return Qe()}json(e){process.stdout.write(`${JSON.stringify(e,null,2)}\n`)}cancel(e){process.stderr.write(`${y.default.red(`✘ ${e}`)}\n`)}fatal(e,t){if(process.stderr.write(`${y.default.red(`✘ ${e}`)}\n`),t){let e=`${y.default.red(t instanceof Error?t.stack??String(t):String(t))}\n`;process.stderr.write(e)}throw t instanceof Error?t:Error(e)}finish(e,t){qe(e)}async flush(){return new Promise(e=>{process.stderr.write(``,()=>e())})}},nt=class{constructor(e){this.options=e,this.originalStdoutWrite=process.stdout.write,e.isJson?this.reporter=new b:e.isQuiet?this.reporter=new x:this.reporter=new tt}info(e){this.reporter.info(e)}warn(e){this.reporter.warn(e)}error(e){this.reporter.error(e)}success(e){this.reporter.success(e)}step(e){this.reporter.step(e)}note(e,t){this.reporter.note(e,t)}log(e){this.reporter.log(e)}spinner(){return this.reporter.spinner()}json(e){this.reporter.json(e)}get stdio(){return this.options.isJson?[process.stdin,process.stderr,process.stderr]:`inherit`}interactiveStdout(e){!this.options.isJson||this.options.isYes||(e?process.stdout.write=process.stderr.write.bind(process.stderr):process.stdout.write=this.originalStdoutWrite)}cancel(e){this.reporter.cancel(e)}fatal(e,t){this.reporter.fatal(e,t)}finish(e,t){this.reporter.finish(e,t)}async flush(){await this.reporter.flush()}};async function rt(e=process.cwd(),t){if(t?.compilerOptions?.types){let e=t.compilerOptions.types;if(e.includes(`vite`)||e.includes(`vite/client`))return`vite`}try{let t=r.default.join(e,`package.json`),i=await n.default.readFile(t,`utf-8`),a=JSON.parse(i),o={...a.dependencies,...a.devDependencies};if(o.vite)return`vite`;if(o.next)return`nextjs`}catch{}try{return await n.default.access(r.default.join(e,`vite.config.ts`)),`vite`}catch{}try{return await n.default.access(r.default.join(e,`vite.config.js`)),`vite`}catch{}try{return await n.default.access(r.default.join(e,`next.config.ts`)),`nextjs`}catch{}try{return await n.default.access(r.default.join(e,`next.config.js`)),`nextjs`}catch{}try{return await n.default.access(r.default.join(e,`next.config.mjs`)),`nextjs`}catch{}try{return await n.default.access(r.default.join(e,`next.config.cjs`)),`nextjs`}catch{}return(await it(e,t)).length>0?`bun-fullstack`:`vanilla`}async function it(e=process.cwd(),t){let i=[];try{let t=r.default.join(e,`bunfig.toml`),a=await n.default.readFile(t,`utf-8`);(a.includes(`[serve]`)||a.includes(`[serve.static]`))&&i.push(`serve`),a.includes(`[build]`)&&i.push(`build`)}catch{}if(i.includes(`serve`)&&i.includes(`build`))return i;let{walk:a}=await Promise.resolve().then(()=>st),o=await a(e),s=i.includes(`serve`),c=i.includes(`build`);for(let e of o)try{let t=await n.default.readFile(e,`utf-8`);if(!s&&(t.includes(`Bun.serve`)||t.includes(`serve(`))&&(/from\s+['"]bun['"]/.test(t)||t.includes(`Bun.serve`))&&(s=!0,i.push(`serve`)),!c&&(t.includes(`Bun.build`)||t.includes(`build(`))&&(/from\s+['"]bun['"]/.test(t)||t.includes(`Bun.build`))&&(c=!0,i.push(`build`)),s&&c)break}catch{}return i}async function at(e=process.cwd(),t){let i=process.env.npm_config_user_agent?.toString()||``;if(i.includes(`pnpm`))return`pnpm`;if(i.includes(`yarn`))return`yarn`;if(i.includes(`bun`))return`bun`;if(i.includes(`npm`))return`npm`;let a=t?.path?r.default.dirname(t.path):e;for(;a!==r.default.parse(a).root;){try{let e=r.default.join(a,`package.json`),t=await n.default.readFile(e,`utf-8`),i=JSON.parse(t);if(i.packageManager){if(i.packageManager.startsWith(`pnpm`))return`pnpm`;if(i.packageManager.startsWith(`yarn`))return`yarn`;if(i.packageManager.startsWith(`bun`))return`bun`}}catch{}let e=[];try{e=await n.default.readdir(a)}catch{}if(e.includes(`pnpm-lock.yaml`))return`pnpm`;if(e.includes(`yarn.lock`))return`yarn`;if(e.includes(`bun.lockb`))return`bun`;if(e.includes(`package-lock.json`))return`npm`;a=r.default.dirname(a)}return`npm`}async function ot(e=process.cwd(),t){let i=t;if(!i){let{findTsConfig:t,loadTsConfig:n}=await Promise.resolve().then(()=>pt),r=await t(e);r&&(i=await n(r))}if(i?.compilerOptions?.rootDir){let t=i.compilerOptions.rootDir,n=r.default.relative(e,t);return n&&n!==`.`&&!n.startsWith(`..`)&&!r.default.isAbsolute(n)?`./${n}/env.ts`:`./env.ts`}try{return await n.default.access(r.default.join(e,`src`)),`./src/env.ts`}catch{return`./env.ts`}}var st=e.n({getEnvExampleKeys:()=>ft,parseEnvExample:()=>lt,resolveImportPaths:()=>ut,scanProjectEnvKeys:()=>dt,walk:()=>ct});async function ct(e,t=[]){try{let i=await n.default.readdir(e,{withFileTypes:!0});for(let n of i)if(n.isDirectory()){let i=n.name;if(i===`node_modules`||i===`dist`||i===`build`||i===`.git`||i===`.turbo`||i===`scratch`)continue;await ct(r.default.join(e,i),t)}else n.isFile()&&/\.(ts|tsx|js|jsx)$/.test(n.name)&&!n.name.endsWith(`.d.ts`)&&t.push(r.default.join(e,n.name))}catch{}return t}function lt(e){let t=[],n=e.split(/\r?\n/);for(let e of n){let n=e.trim();if(!n||n.startsWith(`#`))continue;let r=n.match(/^([A-Z_][A-Z0-9_]*)\s*=/i);r?.[1]&&t.push(r[1])}return Array.from(new Set(t))}function ut(e,t,n){if(e.startsWith(`.`))return[r.default.resolve(r.default.dirname(n),e)];if(r.default.isAbsolute(e))return[e];let i=t.compilerOptions||{},a=i.baseUrl||r.default.dirname(t.path),o=i.paths||{},s=[];for(let[e,t]of Object.entries(o)){let n=e.endsWith(`*`),r=e.replace(/\*$/,``);s.push({cleanPattern:r,targets:Array.isArray(t)?t:[t],hadStar:n})}s.sort((e,t)=>t.cleanPattern.length-e.cleanPattern.length);for(let{cleanPattern:t,targets:n,hadStar:i}of s)if(i&&e.startsWith(t)||!i&&e===t){let i=e.slice(t.length);return n.map(e=>{let t=`${e.replace(/\*$/,``)}${i}`;return r.default.resolve(a,t)})}return i.baseUrl?[r.default.resolve(a,e)]:[]}async function dt(e,t,i){let a=[],o=await ct(e),s=i?i.replace(/\.(ts|js|tsx|jsx)$/,``):null;for(let e of o)try{let i=await n.default.readFile(e,`utf-8`),o=i.matchAll(/process\.env\.([A-Z_][A-Z0-9_]*)/g);for(let e of o)e[1]&&a.push(e[1]);let c=i.matchAll(/import\.meta\.env\.([A-Z_][A-Z0-9_]*)/g);for(let e of c)e[1]&&a.push(e[1]);if(s){let n=i.matchAll(/import\s+[^;]*from\s+['"]([^'"]+)['"]/g);for(let o of n){let n=o[1],c=[];if(t?c=ut(n,t,e):n.startsWith(`.`)&&(c=[r.default.resolve(r.default.dirname(e),n)]),c.some(e=>e.replace(/\.(ts|js|tsx|jsx)$/,``)===s)){let e=i.matchAll(/\benv\.([A-Z_][A-Z0-9_]*)/g);for(let t of e)t[1]&&a.push(t[1])}}}}catch{}return Array.from(new Set(a))}async function ft(e=process.cwd(),t,i){let a=r.default.join(e,`.env.example`);try{let e=lt(await n.default.readFile(a,`utf-8`));if(e.length>0)return{keys:e,source:`.env.example`}}catch{}let o=await dt(e,t,i);return o.length>0?{keys:o,source:`project`}:null}var pt=e.n({checkTsConfig:()=>ht,findTsConfig:()=>q,loadTsConfig:()=>J});const mt=(0,l.createRequire)(require(`url`).pathToFileURL(__filename).href).resolve;async function q(e=process.cwd()){let t=[`tsconfig.app.json`,`tsconfig.json`,`tsconfig.base.json`,`tsconfig.node.json`],i=e;for(;i!==r.default.parse(i).root;){for(let e of t){let t=r.default.join(i,e);try{return await n.default.access(t),t}catch{}}i=r.default.dirname(i)}return null}async function J(e,t=new Set){let i=r.default.resolve(e);if(t.has(i))throw Error(`Circular extends dependency detected in tsconfig.json: ${i}`);t.add(i);let a=``;try{a=await n.default.readFile(e,`utf-8`)}catch{return{path:e,compilerOptions:{}}}let o=(0,u.parse)(a)||{},s=o.compilerOptions||{},c={};if(o.extends){let n=Array.isArray(o.extends)?o.extends:[o.extends];for(let i of n){let n;if(i.startsWith(`.`)||r.default.isAbsolute(i))n=r.default.resolve(r.default.dirname(e),i);else try{n=mt(i,{paths:[r.default.dirname(e)]})}catch{n=r.default.resolve(r.default.dirname(e),`node_modules`,i)}let a={...(await J(n,t)).compilerOptions};a.baseUrl&&=r.default.resolve(r.default.dirname(n),a.baseUrl),a.rootDir&&=r.default.resolve(r.default.dirname(n),a.rootDir),c={...c,...a}}}let l={...s};return l.baseUrl&&=r.default.resolve(r.default.dirname(e),l.baseUrl),l.rootDir&&=r.default.resolve(r.default.dirname(e),l.rootDir),c={...c,...l},{...o,path:e,compilerOptions:c}}async function ht(e=process.cwd()){let t=await q(e);if(!t)return{status:`not_found`};let n=r.default.basename(t);try{let e=await J(t);return e?.compilerOptions?.strict===!0?{status:`strict`,file:n,parsed:e}:{status:`not_strict`,file:n,parsed:e}}catch{return{status:`not_found`}}}function gt(e,t){let n=e.replace(/^v/,``).split(`.`).map(Number),r=t.replace(/^v/,``).split(`.`).map(Number);for(let e=0;e<3;e++){let t=n[e]||0,i=r[e]||0;if(t>i)return 1;if(t<i)return-1}return 0}function _t(e){let t=e.trim().match(/^v?(\d+)(?:\.(\d+))?(?:\.(\d+))?/);return t?[t[1],t[2]??`0`,t[3]??`0`].join(`.`):null}function vt(e,t){let n=e.trim(),r=n.match(/^[\^~]?\s*(v?\d+(?:\.\d+){0,2})$/);if(r){let e=_t(r[1]);return e!==null&>(e,t)>=0}let i=n.match(/(?:>=|>|<=|<|=)\s*v?\d+(?:\.\d+){0,2}/g);return!i||i.join(` `)!==n.replace(/\s+/g,` `)?!1:i.some(e=>{let n=e.match(/^(>=|>|<=|<|=)\s*(v?\d+(?:\.\d+){0,2})$/);if(!n)return!1;let[,r,i]=n,a=_t(i);return a&&(r===`>=`||r===`>`||r===`=`)?gt(a,t)>=0:!1})}async function yt(e=process.cwd()){let t=[],i=process.version,a=`22.0.0`;gt(i,a)===-1?t.push({status:`fail`,requirement:`Node.js Version`,message:`Node.js version must be >= ${a}.`,current:i,expected:`>= ${a}`}):t.push({status:`pass`,requirement:`Node.js Version`,message:`Node.js version is compatible.`});let o=null;try{let i=r.default.join(e,`package.json`),a=await n.default.readFile(i,`utf-8`);o=JSON.parse(a),t.push({status:`pass`,requirement:`package.json`,message:`package.json found.`})}catch{t.push({status:`warn`,requirement:`package.json`,message:`package.json not found in the current directory.`})}if(o){let e={...o.dependencies,...o.devDependencies}.typescript,n=`5.1.0`;e?vt(e,n)?t.push({status:`pass`,requirement:`TypeScript Version`,message:`TypeScript version is compatible.`}):t.push({status:`fail`,requirement:`TypeScript Version`,message:`TypeScript version should be >= ${n}.`,current:e,expected:`>= ${n}`}):t.push({status:`warn`,requirement:`TypeScript Version`,message:`TypeScript not found in package.json dependencies.`})}let s=await ht(e);if(s.status===`not_found`)t.push({status:`warn`,requirement:`tsconfig.json`,message:`tsconfig.json not found.`});else{let e=s.parsed.compilerOptions||{};e.strict===!0?t.push({status:`pass`,requirement:`TypeScript Strict Mode`,message:`Strict mode is enabled.`}):t.push({status:`fail`,requirement:`TypeScript Strict Mode`,message:`Strict mode must be enabled.`,current:`false`,expected:`true`});let n=e.moduleResolution?.toLowerCase(),r=e.module?.toLowerCase();[`bundler`,`node16`,`nodenext`].includes(n||``)||!n&&(r===`node16`||r===`nodenext`)?t.push({status:`pass`,requirement:`TypeScript moduleResolution`,message:`moduleResolution is set to ${n||`implicit`}.`}):t.push({status:`fail`,requirement:`TypeScript moduleResolution`,message:`moduleResolution must be set to 'bundler', 'node16', or 'nodenext'.`,current:n||`default`,expected:`bundler, node16, or nodenext`})}return t}var bt=class{async isEmptyDirectory(e=process.cwd()){try{return(await n.default.readdir(e)).length===0}catch{return!1}}async hasPackageJson(e=process.cwd()){try{return await n.default.access(r.default.join(e,`package.json`)),!0}catch{return!1}}async findTsConfig(e=process.cwd()){return q(e)}async loadTsConfig(e,t=new Set){return J(e,t)}async getEnvExampleKeys(e=process.cwd(),t,n){return ft(e,t,n)}async suggestDefaultEnvPath(e=process.cwd(),t){return ot(e,t)}async checkTsConfig(e=process.cwd()){return ht(e)}async checkRequirements(e=process.cwd()){return yt(e)}async detectFramework(e=process.cwd(),t){return rt(e,t)}async detectBunFeatures(e=process.cwd(),t){return it(e,t)}async detectPackageManager(e=process.cwd(),t){return at(e,t)}};const Y=e=>y.default.cyan(e),xt=y.default.blue(`⛯`);function St(e){try{let t=(0,f.parseModule)(e.code),n=e.code,r=t.exports.default;if(r&&typeof r==`object`&&`$type`in r&&r.$type===`function-call`){let e=r;if((e.$callee||JSON.stringify(r))===`defineConfig`&&e.$args){let t=e.$args[0];if(t&&typeof t==`object`&&`$type`in t&&(t.$type===`arrow-function-expression`||t.$type===`function-expression`))return{success:!1,updated:!1,error:`The 'defineConfig' callback form is currently not supported for automatic mutation. Please add the plugin manually.`};r=t}}if(!r||typeof r!=`object`||typeof r==`object`&&`$type`in r)return{success:!1,updated:!1,error:`Could not find default export object in Vite config`};if(r.plugins||=[],Array.isArray(r.plugins))if(!/\barkenv(?:Vite)?Plugin\b/.test(n))t.imports.$add({from:`@arkenv/vite-plugin`,local:`arkenvVitePlugin`,imported:`default`}),e.envImportPath&&t.imports.$add({from:e.envImportPath,imported:`Env`}),r.plugins.push(`__ARK_PLUGIN_PLACEHOLDER__`);else return{success:!0,updated:!1};else return{success:!1,updated:!1,error:`The 'plugins' property in your Vite config is not an array.`};let i=(0,f.generateCode)(t,{format:(0,f.detectCodeFormat)(n)}).code,a=e.envImportPath?`arkenvVitePlugin(Env)`:`arkenvVitePlugin()`;return i=i.replace(/['"]__ARK_PLUGIN_PLACEHOLDER__['"]/g,a),{success:!0,updated:!0,code:i}}catch(e){return{success:!1,updated:!1,error:`Failed to parse Vite config: ${e instanceof Error?e.message:String(e)}`}}}async function Ct(e=process.cwd()){for(let t of[`vite.config.ts`,`vite.config.js`,`vite.config.mts`,`vite.config.mjs`]){let i=r.default.resolve(e,t);try{return await n.default.access(i),i}catch{}}return null}async function wt(e=process.cwd()){for(let t of[`bunfig.toml`,`bun.setup.ts`,`bun.setup.js`]){let i=r.default.resolve(e,t);try{return await n.default.access(i),i}catch{}}return null}async function Tt(e,t,n){try{let r=St({code:await e.readFile(t),envImportPath:n});return r.success&&r.updated&&r.code&&await e.writeFile(t,r.code),r.success?r.updated===void 0?{success:!0}:{success:!0,updated:r.updated}:{success:!1,error:r.error}}catch(e){return{success:!1,error:e instanceof Error?e.message:String(e)}}}async function Et(e,t){if(!t||t.length===0)return{success:!0,instructions:i.default`
|
|
88
88
|
${y.default.green(`✔`)} Use ${y.default.bold(`Vanilla`)} Bun runtime integration.
|
|
89
89
|
Access validated variables via your ${Y(`env`)} object for typesafety.
|
|
90
90
|
Primarily used for ${y.default.cyan(`server-side`)} or runtime-only validation.
|
|
@@ -108,7 +108,23 @@ ${t?(0,a.styleText)(`cyan`,B):``}
|
|
|
108
108
|
outdir: "./dist",
|
|
109
109
|
${y.default.green(`plugins: [arkenv]`)}
|
|
110
110
|
});
|
|
111
|
-
`),{success:!0,instructions:a.trim()}}async function Dt(e,t){let n=t||await q();if(!n)return{status:`not_found`};let i=r.default.basename(n);try{let t=await e.readFile(n);if((0,u.parse)(t)?.compilerOptions?.strict===!0)return{status:`already_strict`,file:i};let r=(0,u.applyEdits)(t,(0,u.modify)(t,[`compilerOptions`,`strict`],!0,{formattingOptions:{insertSpaces:!0,tabSize:2}}));return await e.writeFile(n,r),{status:`updated`,file:i}}catch{return{status:`error`,file:i}}}var Ot=class{constructor(e,t){this.isQuiet=e,this.stdio=t}async exists(e){try{return await n.default.access(e),!0}catch{return!1}}async readFile(e){return n.default.readFile(e,`utf-8`)}async writeFile(e,t){await n.default.writeFile(e,t,`utf-8`)}async mkdir(e,t){await n.default.mkdir(e,{recursive:t})}async execute(e,t=[],n){return new Promise((r,i)=>{let a=(0,d.spawn)(e,t,{cwd:n,stdio:this.isQuiet?`pipe`:this.stdio,shell:!1}),o=``,s=``,c=1e4;this.isQuiet&&(a.stdout?.on(`data`,e=>{o=(o+e.toString()).slice(-c)}),a.stderr?.on(`data`,e=>{s=(s+e.toString()).slice(-c)})),a.on(`close`,(e,t)=>{if(e===0)r();else{let n=e===null?`Command terminated by signal ${t}`:`Command failed with code ${e}`;this.isQuiet&&(o&&(n+=`\n${y.default.dim(`STDOUT:`)}\n${o}`),s&&(n+=`\n${y.default.red(`STDERR:`)}\n${s}`)),i(Error(n))}}),a.on(`error`,i)})}async updateTsConfigToStrict(e){return Dt(this,e)}async findViteConfig(e){return Ct(e)}async findBunConfig(e){return wt(e)}async bootstrapViteConfig(e,t){return Tt(this,e,t)}async bootstrapBunConfig(e,t){return Et(e,t)}async safeAppend(e,t,n){let{safeAppend:r}=await Promise.resolve().then(()=>p);return r(e,t,n)}};async function kt(e){let t=e.defaultPath||`./src/env.ts`;if(e.hasEnvSchemaFile){let e=await H({message:y.default.yellow(`An existing ArkEnv configuration was found at ${Y(t)}. Do you want to overwrite it?`),initialValue:!1,active:`Yes (override my configuration)`,inactive:`No (abort)`});return N(e)||!e?null:e}return!0}async function At(e){let t=e.detectedKeys,n=e.keysSource||`.env.example`;if(t&&t.length>0){let e=t.length,r=e===1,i=await H({message:n===`.env.example`?`Detected ${Y(`.env.example`)} with ${e} ${r?`key`:`keys`}. Use ${r?`it`:`them`} for your schema?`:`Detected ${e} environment variable${r?``:`s`} used in your project. Use ${r?`it`:`them`} for your schema?`,active:`Yes (Recommended)`,initialValue:!0});return N(i)?null:i}return!1}async function jt(e){if(e.framework===`vite`||e.framework===`bun-fullstack`){let t=e.framework===`vite`?`vite-env.d.ts`:`bun-env.d.ts`;if(e.hasTypeFile)return!0;let n=await H({message:`Establish ${Y(t)} for typesafe environment variables?`,initialValue:!0,active:`Yes (Recommended)`,inactive:`No`});return N(n)?null:n}return!0}async function Mt(e){if(!e.installTypeDefinitions||e.framework!==`vite`&&e.framework!==`bun-fullstack`)return`skip`;let t=e.framework===`vite`?`vite-env.d.ts`:`bun-env.d.ts`;if(e.hasTypeFile){let e=await G({message:`Found existing ${Y(t)}. How should we handle ArkEnv types?`,options:[{value:`append`,label:`Append types safely (if needed)`,hint:`Recommended`},{value:`overwrite`,label:`Overwrite entirely`,hint:`Destructive`},{value:`skip`,label:`Skip`}]});return N(e)?null:e}return`overwrite`}async function Nt(e){let t=await G({message:`Select an example:`,options:e.examples.map(e=>({value:e.id,label:e.name,...e.description?{hint:e.description}:{}}))});return N(t)?null:t}async function Pt(e){let t=await G({message:`Select your framework or build tool:`,initialValue:e.framework,options:[{value:`vanilla`,label:`Vanilla${e.framework===`vanilla`?` (Detected)`:``}`,hint:`Node.js, Bun, server-side or runtime-only validation`},{value:`vite`,label:`Vite${e.framework===`vite`?` (Detected)`:``}`,hint:`Client-side and static inlining validation`},{value:`bun-fullstack`,label:`Bun fullstack dev server${e.framework===`bun-fullstack`?` (Detected)`:``}`,hint:`Client-side bundling and Bun.serve integration`}]});return N(t)?null:t}async function Ft(e){let t=await H({message:`Optional: Would you also like to bootstrap a custom Bun.build script for programmatic bundling?`,initialValue:e.initialValue??!1});return N(t)?null:t}async function It(){let e=await G({message:`Select your preferred validator library:`,options:[{value:`arktype`,label:`ArkType (Recommended)`,hint:`TypeScript's 1:1 validator, optimized from editor to runtime`},{value:`zod`,label:`Zod`,hint:`TypeScript-first schema validation with static type inference`},{value:`valibot`,label:`Valibot`,hint:`The modular and type safe schema library`}]});return N(e)?null:e}async function Lt(e){let t=await H({message:`Use default config path (${Y(e.defaultEnvPath||`./src/env.ts`)})?`,initialValue:!0,active:`Yes (Recommended)`,inactive:`No, let me customize it`});return N(t)?null:t}async function Rt(e){let t=e.defaultEnvPath||`./src/env.ts`;if(!e.useDefaultPath){let e=await et({message:`Where should we create the ArkEnv config?`,placeholder:t,initialValue:t,defaultValue:t});if(N(e))return null;let n=typeof e==`string`?e.trim():``;return n===``?t:n}return t}const X={example:Nt,overwriteEnvSchemaFile:kt,framework:Pt,bunBuild:Ft,useDefaultPath:Lt,path:Rt,installTypeDefinitions:jt,envDtsHandling:Mt,validator:It,useEnvExample:At};async function zt(e,t=!1){return(e?.mode||`existing`)===`new`?Bt(e,t):Vt(e,t)}async function Bt(e,t=!1){let n=e?.examples||[],i=`arkenv-project`;try{let a;if(e?.name){let t=e.name.trim();a=t===`.`||t===`./`||r.default.resolve(process.cwd(),t)===process.cwd()?`.`:t}else if(t)a=i;else{let e=(Z(await et({message:`Project name:`,placeholder:i,defaultValue:i}))||i).trim();a=e===`.`||e===`./`||r.default.resolve(process.cwd(),e)===process.cwd()?`.`:e}let o=e?.example;!o&&!t?o=Z(await X.example({examples:n})):!o&&t&&(o=`basic`);let s=n.find(e=>e.id===o);if(!s){let e=n.map(e=>e.id).join(`, `);throw Error(`Unknown example ${o}. Available examples: ${e}`)}return{mode:`new`,example:s.id,name:a,path:`./src/env.ts`,validator:`arktype`,framework:s.framework,language:`ts`,installSkill:!1}}catch(e){if(e instanceof Ut)return null;throw e}}async function Vt(e,n=!1){let r=e?.defaultEnvPath||`./src/env.ts`,i=e?.envKeys||null,a=e?.envKeysSource||`.env.example`;if(n){let n=e?.framework||`vanilla`,a=await Ht(e,n,r),o;return(n===`vite`||n===`bun-fullstack`)&&(o=a?`append`:`overwrite`),(0,t.shake)({mode:`existing`,path:r,validator:`arktype`,framework:n,bunFeatures:n===`bun-fullstack`?e?.bunFeatures??[`serve`]:void 0,language:`ts`,overwriteEnvSchemaFile:!0,installTypeDefinitions:n!==`vanilla`,installSkill:!1,envDtsHandling:o,envKeys:i??void 0})}try{let n=Z(await X.overwriteEnvSchemaFile({hasEnvSchemaFile:e?.hasEnvSchemaFile??!1,defaultPath:r})),o=Z(await X.framework({framework:e?.framework})),s;if(o===`bun-fullstack`){let t=!!e?.bunFeatures?.includes(`build`);s=Z(await X.bunBuild({initialValue:t}))}let c=Z(await X.useDefaultPath({defaultEnvPath:r})),l=Z(await X.path({useDefaultPath:c,defaultEnvPath:r})),u=await Ht(e,o,l),d=Z(await X.installTypeDefinitions({framework:o,hasTypeFile:u})),f=Z(await X.envDtsHandling({framework:o,installTypeDefinitions:d,hasTypeFile:u})),p=Z(await X.validator()),m=Z(await X.useEnvExample({detectedKeys:i,keysSource:a}));return(0,t.shake)({mode:`existing`,overwriteEnvSchemaFile:n,framework:o,path:l,installTypeDefinitions:d,envDtsHandling:f,validator:p,bunFeatures:o===`bun-fullstack`?s?[`serve`,`build`]:[`serve`]:void 0,language:`ts`,installSkill:!1,envKeys:m?i??void 0:void 0})}catch(e){if(e instanceof Ut)return null;throw e}}async function Ht(e,t,n){return await e?.hasTypeFileAtPath?.({framework:t,envPath:n})??e?.hasTypeFile??!1}var Ut=class extends Error{constructor(){super(`Operation cancelled`)}};function Z(e){if(e===null||N(e))throw Ke(`Operation cancelled`),new Ut;return e}var Wt=class{async confirm(e,n=!0,r,i){let a=await H((0,t.shake)({message:e,initialValue:n,active:r,inactive:i}));return N(a)?null:a}async runWizard(e,t=!1){return zt(e,t)}};const Q={isYes:{long:`--yes`,short:`-y`,kind:`boolean`},isForce:{long:`--force`,short:`-f`,kind:`boolean`},isQuiet:{long:`--quiet`,short:`-q`,kind:`boolean`},isJson:{long:`--json`,short:`-j`,kind:`boolean`},isAgent:{long:`--agent`,short:`-a`,kind:`boolean`},helpRequested:{long:`--help`,short:`-h`,kind:`boolean`},example:{long:`--example`,short:`-e`,kind:`value`}},Gt=new Set(Object.values(Q).flatMap(e=>[e.long,e.short])),Kt=new Set(Object.values(Q).filter(e=>e.kind===`value`).flatMap(e=>[e.long,e.short]));var qt=class{constructor(e,t={}){let n=e.slice(2),r=[],i=!1;for(let e of n){if(i){r.push(e),i=!1;continue}if(Kt.has(e)){r.push(e),i=!0;continue}if(/^-[a-zA-Z]{2,}$/.test(e)){let t=e.slice(1).split(``);for(let e of t)r.push(`-${e}`);Kt.has(`-${t[t.length-1]}`)&&(i=!0)}else r.push(e)}this.args=r,this.command=this.args[0];let a=1,o=[];for(this.validationError=void 0;a<this.args.length;){let e=this.args[a];if(e.startsWith(`-`)){if(!Gt.has(e)){this.validationError=`Unknown argument: ${e}`;break}if(Kt.has(e))if(a+1<this.args.length&&!this.args[a+1].startsWith(`-`))a+=2;else{this.validationError=`Missing value for option: ${e}`;break}else a+=1}else o.push(e),a+=1}this.validationError||(o.length>1?this.validationError=`Unknown argument: ${o[1]}`:this.name=o[0]),this.logger=t.logger||new nt({isQuiet:this.isQuiet,isJson:this.isJson,isYes:this.isYes})}get isAgent(){return this.hasFlag(`isAgent`)}get isYes(){return this.isAgent||this.hasFlag(`isYes`)}get isQuiet(){return this.isAgent||this.hasFlag(`isQuiet`)}get isJson(){return this.isAgent||this.hasFlag(`isJson`)}get isForce(){return this.hasFlag(`isForce`)}get helpRequested(){return this.hasFlag(`helpRequested`)}get example(){let e=Q.example;return this.getFlagValue(e.long,e.short)}hasFlag(e){let t=Q[e];return this.args.includes(t.long)||this.args.includes(t.short)}get initInput(){let e={isYes:this.isYes,isForce:this.isForce,isQuiet:this.isQuiet,isAgent:this.isAgent};return this.example!==void 0&&(e.example=this.example),this.name!==void 0&&(e.name=this.name),e}getFlagValue(e,t){let n=this.args.findIndex(n=>n===e||n===t);if(n!==-1&&this.args[n+1]&&!this.args[n+1].startsWith(`-`))return this.args[n+1]}},Jt=`0.2.2`;function Yt(e,t=2,n=4){let r=Math.max(...e.map(e=>e.left.length),0),i=` `.repeat(t);return e.map(e=>{let t=` `.repeat(r-e.left.length+n);return`${i}${e.left}${t}${e.right}`})}var Xt=class{constructor(e){this.logger=e}async execute(){let e=[{left:`arkenv init [project-name]`,right:`Set up ArkEnv in your project`}],t=[{left:`--yes, -y`,right:`Skip prompts and use defaults (also passed to subprocesses)`},{left:`--force, -f`,right:`Bypass technical requirement checks and force scaffolding`},{left:`--agent, -a`,right:`Agent mode: --yes --quiet --json`},{left:`--example, -e`,right:`Specify an example name when creating a new project`},{left:`--quiet, -q`,right:`Quiet mode: Suppress output, capture logs on failure`},{left:`--json, -j`,right:`Output structured JSON to stdout`},{left:`--help, -h`,right:`Show this help message`}];this.logger.log(`ArkEnv CLI v${Jt}`),this.logger.log(`\n${y.default.bold(`Usage:`)}`);for(let t of Yt(e))this.logger.log(t);this.logger.log(`\n${y.default.bold(`Options:`)}`);for(let e of Yt(t))this.logger.log(e)}};const Zt=(e,t)=>{let n=e?.length?e.map(e=>`\t\t${e}: "string = ''",`).join(`
|
|
111
|
+
`),{success:!0,instructions:a.trim()}}async function Dt(e,t){let n=t||await q();if(!n)return{status:`not_found`};let i=r.default.basename(n);try{let t=await e.readFile(n);if((0,u.parse)(t)?.compilerOptions?.strict===!0)return{status:`already_strict`,file:i};let r=(0,u.applyEdits)(t,(0,u.modify)(t,[`compilerOptions`,`strict`],!0,{formattingOptions:{insertSpaces:!0,tabSize:2}}));return await e.writeFile(n,r),{status:`updated`,file:i}}catch{return{status:`error`,file:i}}}var Ot=class{constructor(e,t){this.isQuiet=e,this.stdio=t}async exists(e){try{return await n.default.access(e),!0}catch{return!1}}async readFile(e){return n.default.readFile(e,`utf-8`)}async writeFile(e,t){await n.default.writeFile(e,t,`utf-8`)}async mkdir(e,t){await n.default.mkdir(e,{recursive:t})}async execute(e,t=[],n){return new Promise((r,i)=>{let a=(0,d.spawn)(e,t,{cwd:n,stdio:this.isQuiet?`pipe`:this.stdio,shell:!1}),o=``,s=``,c=1e4;this.isQuiet&&(a.stdout?.on(`data`,e=>{o=(o+e.toString()).slice(-c)}),a.stderr?.on(`data`,e=>{s=(s+e.toString()).slice(-c)})),a.on(`close`,(e,t)=>{if(e===0)r();else{let n=e===null?`Command terminated by signal ${t}`:`Command failed with code ${e}`;this.isQuiet&&(o&&(n+=`\n${y.default.dim(`STDOUT:`)}\n${o}`),s&&(n+=`\n${y.default.red(`STDERR:`)}\n${s}`)),i(Error(n))}}),a.on(`error`,i)})}async updateTsConfigToStrict(e){return Dt(this,e)}async findViteConfig(e){return Ct(e)}async findBunConfig(e){return wt(e)}async bootstrapViteConfig(e,t){return Tt(this,e,t)}async bootstrapBunConfig(e,t){return Et(e,t)}async safeAppend(e,t,n){let{safeAppend:r}=await Promise.resolve().then(()=>p);return r(e,t,n)}};async function kt(e){let t=e.defaultPath||`./src/env.ts`;if(e.hasEnvSchemaFile){let e=await H({message:y.default.yellow(`An existing ArkEnv configuration was found at ${Y(t)}. Do you want to overwrite it?`),initialValue:!1,active:`Yes (override my configuration)`,inactive:`No (abort)`});return N(e)||!e?null:e}return!0}async function At(e){let t=e.detectedKeys,n=e.keysSource||`.env.example`;if(t&&t.length>0){let e=t.length,r=e===1,i=await H({message:n===`.env.example`?`Detected ${Y(`.env.example`)} with ${e} ${r?`key`:`keys`}. Use ${r?`it`:`them`} for your schema?`:`Detected ${e} environment variable${r?``:`s`} used in your project. Use ${r?`it`:`them`} for your schema?`,active:`Yes (Recommended)`,initialValue:!0});return N(i)?null:i}return!1}async function jt(e){if(e.framework===`vite`||e.framework===`bun-fullstack`){let t=e.framework===`vite`?`vite-env.d.ts`:`bun-env.d.ts`;if(e.hasTypeFile)return!0;let n=await H({message:`Establish ${Y(t)} for typesafe environment variables?`,initialValue:!0,active:`Yes (Recommended)`,inactive:`No`});return N(n)?null:n}return!0}async function Mt(e){if(!e.installTypeDefinitions||e.framework!==`vite`&&e.framework!==`bun-fullstack`)return`skip`;let t=e.framework===`vite`?`vite-env.d.ts`:`bun-env.d.ts`;if(e.hasTypeFile){let e=await G({message:`Found existing ${Y(t)}. How should we handle ArkEnv types?`,options:[{value:`append`,label:`Append types safely (if needed)`,hint:`Recommended`},{value:`overwrite`,label:`Overwrite entirely`,hint:`Destructive`},{value:`skip`,label:`Skip`}]});return N(e)?null:e}return`overwrite`}async function Nt(e){let t=await G({message:`Select an example:`,options:e.examples.map(e=>({value:e.id,label:e.name,...e.description?{hint:e.description}:{}}))});return N(t)?null:t}async function Pt(e){let t=await G({message:`Select your framework or build tool:`,initialValue:e.framework,options:[{value:`vanilla`,label:`Vanilla${e.framework===`vanilla`?` (Detected)`:``}`,hint:`Node.js, Bun, server-side or runtime-only validation`},{value:`vite`,label:`Vite${e.framework===`vite`?` (Detected)`:``}`,hint:`Client-side and static inlining validation`},{value:`bun-fullstack`,label:`Bun fullstack dev server${e.framework===`bun-fullstack`?` (Detected)`:``}`,hint:`Client-side bundling and Bun.serve integration`},{value:`nextjs`,label:`Next.js${e.framework===`nextjs`?` (Detected)`:``}`,hint:`Next.js App or Pages Router with build and runtime validation`}]});return N(t)?null:t}async function Ft(e){let t=await H({message:`Optional: Would you also like to bootstrap a custom Bun.build script for programmatic bundling?`,initialValue:e.initialValue??!1});return N(t)?null:t}async function It(){let e=await G({message:`Select your preferred validator library:`,options:[{value:`arktype`,label:`ArkType (Recommended)`,hint:`TypeScript's 1:1 validator, optimized from editor to runtime`},{value:`zod`,label:`Zod`,hint:`TypeScript-first schema validation with static type inference`},{value:`valibot`,label:`Valibot`,hint:`The modular and type safe schema library`}]});return N(e)?null:e}async function Lt(e){let t=await H({message:`Use default config path (${Y(e.defaultEnvPath||`./src/env.ts`)})?`,initialValue:!0,active:`Yes (Recommended)`,inactive:`No, let me customize it`});return N(t)?null:t}async function Rt(e){let t=e.defaultEnvPath||`./src/env.ts`;if(!e.useDefaultPath){let e=await et({message:`Where should we create the ArkEnv config?`,placeholder:t,initialValue:t,defaultValue:t});if(N(e))return null;let n=typeof e==`string`?e.trim():``;return n===``?t:n}return t}const X={example:Nt,overwriteEnvSchemaFile:kt,framework:Pt,bunBuild:Ft,useDefaultPath:Lt,path:Rt,installTypeDefinitions:jt,envDtsHandling:Mt,validator:It,useEnvExample:At};async function zt(e,t=!1){return(e?.mode||`existing`)===`new`?Bt(e,t):Vt(e,t)}async function Bt(e,t=!1){let n=e?.examples||[],i=`arkenv-project`;try{let a;if(e?.name){let t=e.name.trim();a=t===`.`||t===`./`||r.default.resolve(process.cwd(),t)===process.cwd()?`.`:t}else if(t)a=i;else{let e=(Z(await et({message:`Project name:`,placeholder:i,defaultValue:i}))||i).trim();a=e===`.`||e===`./`||r.default.resolve(process.cwd(),e)===process.cwd()?`.`:e}let o=e?.example;!o&&!t?o=Z(await X.example({examples:n})):!o&&t&&(o=`basic`);let s=n.find(e=>e.id===o);if(!s){let e=n.map(e=>e.id).join(`, `);throw Error(`Unknown example ${o}. Available examples: ${e}`)}return{mode:`new`,example:s.id,name:a,path:`./src/env.ts`,validator:`arktype`,framework:s.framework,language:`ts`,installSkill:!1}}catch(e){if(e instanceof Ut)return null;throw e}}async function Vt(e,n=!1){let r=e?.defaultEnvPath||`./src/env.ts`,i=e?.envKeys||null,a=e?.envKeysSource||`.env.example`;if(n){let n=e?.framework||`vanilla`,a=await Ht(e,n,r),o;return(n===`vite`||n===`bun-fullstack`)&&(o=a?`append`:`overwrite`),(0,t.shake)({mode:`existing`,path:r,validator:`arktype`,framework:n,bunFeatures:n===`bun-fullstack`?e?.bunFeatures??[`serve`]:void 0,language:`ts`,overwriteEnvSchemaFile:!0,installTypeDefinitions:n===`vite`||n===`bun-fullstack`,installSkill:!1,envDtsHandling:o,envKeys:i??void 0})}try{let n=Z(await X.overwriteEnvSchemaFile({hasEnvSchemaFile:e?.hasEnvSchemaFile??!1,defaultPath:r})),o=Z(await X.framework({framework:e?.framework})),s;if(o===`bun-fullstack`){let t=!!e?.bunFeatures?.includes(`build`);s=Z(await X.bunBuild({initialValue:t}))}let c=Z(await X.useDefaultPath({defaultEnvPath:r})),l=Z(await X.path({useDefaultPath:c,defaultEnvPath:r})),u=await Ht(e,o,l),d=Z(await X.installTypeDefinitions({framework:o,hasTypeFile:u})),f=Z(await X.envDtsHandling({framework:o,installTypeDefinitions:d,hasTypeFile:u})),p=Z(await X.validator()),m=Z(await X.useEnvExample({detectedKeys:i,keysSource:a}));return(0,t.shake)({mode:`existing`,overwriteEnvSchemaFile:n,framework:o,path:l,installTypeDefinitions:d,envDtsHandling:f,validator:p,bunFeatures:o===`bun-fullstack`?s?[`serve`,`build`]:[`serve`]:void 0,language:`ts`,installSkill:!1,envKeys:m?i??void 0:void 0})}catch(e){if(e instanceof Ut)return null;throw e}}async function Ht(e,t,n){return await e?.hasTypeFileAtPath?.({framework:t,envPath:n})??e?.hasTypeFile??!1}var Ut=class extends Error{constructor(){super(`Operation cancelled`)}};function Z(e){if(e===null||N(e))throw Ke(`Operation cancelled`),new Ut;return e}var Wt=class{async confirm(e,n=!0,r,i){let a=await H((0,t.shake)({message:e,initialValue:n,active:r,inactive:i}));return N(a)?null:a}async runWizard(e,t=!1){return zt(e,t)}};const Q={isYes:{long:`--yes`,short:`-y`,kind:`boolean`},isForce:{long:`--force`,short:`-f`,kind:`boolean`},isQuiet:{long:`--quiet`,short:`-q`,kind:`boolean`},isJson:{long:`--json`,short:`-j`,kind:`boolean`},isAgent:{long:`--agent`,short:`-a`,kind:`boolean`},helpRequested:{long:`--help`,short:`-h`,kind:`boolean`},example:{long:`--example`,short:`-e`,kind:`value`}},Gt=new Set(Object.values(Q).flatMap(e=>[e.long,e.short])),Kt=new Set(Object.values(Q).filter(e=>e.kind===`value`).flatMap(e=>[e.long,e.short]));var qt=class{constructor(e,t={}){let n=e.slice(2),r=[],i=!1;for(let e of n){if(i){r.push(e),i=!1;continue}if(Kt.has(e)){r.push(e),i=!0;continue}if(/^-[a-zA-Z]{2,}$/.test(e)){let t=e.slice(1).split(``);for(let e of t)r.push(`-${e}`);Kt.has(`-${t[t.length-1]}`)&&(i=!0)}else r.push(e)}this.args=r,this.command=this.args[0];let a=1,o=[];for(this.validationError=void 0;a<this.args.length;){let e=this.args[a];if(e.startsWith(`-`)){if(!Gt.has(e)){this.validationError=`Unknown argument: ${e}`;break}if(Kt.has(e))if(a+1<this.args.length&&!this.args[a+1].startsWith(`-`))a+=2;else{this.validationError=`Missing value for option: ${e}`;break}else a+=1}else o.push(e),a+=1}this.validationError||(o.length>1?this.validationError=`Unknown argument: ${o[1]}`:this.name=o[0]),this.logger=t.logger||new nt({isQuiet:this.isQuiet,isJson:this.isJson,isYes:this.isYes})}get isAgent(){return this.hasFlag(`isAgent`)}get isYes(){return this.isAgent||this.hasFlag(`isYes`)}get isQuiet(){return this.isAgent||this.hasFlag(`isQuiet`)}get isJson(){return this.isAgent||this.hasFlag(`isJson`)}get isForce(){return this.hasFlag(`isForce`)}get helpRequested(){return this.hasFlag(`helpRequested`)}get example(){let e=Q.example;return this.getFlagValue(e.long,e.short)}hasFlag(e){let t=Q[e];return this.args.includes(t.long)||this.args.includes(t.short)}get initInput(){let e={isYes:this.isYes,isForce:this.isForce,isQuiet:this.isQuiet,isAgent:this.isAgent};return this.example!==void 0&&(e.example=this.example),this.name!==void 0&&(e.name=this.name),e}getFlagValue(e,t){let n=this.args.findIndex(n=>n===e||n===t);if(n!==-1&&this.args[n+1]&&!this.args[n+1].startsWith(`-`))return this.args[n+1]}},Jt=`0.2.4`;function Yt(e,t=2,n=4){let r=Math.max(...e.map(e=>e.left.length),0),i=` `.repeat(t);return e.map(e=>{let t=` `.repeat(r-e.left.length+n);return`${i}${e.left}${t}${e.right}`})}var Xt=class{constructor(e){this.logger=e}async execute(){let e=[{left:`arkenv init [project-name]`,right:`Set up ArkEnv in your project`}],t=[{left:`--yes, -y`,right:`Skip prompts and use defaults (also passed to subprocesses)`},{left:`--force, -f`,right:`Bypass technical requirement checks and force scaffolding`},{left:`--agent, -a`,right:`Agent mode: --yes --quiet --json`},{left:`--example, -e`,right:`Specify an example name when creating a new project`},{left:`--quiet, -q`,right:`Quiet mode: Suppress output, capture logs on failure`},{left:`--json, -j`,right:`Output structured JSON to stdout`},{left:`--help, -h`,right:`Show this help message`}];this.logger.log(`ArkEnv CLI v${Jt}`),this.logger.log(`\n${y.default.bold(`Usage:`)}`);for(let t of Yt(e))this.logger.log(t);this.logger.log(`\n${y.default.bold(`Options:`)}`);for(let e of Yt(t))this.logger.log(e)}};function Zt(e,t){let{extraImports:n,serverField:r,clientField:i,sharedField:a,defaultServerFields:o,defaultClientFields:s,defaultSharedFields:c}=t,l=[],u=[],d=[],f=[];if(e&&e.length>0)for(let t of e)t.startsWith(`NEXT_PUBLIC_`)?(u.push(i(t)),f.push(`\t\t${t}: process.env.${t},`)):t===`NODE_ENV`||t===`PORT`?(d.push(a(t,t===`PORT`)),f.push(`\t\t${t}: process.env.${t},`)):l.push(r(t));else l.push(...o),u.push(...s),d.push(...c),f.push(` NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,`,` NODE_ENV: process.env.NODE_ENV,`);let p=[];return l.length>0&&p.push(`\tserver: {\n${l.join(`
|
|
112
|
+
`)}\n\t}`),u.length>0&&p.push(`\tclient: {\n${u.join(`
|
|
113
|
+
`)}\n\t}`),d.length>0&&p.push(`\tshared: {\n${d.join(`
|
|
114
|
+
`)}\n\t}`),p.push(`\truntimeEnv: {\n${f.join(`
|
|
115
|
+
`)}\n\t}`),`${[`import arkenv from "@arkenv/nextjs";`,...n?[n]:[]].join(`
|
|
116
|
+
`)}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Environment variable schema.
|
|
120
|
+
* In Next.js, use \`@arkenv/nextjs\` to validate variables at build-time and runtime.
|
|
121
|
+
* Enforces client/server separation and prevents secret leaks.
|
|
122
|
+
*/
|
|
123
|
+
export const env = arkenv({
|
|
124
|
+
${p.join(`,
|
|
125
|
+
`)},
|
|
126
|
+
});
|
|
127
|
+
`}const Qt=(e,t)=>{let n=e?.length?e.map(e=>`\t\t${e}: "string = ''",`).join(`
|
|
112
128
|
`):` NODE_ENV: "'development' | 'production' | 'test' = 'development'",
|
|
113
129
|
PORT: "number.port = 3000",`;return t===`vite`?i.default`
|
|
114
130
|
import { type } from "arkenv";
|
|
@@ -132,7 +148,7 @@ ${n}
|
|
|
132
148
|
export const Env = type({
|
|
133
149
|
${n}
|
|
134
150
|
});
|
|
135
|
-
`:i.default`
|
|
151
|
+
`:t===`nextjs`?Zt(e,{serverField:e=>`\t\t${e}: "string = ''",`,clientField:e=>`\t\t${e}: "string = ''",`,sharedField:(e,t)=>`\t\t${e}: "${t?`number.port = 3000`:`'development' | 'production' | 'test' = 'development'`}",`,defaultServerFields:[` DATABASE_URL: "string = 'postgres://localhost:5432/mydb'",`],defaultClientFields:[` NEXT_PUBLIC_API_URL: "string = 'https://api.example.com'",`],defaultSharedFields:[` NODE_ENV: "'development' | 'production' | 'test' = 'development'",`]}):i.default`
|
|
136
152
|
import arkenv, { type } from "arkenv";
|
|
137
153
|
|
|
138
154
|
/**
|
|
@@ -143,7 +159,7 @@ ${n}
|
|
|
143
159
|
});
|
|
144
160
|
|
|
145
161
|
export const env = arkenv(Env);
|
|
146
|
-
`}
|
|
162
|
+
`},$t=e=>i.default`
|
|
147
163
|
/// <reference types="vite/client" />
|
|
148
164
|
|
|
149
165
|
type ImportMetaEnvAugmented =
|
|
@@ -156,7 +172,7 @@ ${n}
|
|
|
156
172
|
interface ImportMeta {
|
|
157
173
|
readonly env: ImportMetaEnv;
|
|
158
174
|
}
|
|
159
|
-
|
|
175
|
+
`,en=e=>i.default`
|
|
160
176
|
/// <reference types="bun-types" />
|
|
161
177
|
|
|
162
178
|
type ProcessEnvAugmented = import("@arkenv/bun-plugin").ProcessEnvAugmented<
|
|
@@ -166,7 +182,7 @@ ${n}
|
|
|
166
182
|
declare namespace NodeJS {
|
|
167
183
|
interface ProcessEnv extends ProcessEnvAugmented {}
|
|
168
184
|
}
|
|
169
|
-
`,
|
|
185
|
+
`,tn=(e,t)=>{let n=e?.length?e.map(e=>`\t\t${e}: v.optional(v.string(), ""),`).join(`
|
|
170
186
|
`):` NODE_ENV: v.optional(v.picklist(["development", "production", "test"]), "development"),
|
|
171
187
|
PORT: v.optional(v.pipe(v.string(), v.transform(Number), v.number(), v.integer(), v.minValue(1), v.maxValue(65535)), 3000),`;return t===`vite`?i.default`
|
|
172
188
|
import { type } from "arkenv";
|
|
@@ -192,7 +208,7 @@ ${n}
|
|
|
192
208
|
export const Env = type({
|
|
193
209
|
${n}
|
|
194
210
|
});
|
|
195
|
-
`:i.default`
|
|
211
|
+
`:t===`nextjs`?Zt(e,{extraImports:`import * as v from "valibot";`,serverField:e=>`\t\t${e}: v.optional(v.string(), ""),`,clientField:e=>`\t\t${e}: v.optional(v.string(), ""),`,sharedField:(e,t)=>`\t\t${e}: ${t?`v.optional(v.pipe(v.string(), v.transform(Number), v.number(), v.integer(), v.minValue(1), v.maxValue(65535)), 3000)`:`v.optional(v.picklist(["development", "production", "test"]), "development")`},`,defaultServerFields:[` DATABASE_URL: v.optional(v.pipe(v.string(), v.url()), "postgres://localhost:5432/mydb"),`],defaultClientFields:[` NEXT_PUBLIC_API_URL: v.optional(v.pipe(v.string(), v.url()), "https://api.example.com"),`],defaultSharedFields:[` NODE_ENV: v.optional(v.picklist(["development", "production", "test"]), "development"),`]}):i.default`
|
|
196
212
|
import arkenv from "arkenv/standard";
|
|
197
213
|
import * as v from "valibot";
|
|
198
214
|
|
|
@@ -200,9 +216,9 @@ ${n}
|
|
|
200
216
|
* Environment variable schema for server-side or runtime-only validation.
|
|
201
217
|
*/
|
|
202
218
|
export const env = arkenv({
|
|
203
|
-
${n}
|
|
219
|
+
${n}
|
|
204
220
|
});
|
|
205
|
-
`},
|
|
221
|
+
`},nn=(e,t)=>{let n=e?.length?e.map(e=>`\t\t${e}: z.string().default(""),`).join(`
|
|
206
222
|
`):` NODE_ENV: z.enum(["development", "production", "test"]).default("development"),
|
|
207
223
|
PORT: z.coerce.number().int().min(1).max(65535).default(3000),`;return t===`vite`?i.default`
|
|
208
224
|
import { type } from "arkenv";
|
|
@@ -228,7 +244,7 @@ ${n}
|
|
|
228
244
|
export const Env = type({
|
|
229
245
|
${n}
|
|
230
246
|
});
|
|
231
|
-
`:i.default`
|
|
247
|
+
`:t===`nextjs`?Zt(e,{extraImports:`import { z } from "zod";`,serverField:e=>`\t\t${e}: z.string().default(""),`,clientField:e=>`\t\t${e}: z.string().default(""),`,sharedField:(e,t)=>`\t\t${e}: ${t?`z.coerce.number().int().min(1).max(65535).default(3000)`:`z.enum(["development", "production", "test"]).default("development")`},`,defaultServerFields:[` DATABASE_URL: z.string().url().default("postgres://localhost:5432/mydb"),`],defaultClientFields:[` NEXT_PUBLIC_API_URL: z.string().url().default("https://api.example.com"),`],defaultSharedFields:[` NODE_ENV: z.enum(["development", "production", "test"]).default("development"),`]}):i.default`
|
|
232
248
|
import arkenv from "arkenv/standard";
|
|
233
249
|
import { z } from "zod";
|
|
234
250
|
|
|
@@ -236,14 +252,14 @@ ${n}
|
|
|
236
252
|
* Environment variable schema for server-side or runtime-only validation.
|
|
237
253
|
*/
|
|
238
254
|
export const env = arkenv({
|
|
239
|
-
${n}
|
|
255
|
+
${n}
|
|
240
256
|
});
|
|
241
|
-
`};function
|
|
257
|
+
`};function rn(e){let{validator:t,envKeys:n,framework:r}=e;switch(t){case`arktype`:return`${Qt(n,r)}\n`;case`zod`:return`${nn(n,r)}\n`;case`valibot`:return`${tn(n,r)}\n`;default:throw Error(`Unsupported validator: ${t}`)}}async function an(e,t){let i=t.targetDir??process.cwd(),a=r.default.join(process.cwd(),`.arkenv-temp`);await e.mkdir(a,!0),t.targetDir&&await e.mkdir(i,!0);try{await e.execute(`git`,[`clone`,`--filter=blob:none`,`--sparse`,t.repository,a]);let o=`examples/${t.example}`;await e.execute(`git`,[`-C`,a,`sparse-checkout`,`set`,o]);let s=r.default.join(a,o),c=await n.default.readdir(s),l=[];for(let t of c){let n=r.default.join(i,t);await e.exists(n)&&l.push(t)}if(l.length>0)throw Error(`Scaffolding into a non-empty directory failed. The following paths already exist: ${l.join(`, `)}`);await on(s,i);for(let e of[`package-lock.json`,`pnpm-lock.yaml`,`yarn.lock`,`bun.lockb`,`bun.lock`])await n.default.rm(r.default.join(i,e),{force:!0});let u=r.default.join(i,`package.json`);if(await e.exists(u)){let n=await e.readFile(u),r=JSON.parse(n);r.name=t.targetName,delete r.packageManager,await e.writeFile(u,JSON.stringify(r,null,2))}}finally{await n.default.rm(a,{recursive:!0,force:!0})}}async function on(e,t){let i=await n.default.readdir(e);await Promise.all(i.map(i=>n.default.cp(r.default.join(e,i),r.default.join(t,i),{recursive:!0,force:!1})))}function sn(e,t){let n=t.length>0;switch(e){case`pnpm`:return[`pnpm`,[n?`add`:`install`,...t]];case`yarn`:return[`yarn`,[n?`add`:`install`,...t]];case`bun`:return[`bun`,[n?`add`:`install`,...t]];default:return[`npm`,[`install`,...t]]}}function cn(e){return e.metadata.framework===`vite`?`2. Access via ${Y(`import.meta.env.YOUR_VAR`)}`:e.metadata.framework===`bun-fullstack`?`2. Access via ${Y(`process.env.YOUR_VAR`)}`:`2. Import and use: ${Y(`import { env } from "${e.metadata.importPath}"`)}`}function ln(e,t){if(t)return{message:i.default`
|
|
242
258
|
Inside your AI assistant (e.g. Claude Code), use:
|
|
243
259
|
${Y(`/arkenv`)} - automatically refine your schema and configure integrations.
|
|
244
|
-
`,title:`Next steps`};let n=e.skill?.dlxCommand.join(` `)||`npx`,r=e.skill?.packageName||`yamcodes/arkenv`,a=
|
|
260
|
+
`,title:`Next steps`};let n=e.skill?.dlxCommand.join(` `)||`npx`,r=e.skill?.packageName||`yamcodes/arkenv`,a=cn(e);return{message:i.default`
|
|
245
261
|
1. Check ${Y(e.metadata.displayPath)} and refine your environment schema.
|
|
246
262
|
${a}
|
|
247
263
|
3. (Recommended) Install the AI skill: ${Y(`${n} skills add ${r}`)}
|
|
248
264
|
Then run ${Y(`/arkenv`)} inside your AI assistant to finish.
|
|
249
|
-
`,title:`Next steps`}}var ln=class{constructor(e,t){this.workspace=e,this.reporter=t}async execute(e){let t=this.reporter.spinner();t.start(`Scaffolding ArkEnv configuration...`);try{e.clone&&(t.stop(`Starting new project scaffolding...`),this.reporter.step(`Cloning example ${Y(e.clone.example)}...`),await rn(this.workspace,e.clone),t.start(`Scaffolding complete, finalizing...`));for(let t of e.files){if(t.action===`append`){if(!e.bootstrap||e.bootstrap.framework!==`vite`&&e.bootstrap.framework!==`bun-fullstack`){this.reporter.warn(`Skipping safe-append for ${Y(r.default.basename(t.path))}: unsupported framework.`);continue}await this.workspace.safeAppend(t.path,t.content,e.bootstrap.framework)?this.reporter.info(`Appended ArkEnv types to ${Y(r.default.basename(t.path))}.`):this.reporter.info(`${Y(r.default.basename(t.path))} already contains ArkEnv types.`);continue}if(await this.workspace.mkdir(r.default.dirname(t.path),!0),await this.workspace.writeFile(t.path,t.content),t.label!==`environment schema`&&t.label?.includes(`types`)){let e=t.action===`overwrite`?`Updated`:`Created`;this.reporter.info(`${e} ${Y(r.default.basename(t.path))} for typesafe environment variables.`)}}if(t.stop(`Configuration scaffolded!`),e.install&&process.env.SKIP_INSTALL!==`true`){this.reporter.step(`Installing dependencies with ${Y(e.install.packageManager)}...`);let[t,n]=on(e.install.packageManager,e.install.dependencies);await this.workspace.execute(t,n,e.install.cwd??e.cwd)}let n=!1;if(e.tsConfig){let t=await this.workspace.updateTsConfigToStrict(e.tsConfig.path);t.status===`updated`?(this.reporter.info(`Enforced strict: true in your ${Y(t.file)}`),n=!0):t.status===`error`&&this.reporter.warn(`Could not automatically update ${Y(t.file||`tsconfig.json`)}. Please ensure 'strict: true' is set manually.`)}if(e.bootstrap){if(e.bootstrap.framework===`vite`){let t=await this.workspace.findViteConfig(e.cwd);if(t){this.reporter.step(`Bootstrapping Vite plugin...`);let n=await this.workspace.bootstrapViteConfig(t,e.bootstrap.importPath||`./src/env`);n.success?n.updated&&this.reporter.info(`Updated ${Y(r.default.basename(t))}`):(this.reporter.warn(`Could not automatically update ${Y(r.default.basename(t))}: ${n.error}`),this.reporter.info(`Please add ${Y(`@arkenv/vite-plugin`)} manually.`))}else this.reporter.info(`No Vite config found — please add ${Y(`@arkenv/vite-plugin`)} to your Vite config manually.`)}else if(e.bootstrap.framework===`bun-fullstack`){let t=await this.workspace.findBunConfig(e.cwd),n=await this.workspace.bootstrapBunConfig(t,e.bootstrap.bunFeatures);n.success&&n.instructions?this.reporter.info(n.instructions):n.success||this.reporter.error(n.error||`Bun bootstrap failed`)}}let i=!1;if(e.skill&&process.env.SKIP_INSTALL!==`true`){this.reporter.step(`Installing ArkEnv agent skill...`);try{let[t,...n]=e.skill.dlxCommand,r=[...n,`skills`,`add`,e.skill.packageName];e.skill.isYes&&r.push(`--yes`),await this.workspace.execute(t,r,e.cwd),i=!0}catch(e){let t=e instanceof Error?e.message:String(e);this.reporter.warn(`Failed to install ArkEnv AI skill: ${t}`)}}let a=cn(e,i);this.reporter.note(a.message,a.title),this.reporter.finish(`${xt} ArkEnv scaffolding complete. Happy coding!`,{path:e.metadata.displayPath,framework:e.metadata.framework,validator:e.metadata.validator,packageManager:e.metadata.packageManager,tsConfigUpdated:n,skillInstalled:i})}catch(e){throw t.stop(`Scaffolding failed.`),e}}};function un(e){switch(e){case`pnpm`:return[`pnpm`,`dlx`];case`yarn`:return[`yarn`,`dlx`];case`bun`:return[`bunx`];default:return[`npx`]}}function dn(e){let{mode:n,options:i,packageManager:a,tsConfig:o,shouldUpdateTsConfig:s,cwd:c,existingFiles:l}=e,u=i.name&&i.name!==`.`?r.default.basename(i.name):void 0,d={files:[],cwd:c,metadata:(0,t.shake)({displayPath:``,framework:i.framework,validator:i.validator,packageManager:a,importPath:``,mode:n,example:i.example,name:u})};if(n===`new`){if(!i.example)throw Error(`New project scaffolding requires an example.`);let t=i.name&&i.name!==`.`?r.default.join(c,i.name):void 0,n=i.name&&i.name!==`.`?r.default.basename(i.name):r.default.basename(c);return d.clone={repository:`https://github.com/yamcodes/arkenv.git`,example:i.example,targetName:n,...t!==void 0&&{targetDir:t}},d.install={packageManager:a,dependencies:[],...t!==void 0&&{cwd:t}},i.installSkill&&(d.skill={dlxCommand:un(a),packageName:`yamcodes/arkenv`,isYes:e.isYes}),d.metadata.displayPath=`./src/env.ts`,d.metadata.importPath=`./src/env`,d}let f=r.default.resolve(c,i.path),p=r.default.dirname(f),m=nn(i),h=l.includes(f);(!h||i.overwriteEnvSchemaFile!==!1)&&d.files.push({path:f,content:m,action:h?`overwrite`:`create`,label:`environment schema`});let g=[`arkenv`,i.validator];if(i.framework===`vite`&&g.push(`@arkenv/vite-plugin`),i.framework===`bun-fullstack`&&i.bunFeatures?.length&&g.push(`@arkenv/bun-plugin`),d.install={packageManager:a,dependencies:g},s&&o.file&&(d.tsConfig={path:r.default.resolve(c,o.file),action:`strict`}),(i.framework===`vite`||i.framework===`bun-fullstack`&&i.bunFeatures?.length)&&i.installTypeDefinitions!==!1){let e=i.framework===`vite`?`vite-env.d.ts`:`bun-env.d.ts`,t=r.default.join(p,e),n=l.includes(t);if(i.envDtsHandling!==`skip`)if(i.envDtsHandling===`append`||!i.envDtsHandling&&n)d.files.push({path:t,content:f,action:`append`,label:`${i.framework} types`});else{let e=i.framework===`vite`?Qt(i.path):$t(i.path);d.files.push({path:t,content:e,action:n?`overwrite`:`create`,label:`${i.framework} types`})}}(i.framework===`vite`||i.framework===`bun-fullstack`)&&(d.bootstrap=(0,t.shake)({framework:i.framework,bunFeatures:i.framework===`bun-fullstack`?i.bunFeatures:void 0})),i.installSkill&&(d.skill={dlxCommand:un(a),packageName:`yamcodes/arkenv`,isYes:e.isYes});let _=r.default.relative(c,f).replace(/\\/g,`/`),v=_.startsWith(`.`)?_:`./${_}`,y=v.replace(/\.(ts|js|tsx|jsx)$/,``);return d.metadata.displayPath=v,d.metadata.importPath=y,d.bootstrap&&(d.bootstrap.importPath=y),d}var fn=class{async fetchRegistry(){try{let e=await fetch(`https://raw.githubusercontent.com/yamcodes/arkenv/main/examples/registry.json`);if(!e.ok)throw Error(`Failed to fetch registry: ${e.statusText}`);return await e.json()}catch{return{examples:[{id:`basic`,name:`Basic`,description:`A minimal ArkEnv setup in Node.js`,framework:`vanilla`},{id:`with-vite-react`,name:`React + Vite`,framework:`vite`},{id:`with-bun-react`,name:`React + Bun fullstack dev server`,framework:`bun-fullstack`},{id:`with-zod`,name:`Zod`,description:`ArkEnv with Zod in Node.js`,framework:`vanilla`}]}}}},pn=class{constructor(e,t,n,r,i=new fn){this.logger=e,this.workspace=t,this.prompt=n,this.scanner=r,this.registry=i}async execute(e){let t=await this.collect(e);if(!t)return!1;let n=dn(t),r=new ln(this.workspace,this.logger);try{await r.execute(n)}catch(e){this.logger.fatal(`Scaffolding failed.`,e)}return!0}async collect(e){this.logger.interactiveStdout(!0);try{let t=e.name;t&&r.default.resolve(process.cwd(),t)===process.cwd()&&(t=`.`);let n={...e,...t!==void 0&&{name:t}},i=t&&t!==`.`?r.default.resolve(process.cwd(),t):process.cwd(),a=await this.workspace.exists(i),o=a?await this.scanner.hasPackageJson(i):!1,s=a?await this.scanner.isEmptyDirectory(i):!0;return n.example===void 0?o?await this.collectExistingProject(n,i):s||n.isForce?await this.collectNewProject(n,s):(this.logger.error(`Directory is not empty and no ${Y(`package.json`)} was found.`),this.logger.info(`To scaffold a new project, run ${Y(`arkenv init`)} in an empty directory or use ${Y(`--force`)} to proceed anyway.`),null):await this.collectNewProject(n,s)}finally{this.logger.interactiveStdout(!1)}}async collectExistingProject(e,n){let{isYes:i,isForce:a,isAgent:o}=e,s=await this.scanner.checkRequirements(n),c=s.filter(e=>e.status===`fail`),l=s.filter(e=>e.status===`warn`);for(let e of l)this.logger.warn(`${e.requirement}: ${e.message}`);if(c.length>0)if(a){this.logger.warn(`Technical requirements not met, but continuing due to --force flag.`);for(let e of c)this.logger.warn(`${e.requirement}: ${e.message}`)}else{this.logger.error(`Technical requirements not met:`);for(let e of c)this.logger.error(`- ${e.requirement}: ${e.message}${e.current?` (Current: ${e.current}, Expected: ${e.expected})`:``}`);return this.logger.info(`Use --force to bypass these checks.`),null}let u=!1,d=await this.scanner.checkTsConfig(n);if(d.status===`not_strict`)if(i)u=!0;else{this.logger.warn(`TypeScript strict mode is not enabled in your ${Y(d.file)}.`);let e=await this.prompt.confirm(`ArkEnv requires ${Y(`strict`)} mode in your ${Y(d.file)}. Would you like to enable it now?`,!0,`Yes (Recommended)`);if(e===null)return null;if(!e)return this.logger.cancel(`Operation cancelled.`),null;u=!0}let f=await this.scanner.detectFramework(n,d.parsed),p=f===`bun-fullstack`?await this.scanner.detectBunFeatures(n,d.parsed):void 0,m=await this.scanner.suggestDefaultEnvPath(n,d.parsed),h=r.default.resolve(n,m),g=await this.scanner.getEnvExampleKeys(n,d.parsed,h),_=await this.workspace.exists(h),v=async({framework:e,envPath:t})=>{if(e!==`vite`&&e!==`bun-fullstack`)return!1;let i=e===`vite`?`vite-env.d.ts`:`bun-env.d.ts`,a=r.default.resolve(n,t),o=r.default.dirname(a),s=r.default.join(o,i);return this.workspace.exists(s)},y=await v({framework:f,envPath:m}),b=await this.prompt.runWizard((0,t.shake)({mode:`existing`,framework:f,bunFeatures:p,defaultEnvPath:m,tsConfig:d.parsed??null,envKeys:g?.keys,envKeysSource:g?.source,hasTypeFileAtPath:v,hasTypeFile:y,hasEnvSchemaFile:_}),i);if(b===null)return null;if(o)b.installSkill=!1;else if(i)b.installSkill=!0;else{let e=await this.prompt.confirm(`Would you like to install the ArkEnv agent skill?`,!0,`Yes (Recommended)`);if(e===null)return null;b.installSkill=e}let x=r.default.resolve(n,b.path);if(await this.workspace.exists(x)&&b.overwriteEnvSchemaFile===void 0){let e=await this.prompt.confirm(`File ${Y(r.default.basename(x))} already exists. Overwrite?`,!1);if(e===null)return null;if(!e)return this.logger.cancel(`Operation cancelled.`),null;b.overwriteEnvSchemaFile=e}let S=await this.scanner.detectPackageManager(n,d.parsed),C=[];await this.workspace.exists(x)&&C.push(x);let w;if(b.framework===`vite`?w=`vite-env.d.ts`:b.framework===`bun-fullstack`&&(w=`bun-env.d.ts`),w){let e=r.default.dirname(x),t=r.default.join(e,w);await this.workspace.exists(t)&&C.push(t)}return(0,t.shake)({mode:`existing`,cwd:n,options:b,detectedFramework:f,detectedBunFeatures:p,packageManager:S,tsConfig:d,shouldUpdateTsConfig:u,existingFiles:C,isYes:i})}async collectNewProject(e,n=!0){let{isYes:r,example:i,name:a,isForce:o}=e,s=await this.registry.fetchRegistry(),c=await this.prompt.runWizard((0,t.shake)({mode:`new`,examples:s.examples,example:i,name:a}),r);if(c===null)return null;if(c.name===`.`&&!n&&!o)return this.logger.error(`Cannot scaffold into ${Y(`.`)} because the current directory is not empty.`),this.logger.info(`Run ${Y(`arkenv init`)} in an empty directory or choose a sub-directory name instead.`),null;let l=this.detectPackageManager();return(0,t.shake)({mode:`new`,cwd:process.cwd(),options:c,detectedFramework:c.framework,packageManager:l,tsConfig:{status:`not_found`},shouldUpdateTsConfig:!1,existingFiles:[],isYes:r})}detectPackageManager(){let e=process.env.npm_config_user_agent||``;return e.includes(`pnpm`)?`pnpm`:e.includes(`yarn`)?`yarn`:e.includes(`bun`)?`bun`:`npm`}};function mn(e){let t=new qt(e),n=t.logger,r=new Ot(t.isQuiet,n.stdio),i=new Wt;return{cli:t,logger:n,workspace:r,prompt:i,initUseCase:new pn(n,r,i,new bt),helpUseCase:new Xt(n)}}let $,hn=!1;async function gn(){if(process.env.INIT_CWD)try{process.chdir(process.env.INIT_CWD)}catch{}let{cli:e,logger:n,initUseCase:r,helpUseCase:i}=mn(process.argv);$=n,_n(n),e.validationError&&(n.error(e.validationError),await i.execute(),await n.flush(),process.exit(1)),e.helpRequested&&(await i.execute(),await n.flush(),process.exit(0)),e.command!==`init`&&(e.command?n.error(`Unknown command: ${e.command}`):n.error(`Missing command.`),await i.execute(),await n.flush(),process.exit(1));try{await r.execute((0,t.shake)(e.initInput))||(await n.flush(),process.exit(1))}catch(e){try{n.fatal(`An unexpected error occurred`,e)}catch{}await n.flush(),process.exit(1)}}function _n(e){let t=async t=>{hn&&process.exit(t),hn=!0,setTimeout(()=>{process.exit(t)},2e3).unref(),e.interactiveStdout&&e.interactiveStdout(!1);try{e.cancel(`Operation cancelled.`),await e.flush()}catch(t){e.error&&e.error(`Logger failed during shutdown`,t)}finally{process.exit(t)}};process.on(`SIGINT`,()=>t(130)),process.on(`SIGTERM`,()=>t(143))}gn(),process.on(`unhandledRejection`,async e=>{if($){try{$.fatal(`Unhandled rejection`,e)}catch{}await $.flush()}else console.error(`Unhandled rejection`,e);process.exit(1)}),process.on(`uncaughtException`,async e=>{if($){try{$.fatal(`Uncaught exception`,e)}catch{}await $.flush()}else console.error(`Uncaught exception`,e);process.exit(1)});
|
|
265
|
+
`,title:`Next steps`}}var un=class{constructor(e,t){this.workspace=e,this.reporter=t}async execute(e){let t=this.reporter.spinner();t.start(`Scaffolding ArkEnv configuration...`);try{e.clone&&(t.stop(`Starting new project scaffolding...`),this.reporter.step(`Cloning example ${Y(e.clone.example)}...`),await an(this.workspace,e.clone),t.start(`Scaffolding complete, finalizing...`));for(let t of e.files){if(t.action===`append`){if(!e.bootstrap||e.bootstrap.framework!==`vite`&&e.bootstrap.framework!==`bun-fullstack`){this.reporter.warn(`Skipping safe-append for ${Y(r.default.basename(t.path))}: unsupported framework.`);continue}await this.workspace.safeAppend(t.path,t.content,e.bootstrap.framework)?this.reporter.info(`Appended ArkEnv types to ${Y(r.default.basename(t.path))}.`):this.reporter.info(`${Y(r.default.basename(t.path))} already contains ArkEnv types.`);continue}if(await this.workspace.mkdir(r.default.dirname(t.path),!0),await this.workspace.writeFile(t.path,t.content),t.label!==`environment schema`&&t.label?.includes(`types`)){let e=t.action===`overwrite`?`Updated`:`Created`;this.reporter.info(`${e} ${Y(r.default.basename(t.path))} for typesafe environment variables.`)}}if(t.stop(`Configuration scaffolded!`),e.install&&process.env.SKIP_INSTALL!==`true`){this.reporter.step(`Installing dependencies with ${Y(e.install.packageManager)}...`);let[t,n]=sn(e.install.packageManager,e.install.dependencies);await this.workspace.execute(t,n,e.install.cwd??e.cwd)}let n=!1;if(e.tsConfig){let t=await this.workspace.updateTsConfigToStrict(e.tsConfig.path);t.status===`updated`?(this.reporter.info(`Enforced strict: true in your ${Y(t.file)}`),n=!0):t.status===`error`&&this.reporter.warn(`Could not automatically update ${Y(t.file||`tsconfig.json`)}. Please ensure 'strict: true' is set manually.`)}if(e.bootstrap){if(e.bootstrap.framework===`vite`){let t=await this.workspace.findViteConfig(e.cwd);if(t){this.reporter.step(`Bootstrapping Vite plugin...`);let n=await this.workspace.bootstrapViteConfig(t,e.bootstrap.importPath||`./src/env`);n.success?n.updated&&this.reporter.info(`Updated ${Y(r.default.basename(t))}`):(this.reporter.warn(`Could not automatically update ${Y(r.default.basename(t))}: ${n.error}`),this.reporter.info(`Please add ${Y(`@arkenv/vite-plugin`)} manually.`))}else this.reporter.info(`No Vite config found — please add ${Y(`@arkenv/vite-plugin`)} to your Vite config manually.`)}else if(e.bootstrap.framework===`bun-fullstack`){let t=await this.workspace.findBunConfig(e.cwd),n=await this.workspace.bootstrapBunConfig(t,e.bootstrap.bunFeatures);n.success&&n.instructions?this.reporter.info(n.instructions):n.success||this.reporter.error(n.error||`Bun bootstrap failed`)}}let i=!1;if(e.skill&&process.env.SKIP_INSTALL!==`true`){this.reporter.step(`Installing ArkEnv agent skill...`);try{let[t,...n]=e.skill.dlxCommand,r=[...n,`skills`,`add`,e.skill.packageName];e.skill.isYes&&r.push(`--yes`),await this.workspace.execute(t,r,e.cwd),i=!0}catch(e){let t=e instanceof Error?e.message:String(e);this.reporter.warn(`Failed to install ArkEnv AI skill: ${t}`)}}let a=ln(e,i);this.reporter.note(a.message,a.title),this.reporter.finish(`${xt} ArkEnv scaffolding complete. Happy coding!`,{path:e.metadata.displayPath,framework:e.metadata.framework,validator:e.metadata.validator,packageManager:e.metadata.packageManager,tsConfigUpdated:n,skillInstalled:i})}catch(e){throw t.stop(`Scaffolding failed.`),e}}};function dn(e){switch(e){case`pnpm`:return[`pnpm`,`dlx`];case`yarn`:return[`yarn`,`dlx`];case`bun`:return[`bunx`];default:return[`npx`]}}function fn(e){let{mode:n,options:i,packageManager:a,tsConfig:o,shouldUpdateTsConfig:s,cwd:c,existingFiles:l}=e,u=i.name&&i.name!==`.`?r.default.basename(i.name):void 0,d={files:[],cwd:c,metadata:(0,t.shake)({displayPath:``,framework:i.framework,validator:i.validator,packageManager:a,importPath:``,mode:n,example:i.example,name:u})};if(n===`new`){if(!i.example)throw Error(`New project scaffolding requires an example.`);let t=i.name&&i.name!==`.`?r.default.join(c,i.name):void 0,n=i.name&&i.name!==`.`?r.default.basename(i.name):r.default.basename(c);return d.clone={repository:`https://github.com/yamcodes/arkenv.git`,example:i.example,targetName:n,...t!==void 0&&{targetDir:t}},d.install={packageManager:a,dependencies:[],...t!==void 0&&{cwd:t}},i.installSkill&&(d.skill={dlxCommand:dn(a),packageName:`yamcodes/arkenv`,isYes:e.isYes}),d.metadata.displayPath=`./src/env.ts`,d.metadata.importPath=`./src/env`,d}let f=r.default.resolve(c,i.path),p=r.default.dirname(f),m=rn(i),h=l.includes(f);(!h||i.overwriteEnvSchemaFile!==!1)&&d.files.push({path:f,content:m,action:h?`overwrite`:`create`,label:`environment schema`});let g=[`arkenv`,i.validator];if(i.framework===`vite`&&g.push(`@arkenv/vite-plugin`),i.framework===`bun-fullstack`&&i.bunFeatures?.length&&g.push(`@arkenv/bun-plugin`),i.framework===`nextjs`&&g.push(`@arkenv/nextjs`),(i.framework===`vite`||i.framework===`nextjs`||i.framework===`bun-fullstack`&&i.bunFeatures?.length)&&!g.includes(`arktype`)&&g.push(`arktype`),d.install={packageManager:a,dependencies:g},s&&o.file&&(d.tsConfig={path:r.default.resolve(c,o.file),action:`strict`}),(i.framework===`vite`||i.framework===`bun-fullstack`&&i.bunFeatures?.length)&&i.installTypeDefinitions!==!1){let e=i.framework===`vite`?`vite-env.d.ts`:`bun-env.d.ts`,t=r.default.join(p,e),n=l.includes(t);if(i.envDtsHandling!==`skip`)if(i.envDtsHandling===`append`||!i.envDtsHandling&&n)d.files.push({path:t,content:f,action:`append`,label:`${i.framework} types`});else{let e=i.framework===`vite`?$t(i.path):en(i.path);d.files.push({path:t,content:e,action:n?`overwrite`:`create`,label:`${i.framework} types`})}}(i.framework===`vite`||i.framework===`bun-fullstack`)&&(d.bootstrap=(0,t.shake)({framework:i.framework,bunFeatures:i.framework===`bun-fullstack`?i.bunFeatures:void 0})),i.installSkill&&(d.skill={dlxCommand:dn(a),packageName:`yamcodes/arkenv`,isYes:e.isYes});let _=r.default.relative(c,f).replace(/\\/g,`/`),v=_.startsWith(`.`)?_:`./${_}`,y=v.replace(/\.(ts|js|tsx|jsx)$/,``);return d.metadata.displayPath=v,d.metadata.importPath=y,d.bootstrap&&(d.bootstrap.importPath=y),d}var pn=class{async fetchRegistry(){try{let e=await fetch(`https://raw.githubusercontent.com/yamcodes/arkenv/main/examples/registry.json`);if(!e.ok)throw Error(`Failed to fetch registry: ${e.statusText}`);return await e.json()}catch{return{examples:[{id:`basic`,name:`Basic`,description:`A minimal ArkEnv setup in Node.js`,framework:`vanilla`},{id:`with-nextjs`,name:`Next.js`,description:`Minimal Next.js project with ArkType`,framework:`nextjs`},{id:`with-vite-react`,name:`React + Vite`,framework:`vite`},{id:`with-bun`,name:`Bun (Vanilla)`,description:`Minimal Bun project with ArkType`,framework:`vanilla`},{id:`with-bun-react`,name:`React + Bun fullstack dev server`,framework:`bun-fullstack`},{id:`with-zod`,name:`Zod`,description:`ArkEnv with Zod in Node.js`,framework:`vanilla`}]}}}},mn=class{constructor(e,t,n,r,i=new pn){this.logger=e,this.workspace=t,this.prompt=n,this.scanner=r,this.registry=i}async execute(e){let t=await this.collect(e);if(!t)return!1;let n=fn(t),r=new un(this.workspace,this.logger);try{await r.execute(n)}catch(e){this.logger.fatal(`Scaffolding failed.`,e)}return!0}async collect(e){this.logger.interactiveStdout(!0);try{let t=e.name;t&&r.default.resolve(process.cwd(),t)===process.cwd()&&(t=`.`);let n={...e,...t!==void 0&&{name:t}},i=t&&t!==`.`?r.default.resolve(process.cwd(),t):process.cwd(),a=await this.workspace.exists(i),o=a?await this.scanner.hasPackageJson(i):!1,s=a?await this.scanner.isEmptyDirectory(i):!0;return n.example===void 0?o?await this.collectExistingProject(n,i):s||n.isForce?await this.collectNewProject(n,s):(this.logger.error(`Directory is not empty and no ${Y(`package.json`)} was found.`),this.logger.info(`To scaffold a new project, run ${Y(`arkenv init`)} in an empty directory or use ${Y(`--force`)} to proceed anyway.`),null):await this.collectNewProject(n,s)}finally{this.logger.interactiveStdout(!1)}}async collectExistingProject(e,n){let{isYes:i,isForce:a,isAgent:o}=e,s=await this.scanner.checkRequirements(n),c=s.filter(e=>e.status===`fail`),l=s.filter(e=>e.status===`warn`);for(let e of l)this.logger.warn(`${e.requirement}: ${e.message}`);if(c.length>0)if(a){this.logger.warn(`Technical requirements not met, but continuing due to --force flag.`);for(let e of c)this.logger.warn(`${e.requirement}: ${e.message}`)}else{this.logger.error(`Technical requirements not met:`);for(let e of c)this.logger.error(`- ${e.requirement}: ${e.message}${e.current?` (Current: ${e.current}, Expected: ${e.expected})`:``}`);return this.logger.info(`Use --force to bypass these checks.`),null}let u=!1,d=await this.scanner.checkTsConfig(n);if(d.status===`not_strict`)if(i)u=!0;else{this.logger.warn(`TypeScript strict mode is not enabled in your ${Y(d.file)}.`);let e=await this.prompt.confirm(`ArkEnv requires ${Y(`strict`)} mode in your ${Y(d.file)}. Would you like to enable it now?`,!0,`Yes (Recommended)`);if(e===null)return null;if(!e)return this.logger.cancel(`Operation cancelled.`),null;u=!0}let f=await this.scanner.detectFramework(n,d.parsed),p=f===`bun-fullstack`?await this.scanner.detectBunFeatures(n,d.parsed):void 0,m=await this.scanner.suggestDefaultEnvPath(n,d.parsed),h=r.default.resolve(n,m),g=await this.scanner.getEnvExampleKeys(n,d.parsed,h),_=await this.workspace.exists(h),v=async({framework:e,envPath:t})=>{if(e!==`vite`&&e!==`bun-fullstack`)return!1;let i=e===`vite`?`vite-env.d.ts`:`bun-env.d.ts`,a=r.default.resolve(n,t),o=r.default.dirname(a),s=r.default.join(o,i);return this.workspace.exists(s)},y=await v({framework:f,envPath:m}),b=await this.prompt.runWizard((0,t.shake)({mode:`existing`,framework:f,bunFeatures:p,defaultEnvPath:m,tsConfig:d.parsed??null,envKeys:g?.keys,envKeysSource:g?.source,hasTypeFileAtPath:v,hasTypeFile:y,hasEnvSchemaFile:_}),i);if(b===null)return null;if(o)b.installSkill=!1;else if(i)b.installSkill=!0;else{let e=await this.prompt.confirm(`Would you like to install the ArkEnv agent skill?`,!0,`Yes (Recommended)`);if(e===null)return null;b.installSkill=e}let x=r.default.resolve(n,b.path);if(await this.workspace.exists(x)&&b.overwriteEnvSchemaFile===void 0){let e=await this.prompt.confirm(`File ${Y(r.default.basename(x))} already exists. Overwrite?`,!1);if(e===null)return null;if(!e)return this.logger.cancel(`Operation cancelled.`),null;b.overwriteEnvSchemaFile=e}let S=await this.scanner.detectPackageManager(n,d.parsed),C=[];await this.workspace.exists(x)&&C.push(x);let w;if(b.framework===`vite`?w=`vite-env.d.ts`:b.framework===`bun-fullstack`&&(w=`bun-env.d.ts`),w){let e=r.default.dirname(x),t=r.default.join(e,w);await this.workspace.exists(t)&&C.push(t)}return(0,t.shake)({mode:`existing`,cwd:n,options:b,detectedFramework:f,detectedBunFeatures:p,packageManager:S,tsConfig:d,shouldUpdateTsConfig:u,existingFiles:C,isYes:i})}async collectNewProject(e,n=!0){let{isYes:r,example:i,name:a,isForce:o}=e,s=await this.registry.fetchRegistry(),c=await this.prompt.runWizard((0,t.shake)({mode:`new`,examples:s.examples,example:i,name:a}),r);if(c===null)return null;if(c.name===`.`&&!n&&!o)return this.logger.error(`Cannot scaffold into ${Y(`.`)} because the current directory is not empty.`),this.logger.info(`Run ${Y(`arkenv init`)} in an empty directory or choose a sub-directory name instead.`),null;let l=this.detectPackageManager();return(0,t.shake)({mode:`new`,cwd:process.cwd(),options:c,detectedFramework:c.framework,packageManager:l,tsConfig:{status:`not_found`},shouldUpdateTsConfig:!1,existingFiles:[],isYes:r})}detectPackageManager(){let e=process.env.npm_config_user_agent||``;return e.includes(`pnpm`)?`pnpm`:e.includes(`yarn`)?`yarn`:e.includes(`bun`)?`bun`:`npm`}};function hn(e){let t=new qt(e),n=t.logger,r=new Ot(t.isQuiet,n.stdio),i=new Wt;return{cli:t,logger:n,workspace:r,prompt:i,initUseCase:new mn(n,r,i,new bt),helpUseCase:new Xt(n)}}let $,gn=!1;async function _n(){if(process.env.INIT_CWD)try{process.chdir(process.env.INIT_CWD)}catch{}let{cli:e,logger:n,initUseCase:r,helpUseCase:i}=hn(process.argv);$=n,vn(n),e.validationError&&(n.error(e.validationError),await i.execute(),await n.flush(),process.exit(1)),e.helpRequested&&(await i.execute(),await n.flush(),process.exit(0)),e.command!==`init`&&(e.command?n.error(`Unknown command: ${e.command}`):n.error(`Missing command.`),await i.execute(),await n.flush(),process.exit(1));try{await r.execute((0,t.shake)(e.initInput))||(await n.flush(),process.exit(1))}catch(e){try{n.fatal(`An unexpected error occurred`,e)}catch{}await n.flush(),process.exit(1)}}function vn(e){let t=async t=>{gn&&process.exit(t),gn=!0,setTimeout(()=>{process.exit(t)},2e3).unref(),e.interactiveStdout&&e.interactiveStdout(!1);try{e.cancel(`Operation cancelled.`),await e.flush()}catch(t){e.error&&e.error(`Logger failed during shutdown`,t)}finally{process.exit(t)}};process.on(`SIGINT`,()=>t(130)),process.on(`SIGTERM`,()=>t(143))}_n(),process.on(`unhandledRejection`,async e=>{if($){try{$.fatal(`Unhandled rejection`,e)}catch{}await $.flush()}else console.error(`Unhandled rejection`,e);process.exit(1)}),process.on(`uncaughtException`,async e=>{if($){try{$.fatal(`Uncaught exception`,e)}catch{}await $.flush()}else console.error(`Uncaught exception`,e);process.exit(1)});
|