@nexical/cli 0.11.3 → 0.11.5

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.
Files changed (43) hide show
  1. package/dist/chunk-2FKDEDDE.js +39 -0
  2. package/dist/chunk-2FKDEDDE.js.map +1 -0
  3. package/dist/chunk-2JW5BYZW.js +24 -0
  4. package/dist/chunk-2JW5BYZW.js.map +1 -0
  5. package/dist/chunk-EKCOW7FM.js +118 -0
  6. package/dist/chunk-EKCOW7FM.js.map +1 -0
  7. package/dist/index.js +13 -11
  8. package/dist/index.js.map +1 -1
  9. package/dist/src/commands/deploy.d.ts +3 -12
  10. package/dist/src/commands/deploy.js +106 -108
  11. package/dist/src/commands/deploy.js.map +1 -1
  12. package/dist/src/commands/init.js +3 -3
  13. package/dist/src/commands/module/add.js +3 -3
  14. package/dist/src/deploy/config-manager.d.ts +11 -0
  15. package/dist/src/deploy/config-manager.js +9 -0
  16. package/dist/src/deploy/config-manager.js.map +1 -0
  17. package/dist/src/deploy/providers/cloudflare.d.ts +12 -0
  18. package/dist/src/deploy/providers/cloudflare.js +113 -0
  19. package/dist/src/deploy/providers/cloudflare.js.map +1 -0
  20. package/dist/src/deploy/providers/github.d.ts +10 -0
  21. package/dist/src/deploy/providers/github.js +121 -0
  22. package/dist/src/deploy/providers/github.js.map +1 -0
  23. package/dist/src/deploy/providers/railway.d.ts +12 -0
  24. package/dist/src/deploy/providers/railway.js +89 -0
  25. package/dist/src/deploy/providers/railway.js.map +1 -0
  26. package/dist/src/deploy/registry.d.ts +15 -0
  27. package/dist/src/deploy/registry.js +9 -0
  28. package/dist/src/deploy/registry.js.map +1 -0
  29. package/dist/src/deploy/types.d.ts +47 -0
  30. package/dist/src/deploy/types.js +8 -0
  31. package/dist/src/deploy/types.js.map +1 -0
  32. package/dist/src/deploy/utils.d.ts +6 -0
  33. package/dist/src/deploy/utils.js +11 -0
  34. package/dist/src/deploy/utils.js.map +1 -0
  35. package/package.json +13 -11
  36. package/src/commands/deploy.ts +128 -144
  37. package/src/deploy/config-manager.ts +41 -0
  38. package/src/deploy/providers/cloudflare.ts +143 -0
  39. package/src/deploy/providers/github.ts +135 -0
  40. package/src/deploy/providers/railway.ts +103 -0
  41. package/src/deploy/registry.ts +136 -0
  42. package/src/deploy/types.ts +63 -0
  43. package/src/deploy/utils.ts +13 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/commands/deploy.ts"],"sourcesContent":["import { BaseCommand, runCommand } from '@nexical/cli-core';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\ninterface DeployOptions {\n dryRun: boolean;\n railwayToken?: string;\n cloudflareToken?: string;\n cloudflareAccount?: string;\n}\n\nexport default class DeployCommand extends BaseCommand {\n static description = 'Deploy the application to Railway and Cloudflare.';\n\n static args = {\n options: [\n {\n name: '--dry-run',\n description: 'Simulate the deployment process without making changes.',\n default: false,\n },\n {\n name: '--railway-token <token>',\n description: 'Railway Project Token (optional if already logged in).',\n },\n {\n name: '--cloudflare-token <token>',\n description: 'Cloudflare API Token.',\n },\n {\n name: '--cloudflare-account <id>',\n description: 'Cloudflare Account ID.',\n },\n ],\n };\n\n async run(options: DeployOptions) {\n this.info('Starting Nexical Deployment Automation...');\n\n if (options.dryRun) {\n this.notice('DRY RUN MODE ENABLED');\n }\n\n try {\n // 1. Railway Setup\n await this.setupRailway(options);\n\n // 2. Cloudflare Setup\n await this.setupCloudflare(options);\n\n // 3. GitHub Secrets Setup\n await this.setupGitHubSecrets(options);\n\n this.success('Deployment setup complete! Your application is being deployed.');\n } catch (error: unknown) {\n if (error instanceof Error) {\n this.error(`Deployment failed: ${error.message}`);\n } else {\n this.error(`Deployment failed: ${String(error)}`);\n }\n process.exit(1);\n }\n }\n\n private async setupRailway(options: DeployOptions) {\n this.info('Configuring Railway...');\n\n if (options.dryRun) {\n this.info('[Dry Run] Would run: railway init');\n this.info('[Dry Run] Would run: railway add --database postgres');\n return;\n }\n\n try {\n // Check if railway project exists or init\n // Note: railway init might be interactive, so we might need to handle that or assume user has linked.\n // For now, let's assume we use 'railway link' if they passed a token or have it set.\n\n this.info('Ensuring Railway project is linked...');\n // If they provided a token, we should probably set it in the environment for subsequent calls\n if (options.railwayToken) {\n process.env.RAILWAY_TOKEN = options.railwayToken;\n }\n\n // Check if we are in a railway project\n try {\n await runCommand('railway status');\n } catch {\n this.info('No Railway project detected. Initializing...');\n await runCommand('railway init');\n }\n\n this.info('Adding PostgreSQL service if missing...');\n // railway add --database postgres is usually safe to run twice but we should check status\n const { stdout: status } = await execAsync('railway status');\n if (!status.includes('postgres')) {\n await runCommand('railway add --database postgres');\n }\n } catch (e: unknown) {\n this.warn(\n 'Railway setup encountered an issue. Ensure you are logged in with `railway login`.',\n );\n throw e;\n }\n }\n\n private async setupCloudflare(options: DeployOptions) {\n this.info('Configuring Cloudflare Pages...');\n\n if (options.dryRun) {\n this.info('[Dry Run] Would run: wrangler pages project create nexical-frontend');\n return;\n }\n\n if (!options.cloudflareToken || !options.cloudflareAccount) {\n this.warn('Cloudflare credentials missing. Skipping automated Cloudflare setup.');\n this.info('You can manually set up Cloudflare Pages and add the secrets to GitHub.');\n return;\n }\n\n try {\n // Use wrangler to create project if it doesn't exist\n // We assume project name 'nexical-frontend' for now, should be configurable.\n const projectName = 'nexical-frontend';\n this.info(`Ensuring Cloudflare Pages project \"${projectName}\" exists...`);\n\n try {\n await execAsync(`wrangler pages project create ${projectName} --production-branch main`, {\n env: {\n ...process.env,\n CLOUDFLARE_API_TOKEN: options.cloudflareToken,\n CLOUDFLARE_ACCOUNT_ID: options.cloudflareAccount,\n },\n });\n } catch {\n this.info('Cloudflare project might already exist.');\n }\n } catch (e: unknown) {\n this.warn('Cloudflare setup failed.');\n throw e;\n }\n }\n\n private async setupGitHubSecrets(options: DeployOptions) {\n this.info('Configuring GitHub Secrets...');\n\n if (options.dryRun) {\n this.info('[Dry Run] Would run: gh secret set RAILWAY_TOKEN');\n this.info('[Dry Run] Would run: gh secret set CLOUDFLARE_API_TOKEN');\n this.info('[Dry Run] Would run: gh secret set CLOUDFLARE_ACCOUNT_ID');\n return;\n }\n\n try {\n // We need the Railway Project Token.\n // User might have provided it, or we try to get it from railway tokens?\n // Railway CLI doesn't easily expose the project token via CLI easily without a lot of parsing.\n // Usually users generate it in the UI.\n // If they provided it via --railway-token, we use it.\n\n if (options.railwayToken) {\n this.info('Setting RAILWAY_TOKEN in GitHub...');\n await runCommand(`gh secret set RAILWAY_TOKEN --body \"${options.railwayToken}\"`);\n }\n\n if (options.cloudflareToken) {\n this.info('Setting CLOUDFLARE_API_TOKEN in GitHub...');\n await runCommand(`gh secret set CLOUDFLARE_API_TOKEN --body \"${options.cloudflareToken}\"`);\n }\n\n if (options.cloudflareAccount) {\n this.info('Setting CLOUDFLARE_ACCOUNT_ID in GitHub...');\n await runCommand(\n `gh secret set CLOUDFLARE_ACCOUNT_ID --body \"${options.cloudflareAccount}\"`,\n );\n }\n } catch (e: unknown) {\n this.warn(\n 'GitHub Secrets setup failed. Ensure you have the GitHub CLI (gh) installed and are logged in.',\n );\n throw e;\n }\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 } from '../deploy/types';\n\nexport default class DeployCommand extends BaseCommand {\n static description = `Deploy the application based on nexical.yaml configuration.\n\nThis command orchestrates the deployment of your frontend and backend applications \nby interacting with the providers specified in your configuration file.\n\nCONFIGURATION:\n- Requires a 'nexical.yaml' file in the project root.\n- If the file or specific sections are missing, the CLI will prompt you to run an interactive setup \n and save the configuration for future uses.\n- Supports loading environment variables from a .env file in the project root.\n\nPROVIDERS:\n- Backend: Railway, etc.\n- Frontend: Cloudflare Pages, etc.\n- Repository: GitHub, GitLab, etc.\n\nPROCESS:\n1. Loads environment variables from '.env'.\n2. Loads configuration from 'nexical.yaml'.\n3. Provisions resources via the selected providers.\n4. Configures the repository (secrets/variables) for CI/CD.\n5. Generates CI/CD workflow files.`;\n\n static args = {\n options: [\n {\n name: '--backend <provider>',\n description: 'Override backend provider',\n },\n {\n name: '--frontend <provider>',\n description: 'Override frontend provider',\n },\n {\n name: '--repo <provider>',\n description: 'Override repositroy provider',\n },\n {\n name: '--dry-run',\n description: 'Simulate the deployment process',\n default: false,\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') });\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 providers (CLI flags > Config > Error)\n const backendProviderName =\n (options.backend as string | undefined) || config.deploy?.backend?.provider;\n if (!backendProviderName) {\n this.error(\n \"Backend provider not specified. Use --backend flag or configure 'deploy.backend.provider' in nexical.yaml.\",\n );\n }\n\n const frontendProviderName =\n (options.frontend as string | undefined) || config.deploy?.frontend?.provider;\n if (!frontendProviderName) {\n this.error(\n \"Frontend provider not specified. Use --frontend flag or configure 'deploy.frontend.provider' in nexical.yaml.\",\n );\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 backendProvider = registry.getDeploymentProvider(backendProviderName!);\n const frontendProvider = registry.getDeploymentProvider(frontendProviderName!);\n const repoProvider = registry.getRepositoryProvider(repoProviderName!);\n\n if (!backendProvider) throw new Error(`Backend provider '${backendProviderName}' not found.`);\n if (!frontendProvider)\n throw new Error(`Frontend provider '${frontendProviderName}' not found.`);\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 // Provision\n this.info(`Provisioning Backend with ${backendProvider.name}...`);\n await backendProvider.provision(context);\n\n this.info(`Provisioning Frontend with ${frontendProvider.name}...`);\n await frontendProvider.provision(context);\n\n // Configure Repo\n this.info(`Configuring Repository with ${repoProvider.name}...`);\n\n const secrets: Record<string, string> = {};\n\n // Collect secrets from Backend Provider\n this.info(`Resolving secrets from ${backendProvider.name}...`);\n try {\n const backendSecrets = await backendProvider.getSecrets(context);\n Object.assign(secrets, backendSecrets);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve secrets for ${backendProvider.name}: ${message}`);\n }\n\n // Collect secrets from Frontend Provider\n this.info(`Resolving secrets from ${frontendProvider.name}...`);\n try {\n const frontendSecrets = await frontendProvider.getSecrets(context);\n Object.assign(secrets, frontendSecrets);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve secrets for ${frontendProvider.name}: ${message}`);\n }\n\n await repoProvider.configureSecrets(context, secrets);\n\n const variables: Record<string, string> = {};\n\n // Collect variables from Backend Provider\n try {\n const backendVars = await backendProvider.getVariables(context);\n Object.assign(variables, backendVars);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve variables for ${backendProvider.name}: ${message}`);\n }\n\n // Collect variables from Frontend Provider\n try {\n const frontendVars = await frontendProvider.getVariables(context);\n Object.assign(variables, frontendVars);\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n this.error(`Failed to resolve variables for ${frontendProvider.name}: ${message}`);\n }\n\n await repoProvider.configureVariables(context, variables);\n\n // Generate Workflows\n this.info('Generating CI/CD Workflows...');\n await repoProvider.generateWorkflow(context, [backendProvider, frontendProvider]);\n\n this.success('Deployment configuration complete!');\n }\n}\n"],"mappings":"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","names":[]}
@@ -1,7 +1,4 @@
1
1
  import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
- import {
3
- require_lib
4
- } from "../../chunk-LZ3YQWAR.js";
5
2
  import {
6
3
  addAll,
7
4
  clone,
@@ -12,6 +9,9 @@ import {
12
9
  import {
13
10
  resolveGitUrl
14
11
  } from "../../chunk-PJIOCW2A.js";
12
+ import {
13
+ require_lib
14
+ } from "../../chunk-LZ3YQWAR.js";
15
15
  import {
16
16
  __toESM,
17
17
  init_esm_shims
@@ -1,7 +1,4 @@
1
1
  import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
- import {
3
- require_lib
4
- } from "../../../chunk-LZ3YQWAR.js";
5
2
  import {
6
3
  clone,
7
4
  getRemoteUrl
@@ -9,6 +6,9 @@ import {
9
6
  import {
10
7
  resolveGitUrl
11
8
  } from "../../../chunk-PJIOCW2A.js";
9
+ import {
10
+ require_lib
11
+ } from "../../../chunk-LZ3YQWAR.js";
12
12
  import {
13
13
  __toESM,
14
14
  init_esm_shims
@@ -0,0 +1,11 @@
1
+ import { NexicalConfig } from './types.js';
2
+
3
+ declare class ConfigManager {
4
+ private configPath;
5
+ constructor(cwd: string);
6
+ load(): Promise<NexicalConfig>;
7
+ save(config: NexicalConfig): Promise<void>;
8
+ exists(): Promise<boolean>;
9
+ }
10
+
11
+ export { ConfigManager };
@@ -0,0 +1,9 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ ConfigManager
4
+ } from "../../chunk-2FKDEDDE.js";
5
+ import "../../chunk-OYFWMYPG.js";
6
+ export {
7
+ ConfigManager
8
+ };
9
+ //# sourceMappingURL=config-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,12 @@
1
+ import { DeploymentProvider, DeploymentContext, CIConfig } from '../types.js';
2
+
3
+ declare class CloudflareProvider implements DeploymentProvider {
4
+ name: string;
5
+ type: "frontend";
6
+ provision(context: DeploymentContext): Promise<void>;
7
+ getSecrets(context: DeploymentContext): Promise<Record<string, string>>;
8
+ getVariables(context: DeploymentContext): Promise<Record<string, string>>;
9
+ getCIConfig(): CIConfig;
10
+ }
11
+
12
+ export { CloudflareProvider };
@@ -0,0 +1,113 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ execAsync
4
+ } from "../../../chunk-2JW5BYZW.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "../../../chunk-OYFWMYPG.js";
8
+
9
+ // src/deploy/providers/cloudflare.ts
10
+ init_esm_shims();
11
+ import { logger } from "@nexical/cli-core";
12
+ var CloudflareProvider = class {
13
+ name = "cloudflare";
14
+ type = "frontend";
15
+ async provision(context) {
16
+ const projectName = context.config.deploy?.frontend?.projectName;
17
+ if (!projectName) {
18
+ throw new Error(
19
+ "Cloudflare project name not found in nexical.yaml. Please configure 'deploy.frontend.projectName'."
20
+ );
21
+ }
22
+ const options = context.config.deploy?.frontend?.options || {};
23
+ const apiTokenEnvVar = typeof options.apiTokenEnvVar === "string" ? options.apiTokenEnvVar : void 0;
24
+ const apiToken = (typeof context.options.cloudflareToken === "string" ? context.options.cloudflareToken : void 0) || (apiTokenEnvVar ? process.env[apiTokenEnvVar] : void 0) || process.env.CLOUDFLARE_API_TOKEN;
25
+ const accountIdEnvVar = typeof options.accountIdEnvVar === "string" ? options.accountIdEnvVar : void 0;
26
+ const accountId = (typeof context.options.cloudflareAccount === "string" ? context.options.cloudflareAccount : void 0) || (accountIdEnvVar ? process.env[accountIdEnvVar] : void 0) || process.env.CLOUDFLARE_ACCOUNT_ID;
27
+ logger.info("Configuring Cloudflare Pages...");
28
+ if (context.options.dryRun) {
29
+ logger.info("[Dry Run] Would check Cloudflare Pages project and create if missing.");
30
+ return;
31
+ }
32
+ if (!apiToken || !accountId) {
33
+ logger.warn("Cloudflare credentials missing. Skipping automated Cloudflare setup.");
34
+ logger.info("You can manually set up Cloudflare Pages and add the secrets to GitHub.");
35
+ return;
36
+ }
37
+ try {
38
+ logger.info(`Ensuring Cloudflare Pages project "${projectName}" exists...`);
39
+ try {
40
+ await execAsync(`wrangler pages project create ${projectName} --production-branch main`, {
41
+ env: {
42
+ ...process.env,
43
+ CLOUDFLARE_API_TOKEN: apiToken,
44
+ CLOUDFLARE_ACCOUNT_ID: accountId
45
+ }
46
+ });
47
+ } catch {
48
+ logger.info("Cloudflare project might already exist.");
49
+ }
50
+ } catch (e) {
51
+ logger.warn("Cloudflare setup failed.");
52
+ throw e;
53
+ }
54
+ }
55
+ async getSecrets(context) {
56
+ const options = context.config.deploy?.frontend?.options || {};
57
+ const secrets = {};
58
+ const apiTokenEnvVar = typeof options.apiTokenEnvVar === "string" ? options.apiTokenEnvVar : void 0;
59
+ const apiToken = (apiTokenEnvVar ? process.env[apiTokenEnvVar] : void 0) || process.env.CLOUDFLARE_API_TOKEN;
60
+ if (!apiToken) {
61
+ throw new Error(
62
+ `Cloudflare API Token not found. Please provide it via:
63
+ 1. Configuring 'deploy.frontend.options.apiTokenEnvVar' in nexical.yaml and setting that env var in .env
64
+ 2. Setting CLOUDFLARE_API_TOKEN in .env`
65
+ );
66
+ }
67
+ secrets["CLOUDFLARE_API_TOKEN"] = apiToken;
68
+ const accountIdEnvVar = typeof options.accountIdEnvVar === "string" ? options.accountIdEnvVar : void 0;
69
+ const accountId = (accountIdEnvVar ? process.env[accountIdEnvVar] : void 0) || process.env.CLOUDFLARE_ACCOUNT_ID;
70
+ if (!accountId) {
71
+ throw new Error(
72
+ `Cloudflare Account ID not found. Please provide it via:
73
+ 1. Configuring 'deploy.frontend.options.accountIdEnvVar' in nexical.yaml and setting that env var in .env
74
+ 2. Setting CLOUDFLARE_ACCOUNT_ID in .env`
75
+ );
76
+ }
77
+ secrets["CLOUDFLARE_ACCOUNT_ID"] = accountId;
78
+ return secrets;
79
+ }
80
+ async getVariables(context) {
81
+ const projectName = context.config.deploy?.frontend?.projectName;
82
+ if (!projectName) {
83
+ throw new Error(
84
+ "Cloudflare project name not found in nexical.yaml. Please configure 'deploy.frontend.projectName'."
85
+ );
86
+ }
87
+ return {
88
+ CLOUDFLARE_PROJECT_NAME: projectName
89
+ };
90
+ }
91
+ getCIConfig() {
92
+ return {
93
+ secrets: ["CLOUDFLARE_API_TOKEN", "CLOUDFLARE_ACCOUNT_ID"],
94
+ variables: ["CLOUDFLARE_PROJECT_NAME"],
95
+ deploySteps: [],
96
+ // Handled by action
97
+ githubActionStep: {
98
+ name: "Deploy to Cloudflare Pages",
99
+ uses: "cloudflare/wrangler-action@v3",
100
+ with: {
101
+ apiToken: "${{ secrets.CLOUDFLARE_API_TOKEN }}",
102
+ accountId: "${{ secrets.CLOUDFLARE_ACCOUNT_ID }}",
103
+ command: "pages deploy dist --project-name=${{ vars.CLOUDFLARE_PROJECT_NAME }}",
104
+ workingDirectory: "apps/frontend"
105
+ }
106
+ }
107
+ };
108
+ }
109
+ };
110
+ export {
111
+ CloudflareProvider
112
+ };
113
+ //# sourceMappingURL=cloudflare.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/deploy/providers/cloudflare.ts"],"sourcesContent":["import { logger } from '@nexical/cli-core';\nimport { DeploymentProvider, DeploymentContext, CIConfig } from '../types';\nimport { execAsync } from '../utils';\n\nexport class CloudflareProvider implements DeploymentProvider {\n name = 'cloudflare';\n type = 'frontend' as const;\n\n async provision(context: DeploymentContext): Promise<void> {\n const projectName = context.config.deploy?.frontend?.projectName;\n\n if (!projectName) {\n throw new Error(\n \"Cloudflare project name not found in nexical.yaml. Please configure 'deploy.frontend.projectName'.\",\n );\n }\n\n const options = context.config.deploy?.frontend?.options || {};\n\n // Resolve credentials:\n // 1. CLI flag (options)\n // 2. Env var defined in config (options.apiTokenEnvVar)\n // 3. Default env var (CLOUDFLARE_API_TOKEN)\n const apiTokenEnvVar =\n typeof options.apiTokenEnvVar === 'string' ? options.apiTokenEnvVar : undefined;\n const apiToken =\n (typeof context.options.cloudflareToken === 'string'\n ? context.options.cloudflareToken\n : undefined) ||\n (apiTokenEnvVar ? process.env[apiTokenEnvVar] : undefined) ||\n process.env.CLOUDFLARE_API_TOKEN;\n\n const accountIdEnvVar =\n typeof options.accountIdEnvVar === 'string' ? options.accountIdEnvVar : undefined;\n const accountId =\n (typeof context.options.cloudflareAccount === 'string'\n ? context.options.cloudflareAccount\n : undefined) ||\n (accountIdEnvVar ? process.env[accountIdEnvVar] : undefined) ||\n process.env.CLOUDFLARE_ACCOUNT_ID;\n\n logger.info('Configuring Cloudflare Pages...');\n\n if (context.options.dryRun) {\n logger.info('[Dry Run] Would check Cloudflare Pages project and create if missing.');\n return;\n }\n\n if (!apiToken || !accountId) {\n logger.warn('Cloudflare credentials missing. Skipping automated Cloudflare setup.');\n logger.info('You can manually set up Cloudflare Pages and add the secrets to GitHub.');\n return;\n }\n\n try {\n logger.info(`Ensuring Cloudflare Pages project \"${projectName}\" exists...`);\n try {\n await execAsync(`wrangler pages project create ${projectName} --production-branch main`, {\n env: {\n ...process.env,\n CLOUDFLARE_API_TOKEN: apiToken,\n CLOUDFLARE_ACCOUNT_ID: accountId,\n },\n });\n } catch {\n logger.info('Cloudflare project might already exist.');\n }\n } catch (e: unknown) {\n logger.warn('Cloudflare setup failed.');\n throw e;\n }\n }\n\n async getSecrets(context: DeploymentContext): Promise<Record<string, string>> {\n const options = context.config.deploy?.frontend?.options || {};\n const secrets: Record<string, string> = {};\n\n // Resolve API Token\n const apiTokenEnvVar =\n typeof options.apiTokenEnvVar === 'string' ? options.apiTokenEnvVar : undefined;\n const apiToken =\n (apiTokenEnvVar ? process.env[apiTokenEnvVar] : undefined) ||\n process.env.CLOUDFLARE_API_TOKEN;\n\n if (!apiToken) {\n throw new Error(\n `Cloudflare API Token not found. Please provide it via:\\n` +\n `1. Configuring 'deploy.frontend.options.apiTokenEnvVar' in nexical.yaml and setting that env var in .env\\n` +\n `2. Setting CLOUDFLARE_API_TOKEN in .env`,\n );\n }\n secrets['CLOUDFLARE_API_TOKEN'] = apiToken;\n\n // Resolve Account ID\n const accountIdEnvVar =\n typeof options.accountIdEnvVar === 'string' ? options.accountIdEnvVar : undefined;\n const accountId =\n (accountIdEnvVar ? process.env[accountIdEnvVar] : undefined) ||\n process.env.CLOUDFLARE_ACCOUNT_ID;\n\n if (!accountId) {\n throw new Error(\n `Cloudflare Account ID not found. Please provide it via:\\n` +\n `1. Configuring 'deploy.frontend.options.accountIdEnvVar' in nexical.yaml and setting that env var in .env\\n` +\n `2. Setting CLOUDFLARE_ACCOUNT_ID in .env`,\n );\n }\n secrets['CLOUDFLARE_ACCOUNT_ID'] = accountId;\n\n return secrets;\n }\n\n async getVariables(context: DeploymentContext): Promise<Record<string, string>> {\n const projectName = context.config.deploy?.frontend?.projectName;\n\n if (!projectName) {\n throw new Error(\n \"Cloudflare project name not found in nexical.yaml. Please configure 'deploy.frontend.projectName'.\",\n );\n }\n return {\n CLOUDFLARE_PROJECT_NAME: projectName,\n };\n }\n\n getCIConfig(): CIConfig {\n return {\n secrets: ['CLOUDFLARE_API_TOKEN', 'CLOUDFLARE_ACCOUNT_ID'],\n variables: ['CLOUDFLARE_PROJECT_NAME'],\n deploySteps: [], // Handled by action\n githubActionStep: {\n name: 'Deploy to Cloudflare Pages',\n uses: 'cloudflare/wrangler-action@v3',\n with: {\n apiToken: '${{ secrets.CLOUDFLARE_API_TOKEN }}',\n accountId: '${{ secrets.CLOUDFLARE_ACCOUNT_ID }}',\n command: 'pages deploy dist --project-name=${{ vars.CLOUDFLARE_PROJECT_NAME }}',\n workingDirectory: 'apps/frontend',\n },\n },\n };\n }\n}\n"],"mappings":";;;;;;;;;AAAA;AAAA,SAAS,cAAc;AAIhB,IAAM,qBAAN,MAAuD;AAAA,EAC5D,OAAO;AAAA,EACP,OAAO;AAAA,EAEP,MAAM,UAAU,SAA2C;AACzD,UAAM,cAAc,QAAQ,OAAO,QAAQ,UAAU;AAErD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAAU,QAAQ,OAAO,QAAQ,UAAU,WAAW,CAAC;AAM7D,UAAM,iBACJ,OAAO,QAAQ,mBAAmB,WAAW,QAAQ,iBAAiB;AACxE,UAAM,YACH,OAAO,QAAQ,QAAQ,oBAAoB,WACxC,QAAQ,QAAQ,kBAChB,YACH,iBAAiB,QAAQ,IAAI,cAAc,IAAI,WAChD,QAAQ,IAAI;AAEd,UAAM,kBACJ,OAAO,QAAQ,oBAAoB,WAAW,QAAQ,kBAAkB;AAC1E,UAAM,aACH,OAAO,QAAQ,QAAQ,sBAAsB,WAC1C,QAAQ,QAAQ,oBAChB,YACH,kBAAkB,QAAQ,IAAI,eAAe,IAAI,WAClD,QAAQ,IAAI;AAEd,WAAO,KAAK,iCAAiC;AAE7C,QAAI,QAAQ,QAAQ,QAAQ;AAC1B,aAAO,KAAK,uEAAuE;AACnF;AAAA,IACF;AAEA,QAAI,CAAC,YAAY,CAAC,WAAW;AAC3B,aAAO,KAAK,sEAAsE;AAClF,aAAO,KAAK,yEAAyE;AACrF;AAAA,IACF;AAEA,QAAI;AACF,aAAO,KAAK,sCAAsC,WAAW,aAAa;AAC1E,UAAI;AACF,cAAM,UAAU,iCAAiC,WAAW,6BAA6B;AAAA,UACvF,KAAK;AAAA,YACH,GAAG,QAAQ;AAAA,YACX,sBAAsB;AAAA,YACtB,uBAAuB;AAAA,UACzB;AAAA,QACF,CAAC;AAAA,MACH,QAAQ;AACN,eAAO,KAAK,yCAAyC;AAAA,MACvD;AAAA,IACF,SAAS,GAAY;AACnB,aAAO,KAAK,0BAA0B;AACtC,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAA6D;AAC5E,UAAM,UAAU,QAAQ,OAAO,QAAQ,UAAU,WAAW,CAAC;AAC7D,UAAM,UAAkC,CAAC;AAGzC,UAAM,iBACJ,OAAO,QAAQ,mBAAmB,WAAW,QAAQ,iBAAiB;AACxE,UAAM,YACH,iBAAiB,QAAQ,IAAI,cAAc,IAAI,WAChD,QAAQ,IAAI;AAEd,QAAI,CAAC,UAAU;AACb,YAAM,IAAI;AAAA,QACR;AAAA;AAAA;AAAA,MAGF;AAAA,IACF;AACA,YAAQ,sBAAsB,IAAI;AAGlC,UAAM,kBACJ,OAAO,QAAQ,oBAAoB,WAAW,QAAQ,kBAAkB;AAC1E,UAAM,aACH,kBAAkB,QAAQ,IAAI,eAAe,IAAI,WAClD,QAAQ,IAAI;AAEd,QAAI,CAAC,WAAW;AACd,YAAM,IAAI;AAAA,QACR;AAAA;AAAA;AAAA,MAGF;AAAA,IACF;AACA,YAAQ,uBAAuB,IAAI;AAEnC,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,SAA6D;AAC9E,UAAM,cAAc,QAAQ,OAAO,QAAQ,UAAU;AAErD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,MACL,yBAAyB;AAAA,IAC3B;AAAA,EACF;AAAA,EAEA,cAAwB;AACtB,WAAO;AAAA,MACL,SAAS,CAAC,wBAAwB,uBAAuB;AAAA,MACzD,WAAW,CAAC,yBAAyB;AAAA,MACrC,aAAa,CAAC;AAAA;AAAA,MACd,kBAAkB;AAAA,QAChB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,UACJ,UAAU;AAAA,UACV,WAAW;AAAA,UACX,SAAS;AAAA,UACT,kBAAkB;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,10 @@
1
+ import { RepositoryProvider, DeploymentContext, DeploymentProvider } from '../types.js';
2
+
3
+ declare class GitHubProvider implements RepositoryProvider {
4
+ name: string;
5
+ configureSecrets(context: DeploymentContext, secrets: Record<string, string>): Promise<void>;
6
+ configureVariables(context: DeploymentContext, variables: Record<string, string>): Promise<void>;
7
+ generateWorkflow(context: DeploymentContext, targets: DeploymentProvider[]): Promise<void>;
8
+ }
9
+
10
+ export { GitHubProvider };
@@ -0,0 +1,121 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ execAsync
4
+ } from "../../../chunk-2JW5BYZW.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "../../../chunk-OYFWMYPG.js";
8
+
9
+ // src/deploy/providers/github.ts
10
+ init_esm_shims();
11
+ import fs from "fs/promises";
12
+ import path from "path";
13
+ import YAML from "yaml";
14
+ import { logger } from "@nexical/cli-core";
15
+ var GitHubProvider = class {
16
+ name = "github";
17
+ async configureSecrets(context, secrets) {
18
+ for (const [key, value] of Object.entries(secrets)) {
19
+ if (!value) continue;
20
+ logger.info(`Setting secret ${key} in GitHub...`);
21
+ if (context.options.dryRun) {
22
+ logger.info(`[Dry Run] Would set secret ${key}`);
23
+ } else {
24
+ await execAsync(`gh secret set ${key} --body "${value}"`);
25
+ }
26
+ }
27
+ }
28
+ async configureVariables(context, variables) {
29
+ for (const [key, value] of Object.entries(variables)) {
30
+ if (!value) continue;
31
+ logger.info(`Setting variable ${key} in GitHub...`);
32
+ if (context.options.dryRun) {
33
+ logger.info(`[Dry Run] Would set variable ${key}`);
34
+ } else {
35
+ await execAsync(`gh variable set ${key} --body "${value}"`);
36
+ }
37
+ }
38
+ }
39
+ async generateWorkflow(context, targets) {
40
+ const workflowsDir = path.join(context.cwd, ".github/workflows");
41
+ await fs.mkdir(workflowsDir, { recursive: true });
42
+ for (const target of targets) {
43
+ const config = target.getCIConfig("github");
44
+ if (!config) continue;
45
+ const filename = `deploy-${target.type}.yml`;
46
+ const filepath = path.join(workflowsDir, filename);
47
+ const workflow = {
48
+ name: `Deploy ${target.type === "backend" ? "Backend" : "Frontend"} to ${target.name}`,
49
+ on: {
50
+ push: { branches: ["main"] },
51
+ workflow_dispatch: {}
52
+ },
53
+ jobs: {
54
+ deploy: {
55
+ "runs-on": "ubuntu-latest",
56
+ permissions: {
57
+ contents: "read",
58
+ deployments: "write"
59
+ },
60
+ steps: [
61
+ {
62
+ name: "Checkout",
63
+ uses: "actions/checkout@v4",
64
+ with: { submodules: "recursive" }
65
+ },
66
+ {
67
+ name: "Setup Node",
68
+ uses: "actions/setup-node@v4",
69
+ with: { "node-version": 20, cache: "npm" }
70
+ },
71
+ {
72
+ name: "Install Dependencies",
73
+ run: "npm ci"
74
+ }
75
+ ]
76
+ }
77
+ }
78
+ };
79
+ const steps = workflow.jobs.deploy.steps;
80
+ if (target.type === "frontend") {
81
+ steps.push({
82
+ name: "Build Frontend",
83
+ run: "npm run build --workspace=@app/frontend"
84
+ });
85
+ }
86
+ if (config.installSteps) {
87
+ for (const step of config.installSteps) {
88
+ steps.push({
89
+ name: `Install ${target.name} CLI`,
90
+ run: step
91
+ });
92
+ }
93
+ }
94
+ if (config.deploySteps) {
95
+ for (const step of config.deploySteps) {
96
+ const deployStep = {
97
+ name: `Deploy to ${target.name}`,
98
+ run: step,
99
+ "working-directory": target.type === "backend" ? "apps/backend" : "apps/frontend"
100
+ };
101
+ if (config.secrets && config.secrets.length > 0) {
102
+ deployStep.env = config.secrets.reduce((acc, secret) => {
103
+ acc[secret] = `\${{ secrets.${secret} }}`;
104
+ return acc;
105
+ }, {});
106
+ }
107
+ steps.push(deployStep);
108
+ }
109
+ }
110
+ if (config.githubActionStep) {
111
+ steps.push(config.githubActionStep);
112
+ }
113
+ await fs.writeFile(filepath, YAML.stringify(workflow), "utf-8");
114
+ logger.info(`Generated workflow: ${filepath}`);
115
+ }
116
+ }
117
+ };
118
+ export {
119
+ GitHubProvider
120
+ };
121
+ //# sourceMappingURL=github.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/deploy/providers/github.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport YAML from 'yaml';\nimport { logger } from '@nexical/cli-core';\nimport { RepositoryProvider, DeploymentContext, DeploymentProvider } from '../types';\nimport { execAsync } from '../utils';\n\nexport class GitHubProvider implements RepositoryProvider {\n name = 'github';\n\n async configureSecrets(\n context: DeploymentContext,\n secrets: Record<string, string>,\n ): Promise<void> {\n for (const [key, value] of Object.entries(secrets)) {\n if (!value) continue;\n logger.info(`Setting secret ${key} in GitHub...`);\n if (context.options.dryRun) {\n logger.info(`[Dry Run] Would set secret ${key}`);\n } else {\n await execAsync(`gh secret set ${key} --body \"${value}\"`);\n }\n }\n }\n\n async configureVariables(\n context: DeploymentContext,\n variables: Record<string, string>,\n ): Promise<void> {\n for (const [key, value] of Object.entries(variables)) {\n if (!value) continue;\n logger.info(`Setting variable ${key} in GitHub...`);\n if (context.options.dryRun) {\n logger.info(`[Dry Run] Would set variable ${key}`);\n } else {\n await execAsync(`gh variable set ${key} --body \"${value}\"`);\n }\n }\n }\n\n async generateWorkflow(context: DeploymentContext, targets: DeploymentProvider[]): Promise<void> {\n const workflowsDir = path.join(context.cwd, '.github/workflows');\n await fs.mkdir(workflowsDir, { recursive: true });\n\n for (const target of targets) {\n const config = target.getCIConfig('github');\n if (!config) continue;\n\n const filename = `deploy-${target.type}.yml`;\n const filepath = path.join(workflowsDir, filename);\n\n const workflow: Record<string, unknown> = {\n name: `Deploy ${target.type === 'backend' ? 'Backend' : 'Frontend'} to ${target.name}`,\n on: {\n push: { branches: ['main'] },\n workflow_dispatch: {},\n },\n jobs: {\n deploy: {\n 'runs-on': 'ubuntu-latest',\n permissions: {\n contents: 'read',\n deployments: 'write',\n },\n steps: [\n {\n name: 'Checkout',\n uses: 'actions/checkout@v4',\n with: { submodules: 'recursive' },\n },\n {\n name: 'Setup Node',\n uses: 'actions/setup-node@v4',\n with: { 'node-version': 20, cache: 'npm' },\n },\n {\n name: 'Install Dependencies',\n run: 'npm ci',\n },\n ],\n },\n },\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const steps = (workflow as any).jobs.deploy.steps;\n\n // Build (if frontend)\n if (target.type === 'frontend') {\n steps.push({\n name: 'Build Frontend',\n run: 'npm run build --workspace=@app/frontend',\n });\n }\n\n // Provider Install Steps\n if (config.installSteps) {\n for (const step of config.installSteps) {\n steps.push({\n name: `Install ${target.name} CLI`,\n run: step,\n });\n }\n }\n\n // Provider Deploy Steps\n if (config.deploySteps) {\n for (const step of config.deploySteps) {\n const deployStep: Record<string, unknown> = {\n name: `Deploy to ${target.name}`,\n run: step,\n 'working-directory': target.type === 'backend' ? 'apps/backend' : 'apps/frontend',\n };\n\n if (config.secrets && config.secrets.length > 0) {\n deployStep.env = config.secrets.reduce((acc: Record<string, string>, secret) => {\n acc[secret] = `\\${{ secrets.${secret} }}`;\n return acc;\n }, {});\n }\n\n steps.push(deployStep);\n }\n }\n\n // Provider Action Step\n if (config.githubActionStep) {\n steps.push(config.githubActionStep);\n }\n\n await fs.writeFile(filepath, YAML.stringify(workflow), 'utf-8');\n logger.info(`Generated workflow: ${filepath}`);\n }\n }\n}\n"],"mappings":";;;;;;;;;AAAA;AAAA,OAAO,QAAQ;AACf,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,SAAS,cAAc;AAIhB,IAAM,iBAAN,MAAmD;AAAA,EACxD,OAAO;AAAA,EAEP,MAAM,iBACJ,SACA,SACe;AACf,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,GAAG;AAClD,UAAI,CAAC,MAAO;AACZ,aAAO,KAAK,kBAAkB,GAAG,eAAe;AAChD,UAAI,QAAQ,QAAQ,QAAQ;AAC1B,eAAO,KAAK,8BAA8B,GAAG,EAAE;AAAA,MACjD,OAAO;AACL,cAAM,UAAU,iBAAiB,GAAG,YAAY,KAAK,GAAG;AAAA,MAC1D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,mBACJ,SACA,WACe;AACf,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,SAAS,GAAG;AACpD,UAAI,CAAC,MAAO;AACZ,aAAO,KAAK,oBAAoB,GAAG,eAAe;AAClD,UAAI,QAAQ,QAAQ,QAAQ;AAC1B,eAAO,KAAK,gCAAgC,GAAG,EAAE;AAAA,MACnD,OAAO;AACL,cAAM,UAAU,mBAAmB,GAAG,YAAY,KAAK,GAAG;AAAA,MAC5D;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,iBAAiB,SAA4B,SAA8C;AAC/F,UAAM,eAAe,KAAK,KAAK,QAAQ,KAAK,mBAAmB;AAC/D,UAAM,GAAG,MAAM,cAAc,EAAE,WAAW,KAAK,CAAC;AAEhD,eAAW,UAAU,SAAS;AAC5B,YAAM,SAAS,OAAO,YAAY,QAAQ;AAC1C,UAAI,CAAC,OAAQ;AAEb,YAAM,WAAW,UAAU,OAAO,IAAI;AACtC,YAAM,WAAW,KAAK,KAAK,cAAc,QAAQ;AAEjD,YAAM,WAAoC;AAAA,QACxC,MAAM,UAAU,OAAO,SAAS,YAAY,YAAY,UAAU,OAAO,OAAO,IAAI;AAAA,QACpF,IAAI;AAAA,UACF,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE;AAAA,UAC3B,mBAAmB,CAAC;AAAA,QACtB;AAAA,QACA,MAAM;AAAA,UACJ,QAAQ;AAAA,YACN,WAAW;AAAA,YACX,aAAa;AAAA,cACX,UAAU;AAAA,cACV,aAAa;AAAA,YACf;AAAA,YACA,OAAO;AAAA,cACL;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM,EAAE,YAAY,YAAY;AAAA,cAClC;AAAA,cACA;AAAA,gBACE,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM,EAAE,gBAAgB,IAAI,OAAO,MAAM;AAAA,cAC3C;AAAA,cACA;AAAA,gBACE,MAAM;AAAA,gBACN,KAAK;AAAA,cACP;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAGA,YAAM,QAAS,SAAiB,KAAK,OAAO;AAG5C,UAAI,OAAO,SAAS,YAAY;AAC9B,cAAM,KAAK;AAAA,UACT,MAAM;AAAA,UACN,KAAK;AAAA,QACP,CAAC;AAAA,MACH;AAGA,UAAI,OAAO,cAAc;AACvB,mBAAW,QAAQ,OAAO,cAAc;AACtC,gBAAM,KAAK;AAAA,YACT,MAAM,WAAW,OAAO,IAAI;AAAA,YAC5B,KAAK;AAAA,UACP,CAAC;AAAA,QACH;AAAA,MACF;AAGA,UAAI,OAAO,aAAa;AACtB,mBAAW,QAAQ,OAAO,aAAa;AACrC,gBAAM,aAAsC;AAAA,YAC1C,MAAM,aAAa,OAAO,IAAI;AAAA,YAC9B,KAAK;AAAA,YACL,qBAAqB,OAAO,SAAS,YAAY,iBAAiB;AAAA,UACpE;AAEA,cAAI,OAAO,WAAW,OAAO,QAAQ,SAAS,GAAG;AAC/C,uBAAW,MAAM,OAAO,QAAQ,OAAO,CAAC,KAA6B,WAAW;AAC9E,kBAAI,MAAM,IAAI,gBAAgB,MAAM;AACpC,qBAAO;AAAA,YACT,GAAG,CAAC,CAAC;AAAA,UACP;AAEA,gBAAM,KAAK,UAAU;AAAA,QACvB;AAAA,MACF;AAGA,UAAI,OAAO,kBAAkB;AAC3B,cAAM,KAAK,OAAO,gBAAgB;AAAA,MACpC;AAEA,YAAM,GAAG,UAAU,UAAU,KAAK,UAAU,QAAQ,GAAG,OAAO;AAC9D,aAAO,KAAK,uBAAuB,QAAQ,EAAE;AAAA,IAC/C;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,12 @@
1
+ import { DeploymentProvider, DeploymentContext, CIConfig } from '../types.js';
2
+
3
+ declare class RailwayProvider implements DeploymentProvider {
4
+ name: string;
5
+ type: "backend";
6
+ provision(context: DeploymentContext): Promise<void>;
7
+ getSecrets(context: DeploymentContext): Promise<Record<string, string>>;
8
+ getVariables(context: DeploymentContext): Promise<Record<string, string>>;
9
+ getCIConfig(): CIConfig;
10
+ }
11
+
12
+ export { RailwayProvider };
@@ -0,0 +1,89 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ execAsync
4
+ } from "../../../chunk-2JW5BYZW.js";
5
+ import {
6
+ init_esm_shims
7
+ } from "../../../chunk-OYFWMYPG.js";
8
+
9
+ // src/deploy/providers/railway.ts
10
+ init_esm_shims();
11
+ import path from "path";
12
+ import { logger } from "@nexical/cli-core";
13
+ var RailwayProvider = class {
14
+ name = "railway";
15
+ type = "backend";
16
+ async provision(context) {
17
+ const backendDir = path.join(context.cwd, "apps/backend");
18
+ const railwayName = context.config.deploy?.backend?.projectName;
19
+ if (!railwayName) {
20
+ throw new Error(
21
+ "Railway project name not found in nexical.yaml. Please configure 'deploy.backend.projectName'."
22
+ );
23
+ }
24
+ const serviceName = railwayName || "nexical-backend";
25
+ logger.info("Configuring Railway...");
26
+ if (context.options.dryRun) {
27
+ logger.info("[Dry Run] Would check Railway status and init project.");
28
+ return;
29
+ }
30
+ try {
31
+ try {
32
+ await execAsync("railway status", { cwd: backendDir });
33
+ } catch {
34
+ const initCmd = railwayName ? `railway init --name ${railwayName}` : "railway init";
35
+ logger.info(`No Railway project detected in apps/backend. Initializing with: ${initCmd}`);
36
+ await execAsync(initCmd, { cwd: backendDir });
37
+ }
38
+ logger.info(`Adding PostgreSQL service if missing for "${serviceName}"...`);
39
+ const { stdout: status } = await execAsync("railway status", { cwd: backendDir });
40
+ if (!status.includes("postgres")) {
41
+ await execAsync("railway add --database postgres", { cwd: backendDir });
42
+ }
43
+ } catch (e) {
44
+ logger.warn(
45
+ "Railway setup encountered an issue. Ensure you are logged in with `railway login`."
46
+ );
47
+ throw e;
48
+ }
49
+ }
50
+ async getSecrets(context) {
51
+ const options = context.config.deploy?.backend?.options || {};
52
+ const secrets = {};
53
+ const tokenEnvVar = typeof options.tokenEnvVar === "string" ? options.tokenEnvVar : void 0;
54
+ const token = (tokenEnvVar ? process.env[tokenEnvVar] : void 0) || process.env.RAILWAY_TOKEN;
55
+ if (!token) {
56
+ throw new Error(
57
+ `Railway Token not found. Please provide it via:
58
+ 1. Configuring 'deploy.backend.options.tokenEnvVar' in nexical.yaml and setting that env var in .env
59
+ 2. Setting RAILWAY_TOKEN in .env`
60
+ );
61
+ }
62
+ secrets["RAILWAY_TOKEN"] = token;
63
+ return secrets;
64
+ }
65
+ async getVariables(context) {
66
+ const railwayName = context.config.deploy?.backend?.projectName;
67
+ if (!railwayName) {
68
+ throw new Error(
69
+ "Railway project name not found in nexical.yaml. Please configure 'deploy.backend.projectName'."
70
+ );
71
+ }
72
+ const serviceName = railwayName || "nexical-backend";
73
+ return {
74
+ RAILWAY_SERVICE_NAME: serviceName
75
+ };
76
+ }
77
+ getCIConfig() {
78
+ return {
79
+ secrets: ["RAILWAY_TOKEN"],
80
+ variables: ["RAILWAY_SERVICE_NAME"],
81
+ installSteps: ["npm install -g @railway/cli"],
82
+ deploySteps: ["railway up --service ${{ vars.RAILWAY_SERVICE_NAME }} --detach"]
83
+ };
84
+ }
85
+ };
86
+ export {
87
+ RailwayProvider
88
+ };
89
+ //# sourceMappingURL=railway.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/deploy/providers/railway.ts"],"sourcesContent":["import path from 'node:path';\nimport { logger } from '@nexical/cli-core';\nimport { DeploymentProvider, DeploymentContext, CIConfig } from '../types';\nimport { execAsync } from '../utils';\n\nexport class RailwayProvider implements DeploymentProvider {\n name = 'railway';\n type = 'backend' as const;\n\n async provision(context: DeploymentContext): Promise<void> {\n const backendDir = path.join(context.cwd, 'apps/backend');\n // Resolve project name/token\n const railwayName = context.config.deploy?.backend?.projectName;\n\n if (!railwayName) {\n throw new Error(\n \"Railway project name not found in nexical.yaml. Please configure 'deploy.backend.projectName'.\",\n );\n }\n\n // Service name defaults to project name for the primary backend\n const serviceName = railwayName || 'nexical-backend';\n // Note: Token is usually handled by `railway login` for CLI, but for CI we need it.\n // The provider might not need to know the token for `provision` if we rely on CLI auth.\n // However, we might need to export it for GitHub secrets.\n\n logger.info('Configuring Railway...');\n\n if (context.options.dryRun) {\n logger.info('[Dry Run] Would check Railway status and init project.');\n return;\n }\n\n try {\n try {\n await execAsync('railway status', { cwd: backendDir });\n } catch {\n const initCmd = railwayName ? `railway init --name ${railwayName}` : 'railway init';\n logger.info(`No Railway project detected in apps/backend. Initializing with: ${initCmd}`);\n await execAsync(initCmd, { cwd: backendDir });\n }\n\n logger.info(`Adding PostgreSQL service if missing for \"${serviceName}\"...`);\n const { stdout: status } = await execAsync('railway status', { cwd: backendDir });\n if (!status.includes('postgres')) {\n await execAsync('railway add --database postgres', { cwd: backendDir });\n }\n } catch (e: unknown) {\n logger.warn(\n 'Railway setup encountered an issue. Ensure you are logged in with `railway login`.',\n );\n throw e;\n }\n }\n\n async getSecrets(context: DeploymentContext): Promise<Record<string, string>> {\n const options = context.config.deploy?.backend?.options || {};\n const secrets: Record<string, string> = {};\n\n // Resolve Railway Token\n // Priority: Configured Env Var > Default Env Var\n const tokenEnvVar = typeof options.tokenEnvVar === 'string' ? options.tokenEnvVar : undefined;\n const token = (tokenEnvVar ? process.env[tokenEnvVar] : undefined) || process.env.RAILWAY_TOKEN;\n\n if (!token) {\n // Strict check: Error if token is missing\n throw new Error(\n `Railway Token not found. Please provide it via:\\n` +\n `1. Configuring 'deploy.backend.options.tokenEnvVar' in nexical.yaml and setting that env var in .env\\n` +\n `2. Setting RAILWAY_TOKEN in .env`,\n );\n }\n\n secrets['RAILWAY_TOKEN'] = token;\n return secrets;\n }\n\n async getVariables(context: DeploymentContext): Promise<Record<string, string>> {\n const railwayName = context.config.deploy?.backend?.projectName;\n\n if (!railwayName) {\n throw new Error(\n \"Railway project name not found in nexical.yaml. Please configure 'deploy.backend.projectName'.\",\n );\n }\n\n // Service name defaults to project name\n const serviceName = railwayName || 'nexical-backend';\n\n return {\n RAILWAY_SERVICE_NAME: serviceName,\n };\n }\n\n getCIConfig(): CIConfig {\n return {\n secrets: ['RAILWAY_TOKEN'],\n variables: ['RAILWAY_SERVICE_NAME'],\n installSteps: ['npm install -g @railway/cli'],\n deploySteps: ['railway up --service ${{ vars.RAILWAY_SERVICE_NAME }} --detach'],\n };\n }\n}\n"],"mappings":";;;;;;;;;AAAA;AAAA,OAAO,UAAU;AACjB,SAAS,cAAc;AAIhB,IAAM,kBAAN,MAAoD;AAAA,EACzD,OAAO;AAAA,EACP,OAAO;AAAA,EAEP,MAAM,UAAU,SAA2C;AACzD,UAAM,aAAa,KAAK,KAAK,QAAQ,KAAK,cAAc;AAExD,UAAM,cAAc,QAAQ,OAAO,QAAQ,SAAS;AAEpD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAGA,UAAM,cAAc,eAAe;AAKnC,WAAO,KAAK,wBAAwB;AAEpC,QAAI,QAAQ,QAAQ,QAAQ;AAC1B,aAAO,KAAK,wDAAwD;AACpE;AAAA,IACF;AAEA,QAAI;AACF,UAAI;AACF,cAAM,UAAU,kBAAkB,EAAE,KAAK,WAAW,CAAC;AAAA,MACvD,QAAQ;AACN,cAAM,UAAU,cAAc,uBAAuB,WAAW,KAAK;AACrE,eAAO,KAAK,mEAAmE,OAAO,EAAE;AACxF,cAAM,UAAU,SAAS,EAAE,KAAK,WAAW,CAAC;AAAA,MAC9C;AAEA,aAAO,KAAK,6CAA6C,WAAW,MAAM;AAC1E,YAAM,EAAE,QAAQ,OAAO,IAAI,MAAM,UAAU,kBAAkB,EAAE,KAAK,WAAW,CAAC;AAChF,UAAI,CAAC,OAAO,SAAS,UAAU,GAAG;AAChC,cAAM,UAAU,mCAAmC,EAAE,KAAK,WAAW,CAAC;AAAA,MACxE;AAAA,IACF,SAAS,GAAY;AACnB,aAAO;AAAA,QACL;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAA6D;AAC5E,UAAM,UAAU,QAAQ,OAAO,QAAQ,SAAS,WAAW,CAAC;AAC5D,UAAM,UAAkC,CAAC;AAIzC,UAAM,cAAc,OAAO,QAAQ,gBAAgB,WAAW,QAAQ,cAAc;AACpF,UAAM,SAAS,cAAc,QAAQ,IAAI,WAAW,IAAI,WAAc,QAAQ,IAAI;AAElF,QAAI,CAAC,OAAO;AAEV,YAAM,IAAI;AAAA,QACR;AAAA;AAAA;AAAA,MAGF;AAAA,IACF;AAEA,YAAQ,eAAe,IAAI;AAC3B,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,aAAa,SAA6D;AAC9E,UAAM,cAAc,QAAQ,OAAO,QAAQ,SAAS;AAEpD,QAAI,CAAC,aAAa;AAChB,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAGA,UAAM,cAAc,eAAe;AAEnC,WAAO;AAAA,MACL,sBAAsB;AAAA,IACxB;AAAA,EACF;AAAA,EAEA,cAAwB;AACtB,WAAO;AAAA,MACL,SAAS,CAAC,eAAe;AAAA,MACzB,WAAW,CAAC,sBAAsB;AAAA,MAClC,cAAc,CAAC,6BAA6B;AAAA,MAC5C,aAAa,CAAC,gEAAgE;AAAA,IAChF;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,15 @@
1
+ import { DeploymentProvider, RepositoryProvider } from './types.js';
2
+
3
+ declare class ProviderRegistry {
4
+ private deploymentProviders;
5
+ private repositoryProviders;
6
+ registerDeploymentProvider(provider: DeploymentProvider): void;
7
+ registerRepositoryProvider(provider: RepositoryProvider): void;
8
+ getDeploymentProvider(name: string): DeploymentProvider | undefined;
9
+ getRepositoryProvider(name: string): RepositoryProvider | undefined;
10
+ private registerProviderFromModule;
11
+ loadCoreProviders(): Promise<void>;
12
+ loadLocalProviders(cwd: string): Promise<void>;
13
+ }
14
+
15
+ export { ProviderRegistry };
@@ -0,0 +1,9 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ ProviderRegistry
4
+ } from "../../chunk-EKCOW7FM.js";
5
+ import "../../chunk-OYFWMYPG.js";
6
+ export {
7
+ ProviderRegistry
8
+ };
9
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,47 @@
1
+ interface CIConfig {
2
+ secrets: string[];
3
+ variables: string[];
4
+ installSteps?: string[];
5
+ buildSteps?: string[];
6
+ deploySteps?: string[];
7
+ githubActionStep?: Record<string, unknown>;
8
+ }
9
+ interface DeploymentContext {
10
+ cwd: string;
11
+ config: NexicalConfig;
12
+ options: Record<string, unknown>;
13
+ }
14
+ interface DeploymentProvider {
15
+ name: string;
16
+ type: 'frontend' | 'backend';
17
+ provision(context: DeploymentContext): Promise<void>;
18
+ getCIConfig(repoType: 'github' | 'gitlab'): CIConfig;
19
+ getSecrets(context: DeploymentContext): Promise<Record<string, string>>;
20
+ getVariables(context: DeploymentContext): Promise<Record<string, string>>;
21
+ }
22
+ interface RepositoryProvider {
23
+ name: string;
24
+ configureSecrets(context: DeploymentContext, secrets: Record<string, string>): Promise<void>;
25
+ configureVariables(context: DeploymentContext, variables: Record<string, string>): Promise<void>;
26
+ generateWorkflow(context: DeploymentContext, targets: DeploymentProvider[]): Promise<void>;
27
+ }
28
+ interface NexicalConfig {
29
+ deploy?: {
30
+ backend?: {
31
+ provider: string;
32
+ projectName?: string;
33
+ options?: Record<string, unknown>;
34
+ };
35
+ frontend?: {
36
+ provider: string;
37
+ projectName?: string;
38
+ options?: Record<string, unknown>;
39
+ };
40
+ repository?: {
41
+ provider: string;
42
+ options?: Record<string, unknown>;
43
+ };
44
+ };
45
+ }
46
+
47
+ export type { CIConfig, DeploymentContext, DeploymentProvider, NexicalConfig, RepositoryProvider };
@@ -0,0 +1,8 @@
1
+ import { createRequire } from "module"; const require = createRequire(import.meta.url);
2
+ import {
3
+ init_esm_shims
4
+ } from "../../chunk-OYFWMYPG.js";
5
+
6
+ // src/deploy/types.ts
7
+ init_esm_shims();
8
+ //# sourceMappingURL=types.js.map