@nexical/cli 0.12.0 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -18,7 +18,7 @@ import { fileURLToPath } from "url";
18
18
  // package.json
19
19
  var package_default = {
20
20
  name: "@nexical/cli",
21
- version: "0.12.0",
21
+ version: "0.12.1",
22
22
  license: "Apache-2.0",
23
23
  type: "module",
24
24
  bin: {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../index.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI, findProjectRoot } from '@nexical/cli-core';\nimport { fileURLToPath } from 'node:url';\nimport { discoverCommandDirectories } from './src/utils/discovery.js';\nimport pkg from './package.json';\nimport path from 'node:path';\nimport { filterCommandDirectories } from './src/utils/filter.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst commandName = 'nexical';\nconst projectRoot = (await findProjectRoot(commandName, process.cwd())) || process.cwd();\nconst coreCommandsDir = path.resolve(__dirname, './src/commands');\nconst additionalCommands = discoverCommandDirectories(projectRoot);\n\nconst filteredAdditional = filterCommandDirectories(additionalCommands, coreCommandsDir);\n\nconst app = new CLI({\n version: pkg.version,\n commandName: commandName,\n searchDirectories: [...new Set([coreCommandsDir, ...filteredAdditional])],\n});\napp.start();\n","{\n \"name\": \"@nexical/cli\",\n \"version\": \"0.12.0\",\n \"license\": \"Apache-2.0\",\n \"type\": \"module\",\n \"bin\": {\n \"nexical\": \"./dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup && cp -r src/deploy/templates dist/\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/index.js\",\n \"test\": \"npm run test:unit && npm run test:integration && npm run test:e2e\",\n \"test:unit\": \"vitest run --config vitest.config.ts --coverage\",\n \"test:integration\": \"vitest run --config vitest.integration.config.ts\",\n \"test:e2e\": \"npm run build && vitest run --config vitest.e2e.config.ts\",\n \"test:watch\": \"vitest\",\n \"format\": \"prettier --write .\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"prepare\": \"husky\"\n },\n \"lint-staged\": {\n \"**/*\": [\n \"prettier --write --ignore-unknown\"\n ],\n \"**/*.{js,jsx,ts,tsx,astro}\": [\n \"eslint --fix\"\n ]\n },\n \"dependencies\": {\n \"@nexical/ai\": \"^0.1.5\",\n \"@nexical/cli-core\": \"^0.1.16\",\n \"dotenv\": \"^17.3.1\",\n \"fast-glob\": \"^3.3.3\",\n \"glob\": \"^13.0.5\",\n \"jiti\": \"^2.6.1\",\n \"minimist\": \"^1.2.8\",\n \"yaml\": \"^2.8.2\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.2\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/minimist\": \"^1.2.5\",\n \"@types/node\": \"^25.3.0\",\n \"@types/nunjucks\": \"^3.2.6\",\n \"@vitest/coverage-v8\": \"^4.0.18\",\n \"eslint\": \"^9.39.2\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-astro\": \"^1.6.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"eslint-plugin-react-hooks\": \"^7.0.1\",\n \"execa\": \"^9.6.1\",\n \"fs-extra\": \"^11.3.3\",\n \"globals\": \"^17.3.0\",\n \"husky\": \"^9.1.7\",\n \"lint-staged\": \"^16.2.7\",\n \"prettier\": \"^3.8.1\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\",\n \"typescript-eslint\": \"^8.56.0\",\n \"vitest\": \"^4.0.18\"\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AACA,SAAS,KAAK,uBAAuB;AACrC,SAAS,qBAAqB;;;ACF9B;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,SAAW;AAAA,EACb;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAW;AAAA,EACb;AAAA,EACA,eAAe;AAAA,IACb,QAAQ;AAAA,MACN;AAAA,IACF;AAAA,IACA,8BAA8B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAgB;AAAA,IACd,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,QAAU;AAAA,IACV,aAAa;AAAA,IACb,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,UAAY;AAAA,IACZ,MAAQ;AAAA,EACV;AAAA,EACA,iBAAmB;AAAA,IACjB,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,uBAAuB;AAAA,IACvB,QAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,6BAA6B;AAAA,IAC7B,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,SAAW;AAAA,IACX,OAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,YAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,QAAU;AAAA,EACZ;AACF;;;AD5DA,OAAO,UAAU;AAGjB,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,IAAM,cAAc;AACpB,IAAM,cAAe,MAAM,gBAAgB,aAAa,QAAQ,IAAI,CAAC,KAAM,QAAQ,IAAI;AACvF,IAAM,kBAAkB,KAAK,QAAQ,WAAW,gBAAgB;AAChE,IAAM,qBAAqB,2BAA2B,WAAW;AAEjE,IAAM,qBAAqB,yBAAyB,oBAAoB,eAAe;AAEvF,IAAM,MAAM,IAAI,IAAI;AAAA,EAClB,SAAS,gBAAI;AAAA,EACb;AAAA,EACA,mBAAmB,CAAC,GAAG,oBAAI,IAAI,CAAC,iBAAiB,GAAG,kBAAkB,CAAC,CAAC;AAC1E,CAAC;AACD,IAAI,MAAM;","names":[]}
1
+ {"version":3,"sources":["../index.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI, findProjectRoot } from '@nexical/cli-core';\nimport { fileURLToPath } from 'node:url';\nimport { discoverCommandDirectories } from './src/utils/discovery.js';\nimport pkg from './package.json';\nimport path from 'node:path';\nimport { filterCommandDirectories } from './src/utils/filter.js';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst commandName = 'nexical';\nconst projectRoot = (await findProjectRoot(commandName, process.cwd())) || process.cwd();\nconst coreCommandsDir = path.resolve(__dirname, './src/commands');\nconst additionalCommands = discoverCommandDirectories(projectRoot);\n\nconst filteredAdditional = filterCommandDirectories(additionalCommands, coreCommandsDir);\n\nconst app = new CLI({\n version: pkg.version,\n commandName: commandName,\n searchDirectories: [...new Set([coreCommandsDir, ...filteredAdditional])],\n});\napp.start();\n","{\n \"name\": \"@nexical/cli\",\n \"version\": \"0.12.1\",\n \"license\": \"Apache-2.0\",\n \"type\": \"module\",\n \"bin\": {\n \"nexical\": \"./dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup && cp -r src/deploy/templates dist/\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/index.js\",\n \"test\": \"npm run test:unit && npm run test:integration && npm run test:e2e\",\n \"test:unit\": \"vitest run --config vitest.config.ts --coverage\",\n \"test:integration\": \"vitest run --config vitest.integration.config.ts\",\n \"test:e2e\": \"npm run build && vitest run --config vitest.e2e.config.ts\",\n \"test:watch\": \"vitest\",\n \"format\": \"prettier --write .\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"prepare\": \"husky\"\n },\n \"lint-staged\": {\n \"**/*\": [\n \"prettier --write --ignore-unknown\"\n ],\n \"**/*.{js,jsx,ts,tsx,astro}\": [\n \"eslint --fix\"\n ]\n },\n \"dependencies\": {\n \"@nexical/ai\": \"^0.1.5\",\n \"@nexical/cli-core\": \"^0.1.16\",\n \"dotenv\": \"^17.3.1\",\n \"fast-glob\": \"^3.3.3\",\n \"glob\": \"^13.0.5\",\n \"jiti\": \"^2.6.1\",\n \"minimist\": \"^1.2.8\",\n \"yaml\": \"^2.8.2\"\n },\n \"devDependencies\": {\n \"@eslint/js\": \"^9.39.2\",\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/minimist\": \"^1.2.5\",\n \"@types/node\": \"^25.3.0\",\n \"@types/nunjucks\": \"^3.2.6\",\n \"@vitest/coverage-v8\": \"^4.0.18\",\n \"eslint\": \"^9.39.2\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-astro\": \"^1.6.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"eslint-plugin-react-hooks\": \"^7.0.1\",\n \"execa\": \"^9.6.1\",\n \"fs-extra\": \"^11.3.3\",\n \"globals\": \"^17.3.0\",\n \"husky\": \"^9.1.7\",\n \"lint-staged\": \"^16.2.7\",\n \"prettier\": \"^3.8.1\",\n \"tsup\": \"^8.5.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.9.3\",\n \"typescript-eslint\": \"^8.56.0\",\n \"vitest\": \"^4.0.18\"\n }\n}\n"],"mappings":";;;;;;;;;;;;;AAAA;AACA,SAAS,KAAK,uBAAuB;AACrC,SAAS,qBAAqB;;;ACF9B;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,SAAW;AAAA,EACb;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAW;AAAA,EACb;AAAA,EACA,eAAe;AAAA,IACb,QAAQ;AAAA,MACN;AAAA,IACF;AAAA,IACA,8BAA8B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAgB;AAAA,IACd,eAAe;AAAA,IACf,qBAAqB;AAAA,IACrB,QAAU;AAAA,IACV,aAAa;AAAA,IACb,MAAQ;AAAA,IACR,MAAQ;AAAA,IACR,UAAY;AAAA,IACZ,MAAQ;AAAA,EACV;AAAA,EACA,iBAAmB;AAAA,IACjB,cAAc;AAAA,IACd,mBAAmB;AAAA,IACnB,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,mBAAmB;AAAA,IACnB,uBAAuB;AAAA,IACvB,QAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,6BAA6B;AAAA,IAC7B,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,SAAW;AAAA,IACX,OAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAY;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,YAAc;AAAA,IACd,qBAAqB;AAAA,IACrB,QAAU;AAAA,EACZ;AACF;;;AD5DA,OAAO,UAAU;AAGjB,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,IAAM,cAAc;AACpB,IAAM,cAAe,MAAM,gBAAgB,aAAa,QAAQ,IAAI,CAAC,KAAM,QAAQ,IAAI;AACvF,IAAM,kBAAkB,KAAK,QAAQ,WAAW,gBAAgB;AAChE,IAAM,qBAAqB,2BAA2B,WAAW;AAEjE,IAAM,qBAAqB,yBAAyB,oBAAoB,eAAe;AAEvF,IAAM,MAAM,IAAI,IAAI;AAAA,EAClB,SAAS,gBAAI;AAAA,EACb;AAAA,EACA,mBAAmB,CAAC,GAAG,oBAAI,IAAI,CAAC,iBAAiB,GAAG,kBAAkB,CAAC,CAAC;AAC1E,CAAC;AACD,IAAI,MAAM;","names":[]}
@@ -118,12 +118,26 @@ PROCESS:
118
118
  }
119
119
  if (isManual && app.buildCommand) {
120
120
  this.info(` Building ${app.name} locally...`);
121
+ const buildEnv = {
122
+ ...process.env,
123
+ ...app.env || {}
124
+ };
125
+ if (app.domain) {
126
+ const domain = Array.isArray(app.domain) ? app.domain[0] : app.domain;
127
+ buildEnv.SITE = `https://${domain}`;
128
+ buildEnv.BASE = "/";
129
+ }
121
130
  if (context.options.dryRun) {
122
131
  this.info(` [Dry Run] Would run build: ${app.buildCommand}`);
132
+ if (buildEnv.SITE) {
133
+ this.info(
134
+ ` [Dry Run] Environment override: SITE=${buildEnv.SITE} BASE=${buildEnv.BASE}`
135
+ );
136
+ }
123
137
  } else {
124
138
  try {
125
139
  const { execAsync } = await import("../deploy/utils.js");
126
- await execAsync(app.buildCommand);
140
+ await execAsync(app.buildCommand, { env: buildEnv });
127
141
  } catch (e) {
128
142
  const message = e instanceof Error ? e.message : String(e);
129
143
  this.error(`Build failed for ${app.name}: ${message}`);
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/deploy.ts"],"sourcesContent":["import path from 'node:path';\nimport dotenv from 'dotenv';\nimport { BaseCommand } from '@nexical/cli-core';\nimport { ConfigManager } from '../deploy/config-manager';\nimport { ProviderRegistry } from '../deploy/registry';\nimport { DeploymentContext, HostingProvider, AppConfig, DnsRecord } from '../deploy/types';\n\nexport default class DeployCommand extends BaseCommand {\n static usage = 'deploy';\n static description = 'Deploy the application based on nexical.yaml configuration.';\n static help = `This command orchestrates the deployment of your applications \nby interacting with the providers specified in your configuration file.\n\nCONFIGURATION:\n- Requires a 'nexical.yaml' file in the project root.\n- Supports definition of multiple applications under 'deploy.apps'.\n- Supports loading environment variables from a .env file in the project root.\n\nPROCESS:\n1. Loads environment variables from '.env'.\n2. Loads configuration from 'nexical.yaml'.\n3. Provisions resources for each application.\n4. Configures the repository (secrets/variables) for CI/CD.\n5. Generates CI/CD workflow files for each application.`;\n\n static args = {\n options: [\n {\n name: '--env <environment>',\n description: 'Deployment environment (e.g. production, staging)',\n default: 'production',\n },\n {\n name: '--dry-run',\n description: 'Simulate the deployment process',\n default: false,\n },\n {\n name: '--apps <apps>',\n description: 'Comma separated list of applications to deploy',\n },\n {\n name: '--manual',\n description: 'Perform a direct build and deployment from the local machine',\n default: false,\n },\n {\n name: '--repo <provider>',\n description: 'Repository provider to use (e.g. github, gitlab)',\n },\n ],\n };\n\n async run(options: Record<string, unknown>) {\n this.info('Starting Nexical Deployment...');\n\n // Load environment variables from .env\n dotenv.config({ path: path.join(process.cwd(), '.env'), quiet: true });\n\n const configManager = new ConfigManager(process.cwd());\n const config = await configManager.load();\n const registry = new ProviderRegistry();\n\n // Register core and local providers\n await registry.loadCoreProviders();\n await registry.loadLocalProviders(process.cwd());\n\n // Resolve Applications\n const appsMap = config.deploy?.apps || {};\n let apps: AppConfig[] = Object.entries(appsMap).map(([name, appConfig]) => {\n const app: AppConfig = {\n ...(appConfig as unknown as AppConfig),\n name,\n };\n return app;\n });\n\n // Filter applications if --apps is specified\n const selectedApps = options.apps as string | undefined;\n if (selectedApps) {\n const appNames = selectedApps.split(',').map((s) => s.trim());\n const filteredApps = apps.filter((app) => appNames.includes(app.name));\n\n // Validation: Ensure all specified apps exist\n const missingApps = appNames.filter((name) => !apps.find((app) => app.name === name));\n if (missingApps.length > 0) {\n this.error(\n `The following applications were not found in nexical.yaml: ${missingApps.join(', ')}`,\n );\n }\n\n apps = filteredApps;\n }\n\n if (apps.length === 0) {\n this.error('No applications found in nexical.yaml. Please configure [deploy.apps].');\n }\n\n const repoProviderName =\n (options.repo as string | undefined) || config.deploy?.repository?.provider;\n if (!repoProviderName) {\n this.error(\n \"Repository provider not specified. Use --repo flag or configure 'deploy.repository.provider' in nexical.yaml.\",\n );\n }\n\n const repoProvider = registry.getRepositoryProvider(repoProviderName!);\n if (!repoProvider) throw new Error(`Repository provider '${repoProviderName}' not found.`);\n\n const context: DeploymentContext = {\n cwd: process.cwd(),\n config,\n options,\n };\n\n const activeApps: { provider: HostingProvider; app: AppConfig }[] = [];\n const secrets: Record<string, string> = {};\n const variables: Record<string, string> = {};\n\n this.info(`Deploying ${apps.length} applications in parallel...`);\n\n const isManual = !!options.manual;\n\n await Promise.all(\n apps.map(async (app) => {\n this.info(`Processing application: ${app.name}...`);\n const provider = registry.getHostingProvider(app.provider);\n if (!provider) {\n this.error(`Provider '${app.provider}' not found for application '${app.name}'.`);\n return;\n }\n\n // Build\n if (isManual && app.buildCommand) {\n this.info(` Building ${app.name} locally...`);\n if (context.options.dryRun) {\n this.info(` [Dry Run] Would run build: ${app.buildCommand}`);\n } else {\n try {\n const { execAsync } = await import('../deploy/utils');\n await execAsync(app.buildCommand);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Build failed for ${app.name}: ${message}`);\n return;\n }\n }\n }\n\n // Provision\n this.info(` Provisioning ${app.name} with ${provider.name}...`);\n await provider.provision(context, app);\n\n // Direct Deploy\n if (isManual && provider.deploy) {\n this.info(` Performing direct deployment for ${app.name}...`);\n await provider.deploy(context, app);\n }\n\n // Collect secrets\n this.info(` Resolving secrets for ${app.name} from ${provider.name}...`);\n try {\n const appSecrets = await provider.getSecrets(context, app);\n Object.assign(secrets, appSecrets);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve secrets for ${app.name} (${provider.name}): ${message}`);\n }\n\n // Collect variables\n this.info(` Resolving variables for ${app.name} from ${provider.name}...`);\n try {\n const appVars = await provider.getVariables(context, app);\n Object.assign(variables, appVars);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve variables for ${app.name} (${provider.name}): ${message}`);\n }\n\n activeApps.push({ provider, app });\n }),\n );\n\n // Configure Repo\n this.info(`Configuring Repository with ${repoProvider.name}...`);\n await repoProvider.configureSecrets(context, secrets);\n await repoProvider.configureVariables(context, variables);\n\n // Generate Workflows\n this.info('Generating CI/CD Workflows...');\n await repoProvider.generateWorkflow(context, activeApps);\n\n // DNS Provisioning\n const dnsConfig = config.deploy?.dns;\n if (dnsConfig?.provider) {\n const dnsProvider = registry.getDnsProvider(dnsConfig.provider);\n if (!dnsProvider) {\n this.error(`DNS provider '${dnsConfig.provider}' not found.`);\n return;\n }\n\n const dnsRecords: DnsRecord[] = [];\n for (const { app, provider } of activeApps) {\n const target =\n app.dnsTarget ||\n (provider.getDefaultDnsTarget ? provider.getDefaultDnsTarget(app) : undefined);\n\n if (app.domain && target) {\n const domains = Array.isArray(app.domain) ? app.domain : [app.domain];\n for (const domain of domains) {\n const isIp = /^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$/.test(target);\n dnsRecords.push({\n type: isIp ? 'A' : 'CNAME',\n name: domain,\n content: target,\n proxied: true,\n });\n }\n } else if (app.domain && !target) {\n this.warn(\n `App '${app.name}' specifies domain(s) but no 'dnsTarget' could be inferred. Skipping DNS auto-provisioning.`,\n );\n }\n }\n\n if (dnsRecords.length > 0) {\n this.info(`Configuring DNS with ${dnsProvider.name}...`);\n try {\n await dnsProvider.provision(context, dnsRecords);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.warn(`DNS provisioning failed: ${message}`);\n }\n }\n }\n\n this.success('Deployment configuration complete!');\n }\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../src/commands/deploy.ts"],"sourcesContent":["import path from 'node:path';\nimport dotenv from 'dotenv';\nimport { BaseCommand } from '@nexical/cli-core';\nimport { ConfigManager } from '../deploy/config-manager';\nimport { ProviderRegistry } from '../deploy/registry';\nimport { DeploymentContext, HostingProvider, AppConfig, DnsRecord } from '../deploy/types';\n\nexport default class DeployCommand extends BaseCommand {\n static usage = 'deploy';\n static description = 'Deploy the application based on nexical.yaml configuration.';\n static help = `This command orchestrates the deployment of your applications \nby interacting with the providers specified in your configuration file.\n\nCONFIGURATION:\n- Requires a 'nexical.yaml' file in the project root.\n- Supports definition of multiple applications under 'deploy.apps'.\n- Supports loading environment variables from a .env file in the project root.\n\nPROCESS:\n1. Loads environment variables from '.env'.\n2. Loads configuration from 'nexical.yaml'.\n3. Provisions resources for each application.\n4. Configures the repository (secrets/variables) for CI/CD.\n5. Generates CI/CD workflow files for each application.`;\n\n static args = {\n options: [\n {\n name: '--env <environment>',\n description: 'Deployment environment (e.g. production, staging)',\n default: 'production',\n },\n {\n name: '--dry-run',\n description: 'Simulate the deployment process',\n default: false,\n },\n {\n name: '--apps <apps>',\n description: 'Comma separated list of applications to deploy',\n },\n {\n name: '--manual',\n description: 'Perform a direct build and deployment from the local machine',\n default: false,\n },\n {\n name: '--repo <provider>',\n description: 'Repository provider to use (e.g. github, gitlab)',\n },\n ],\n };\n\n async run(options: Record<string, unknown>) {\n this.info('Starting Nexical Deployment...');\n\n // Load environment variables from .env\n dotenv.config({ path: path.join(process.cwd(), '.env'), quiet: true });\n\n const configManager = new ConfigManager(process.cwd());\n const config = await configManager.load();\n const registry = new ProviderRegistry();\n\n // Register core and local providers\n await registry.loadCoreProviders();\n await registry.loadLocalProviders(process.cwd());\n\n // Resolve Applications\n const appsMap = config.deploy?.apps || {};\n let apps: AppConfig[] = Object.entries(appsMap).map(([name, appConfig]) => {\n const app: AppConfig = {\n ...(appConfig as unknown as AppConfig),\n name,\n };\n return app;\n });\n\n // Filter applications if --apps is specified\n const selectedApps = options.apps as string | undefined;\n if (selectedApps) {\n const appNames = selectedApps.split(',').map((s) => s.trim());\n const filteredApps = apps.filter((app) => appNames.includes(app.name));\n\n // Validation: Ensure all specified apps exist\n const missingApps = appNames.filter((name) => !apps.find((app) => app.name === name));\n if (missingApps.length > 0) {\n this.error(\n `The following applications were not found in nexical.yaml: ${missingApps.join(', ')}`,\n );\n }\n\n apps = filteredApps;\n }\n\n if (apps.length === 0) {\n this.error('No applications found in nexical.yaml. Please configure [deploy.apps].');\n }\n\n const repoProviderName =\n (options.repo as string | undefined) || config.deploy?.repository?.provider;\n if (!repoProviderName) {\n this.error(\n \"Repository provider not specified. Use --repo flag or configure 'deploy.repository.provider' in nexical.yaml.\",\n );\n }\n\n const repoProvider = registry.getRepositoryProvider(repoProviderName!);\n if (!repoProvider) throw new Error(`Repository provider '${repoProviderName}' not found.`);\n\n const context: DeploymentContext = {\n cwd: process.cwd(),\n config,\n options,\n };\n\n const activeApps: { provider: HostingProvider; app: AppConfig }[] = [];\n const secrets: Record<string, string> = {};\n const variables: Record<string, string> = {};\n\n this.info(`Deploying ${apps.length} applications in parallel...`);\n\n const isManual = !!options.manual;\n\n await Promise.all(\n apps.map(async (app) => {\n this.info(`Processing application: ${app.name}...`);\n const provider = registry.getHostingProvider(app.provider);\n if (!provider) {\n this.error(`Provider '${app.provider}' not found for application '${app.name}'.`);\n return;\n }\n\n // Build\n if (isManual && app.buildCommand) {\n this.info(` Building ${app.name} locally...`);\n\n const buildEnv: Record<string, string> = {\n ...(process.env as Record<string, string>),\n ...(app.env || {}),\n };\n\n if (app.domain) {\n const domain = Array.isArray(app.domain) ? app.domain[0] : app.domain;\n buildEnv.SITE = `https://${domain}`;\n buildEnv.BASE = '/';\n }\n\n if (context.options.dryRun) {\n this.info(` [Dry Run] Would run build: ${app.buildCommand}`);\n if (buildEnv.SITE) {\n this.info(\n ` [Dry Run] Environment override: SITE=${buildEnv.SITE} BASE=${buildEnv.BASE}`,\n );\n }\n } else {\n try {\n const { execAsync } = await import('../deploy/utils');\n await execAsync(app.buildCommand, { env: buildEnv });\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Build failed for ${app.name}: ${message}`);\n return;\n }\n }\n }\n\n // Provision\n this.info(` Provisioning ${app.name} with ${provider.name}...`);\n await provider.provision(context, app);\n\n // Direct Deploy\n if (isManual && provider.deploy) {\n this.info(` Performing direct deployment for ${app.name}...`);\n await provider.deploy(context, app);\n }\n\n // Collect secrets\n this.info(` Resolving secrets for ${app.name} from ${provider.name}...`);\n try {\n const appSecrets = await provider.getSecrets(context, app);\n Object.assign(secrets, appSecrets);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve secrets for ${app.name} (${provider.name}): ${message}`);\n }\n\n // Collect variables\n this.info(` Resolving variables for ${app.name} from ${provider.name}...`);\n try {\n const appVars = await provider.getVariables(context, app);\n Object.assign(variables, appVars);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve variables for ${app.name} (${provider.name}): ${message}`);\n }\n\n activeApps.push({ provider, app });\n }),\n );\n\n // Configure Repo\n this.info(`Configuring Repository with ${repoProvider.name}...`);\n await repoProvider.configureSecrets(context, secrets);\n await repoProvider.configureVariables(context, variables);\n\n // Generate Workflows\n this.info('Generating CI/CD Workflows...');\n await repoProvider.generateWorkflow(context, activeApps);\n\n // DNS Provisioning\n const dnsConfig = config.deploy?.dns;\n if (dnsConfig?.provider) {\n const dnsProvider = registry.getDnsProvider(dnsConfig.provider);\n if (!dnsProvider) {\n this.error(`DNS provider '${dnsConfig.provider}' not found.`);\n return;\n }\n\n const dnsRecords: DnsRecord[] = [];\n for (const { app, provider } of activeApps) {\n const target =\n app.dnsTarget ||\n (provider.getDefaultDnsTarget ? provider.getDefaultDnsTarget(app) : undefined);\n\n if (app.domain && target) {\n const domains = Array.isArray(app.domain) ? app.domain : [app.domain];\n for (const domain of domains) {\n const isIp = /^(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$/.test(target);\n dnsRecords.push({\n type: isIp ? 'A' : 'CNAME',\n name: domain,\n content: target,\n proxied: true,\n });\n }\n } else if (app.domain && !target) {\n this.warn(\n `App '${app.name}' specifies domain(s) but no 'dnsTarget' could be inferred. Skipping DNS auto-provisioning.`,\n );\n }\n }\n\n if (dnsRecords.length > 0) {\n this.info(`Configuring DNS with ${dnsProvider.name}...`);\n try {\n await dnsProvider.provision(context, dnsRecords);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.warn(`DNS provisioning failed: ${message}`);\n }\n }\n }\n\n this.success('Deployment configuration complete!');\n }\n}\n"],"mappings":"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","names":[]}
@@ -94,6 +94,13 @@ declare const DeploymentSchema: z.ZodObject<{
94
94
  dnsTarget: z.ZodOptional<z.ZodString>;
95
95
  }, z.ZodTypeAny, "passthrough">>>>;
96
96
  }, "strip", z.ZodTypeAny, {
97
+ dns?: z.objectOutputType<{
98
+ provider: z.ZodString;
99
+ }, z.ZodTypeAny, "passthrough"> | undefined;
100
+ repository?: {
101
+ provider: string;
102
+ options?: Record<string, any> | undefined;
103
+ } | undefined;
97
104
  apps?: Record<string, z.objectOutputType<{
98
105
  provider: z.ZodString;
99
106
  projectName: z.ZodOptional<z.ZodString>;
@@ -107,14 +114,14 @@ declare const DeploymentSchema: z.ZodObject<{
107
114
  domain: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
108
115
  dnsTarget: z.ZodOptional<z.ZodString>;
109
116
  }, z.ZodTypeAny, "passthrough">> | undefined;
110
- dns?: z.objectOutputType<{
117
+ }, {
118
+ dns?: z.objectInputType<{
111
119
  provider: z.ZodString;
112
120
  }, z.ZodTypeAny, "passthrough"> | undefined;
113
121
  repository?: {
114
122
  provider: string;
115
123
  options?: Record<string, any> | undefined;
116
124
  } | undefined;
117
- }, {
118
125
  apps?: Record<string, z.objectInputType<{
119
126
  provider: z.ZodString;
120
127
  projectName: z.ZodOptional<z.ZodString>;
@@ -128,16 +135,16 @@ declare const DeploymentSchema: z.ZodObject<{
128
135
  domain: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
129
136
  dnsTarget: z.ZodOptional<z.ZodString>;
130
137
  }, z.ZodTypeAny, "passthrough">> | undefined;
131
- dns?: z.objectInputType<{
138
+ }>>;
139
+ }, "strip", z.ZodTypeAny, {
140
+ deploy?: {
141
+ dns?: z.objectOutputType<{
132
142
  provider: z.ZodString;
133
143
  }, z.ZodTypeAny, "passthrough"> | undefined;
134
144
  repository?: {
135
145
  provider: string;
136
146
  options?: Record<string, any> | undefined;
137
147
  } | undefined;
138
- }>>;
139
- }, "strip", z.ZodTypeAny, {
140
- deploy?: {
141
148
  apps?: Record<string, z.objectOutputType<{
142
149
  provider: z.ZodString;
143
150
  projectName: z.ZodOptional<z.ZodString>;
@@ -151,16 +158,16 @@ declare const DeploymentSchema: z.ZodObject<{
151
158
  domain: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
152
159
  dnsTarget: z.ZodOptional<z.ZodString>;
153
160
  }, z.ZodTypeAny, "passthrough">> | undefined;
154
- dns?: z.objectOutputType<{
161
+ } | undefined;
162
+ }, {
163
+ deploy?: {
164
+ dns?: z.objectInputType<{
155
165
  provider: z.ZodString;
156
166
  }, z.ZodTypeAny, "passthrough"> | undefined;
157
167
  repository?: {
158
168
  provider: string;
159
169
  options?: Record<string, any> | undefined;
160
170
  } | undefined;
161
- } | undefined;
162
- }, {
163
- deploy?: {
164
171
  apps?: Record<string, z.objectInputType<{
165
172
  provider: z.ZodString;
166
173
  projectName: z.ZodOptional<z.ZodString>;
@@ -174,13 +181,6 @@ declare const DeploymentSchema: z.ZodObject<{
174
181
  domain: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodArray<z.ZodString, "many">]>>;
175
182
  dnsTarget: z.ZodOptional<z.ZodString>;
176
183
  }, z.ZodTypeAny, "passthrough">> | undefined;
177
- dns?: z.objectInputType<{
178
- provider: z.ZodString;
179
- }, z.ZodTypeAny, "passthrough"> | undefined;
180
- repository?: {
181
- provider: string;
182
- options?: Record<string, any> | undefined;
183
- } | undefined;
184
184
  } | undefined;
185
185
  }>;
186
186
  type ValidatedNexicalConfig = z.infer<typeof DeploymentSchema>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexical/cli",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "bin": {
@@ -133,12 +133,29 @@ PROCESS:
133
133
  // Build
134
134
  if (isManual && app.buildCommand) {
135
135
  this.info(` Building ${app.name} locally...`);
136
+
137
+ const buildEnv: Record<string, string> = {
138
+ ...(process.env as Record<string, string>),
139
+ ...(app.env || {}),
140
+ };
141
+
142
+ if (app.domain) {
143
+ const domain = Array.isArray(app.domain) ? app.domain[0] : app.domain;
144
+ buildEnv.SITE = `https://${domain}`;
145
+ buildEnv.BASE = '/';
146
+ }
147
+
136
148
  if (context.options.dryRun) {
137
149
  this.info(` [Dry Run] Would run build: ${app.buildCommand}`);
150
+ if (buildEnv.SITE) {
151
+ this.info(
152
+ ` [Dry Run] Environment override: SITE=${buildEnv.SITE} BASE=${buildEnv.BASE}`,
153
+ );
154
+ }
138
155
  } else {
139
156
  try {
140
157
  const { execAsync } = await import('../deploy/utils');
141
- await execAsync(app.buildCommand);
158
+ await execAsync(app.buildCommand, { env: buildEnv });
142
159
  } catch (e: unknown) {
143
160
  const message = e instanceof Error ? e.message : String(e);
144
161
  this.error(`Build failed for ${app.name}: ${message}`);