@nexical/cli 0.11.23 → 0.12.0
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/README.md +90 -235
- package/dist/{chunk-OYFWMYPG.js → chunk-6DE5Q66O.js} +6 -1
- package/dist/{chunk-OYFWMYPG.js.map → chunk-6DE5Q66O.js.map} +1 -1
- package/dist/chunk-G66GMEFE.js +31 -0
- package/dist/chunk-G66GMEFE.js.map +1 -0
- package/dist/{chunk-2FKDEDDE.js → chunk-HOVS7SCD.js} +16 -3
- package/dist/chunk-HOVS7SCD.js.map +1 -0
- package/dist/{chunk-GUUPSHWC.js → chunk-JEMIKBGX.js} +3 -3
- package/dist/chunk-JGAMEJTL.js +4101 -0
- package/dist/chunk-JGAMEJTL.js.map +1 -0
- package/dist/{chunk-OUGA4CB4.js → chunk-JS6WL5NS.js} +2 -2
- package/dist/{chunk-GEESHGE4.js → chunk-L2RUXOL4.js} +2 -2
- package/dist/{chunk-54HY52LH.js → chunk-QTJIGPQ3.js} +2 -2
- package/dist/{chunk-EKCOW7FM.js → chunk-USP2MI63.js} +41 -23
- package/dist/chunk-USP2MI63.js.map +1 -0
- package/dist/{chunk-2JW5BYZW.js → chunk-VKE7R2EZ.js} +2 -2
- package/dist/{chunk-AC4B3HPJ.js → chunk-XONR27KC.js} +2 -2
- package/dist/{chunk-PJIOCW2A.js → chunk-ZWNIZB3Q.js} +2 -2
- package/dist/index.js +5 -5
- package/dist/index.js.map +1 -1
- package/dist/src/commands/deploy.d.ts +3 -3
- package/dist/src/commands/deploy.js +134 -78
- package/dist/src/commands/deploy.js.map +1 -1
- package/dist/src/commands/init.js +5 -5
- package/dist/src/commands/module/add.js +4 -4
- package/dist/src/commands/module/list.js +2 -2
- package/dist/src/commands/module/remove.js +2 -2
- package/dist/src/commands/module/update.js +2 -2
- package/dist/src/commands/prompt.js +2 -2
- package/dist/src/commands/run.js +2 -2
- package/dist/src/commands/setup.js +3 -3
- package/dist/src/deploy/config-manager.js +3 -2
- package/dist/src/deploy/providers/cloudflare.d.ts +13 -8
- package/dist/src/deploy/providers/cloudflare.js +161 -52
- package/dist/src/deploy/providers/cloudflare.js.map +1 -1
- package/dist/src/deploy/providers/dns-cloudflare.d.ts +9 -0
- package/dist/src/deploy/providers/dns-cloudflare.js +123 -0
- package/dist/src/deploy/providers/dns-cloudflare.js.map +1 -0
- package/dist/src/deploy/providers/github.d.ts +6 -2
- package/dist/src/deploy/providers/github.js +37 -45
- package/dist/src/deploy/providers/github.js.map +1 -1
- package/dist/src/deploy/providers/railway.d.ts +17 -8
- package/dist/src/deploy/providers/railway.js +106 -45
- package/dist/src/deploy/providers/railway.js.map +1 -1
- package/dist/src/deploy/registry.d.ts +7 -4
- package/dist/src/deploy/registry.js +2 -2
- package/dist/src/deploy/schema.d.ts +188 -0
- package/dist/src/deploy/schema.js +11 -0
- package/dist/src/deploy/schema.js.map +1 -0
- package/dist/src/deploy/template-manager.d.ts +12 -0
- package/dist/src/deploy/template-manager.js +9 -0
- package/dist/src/deploy/template-manager.js.map +1 -0
- package/dist/src/deploy/types.d.ts +42 -17
- package/dist/src/deploy/types.js +1 -1
- package/dist/src/deploy/types.js.map +1 -1
- package/dist/src/deploy/utils.js +2 -2
- package/dist/src/utils/discovery.js +2 -2
- package/dist/src/utils/filter.js +2 -2
- package/dist/src/utils/git.js +2 -2
- package/dist/src/utils/url-resolver.js +2 -2
- package/dist/templates/github-workflow.yaml +23 -0
- package/package.json +2 -2
- package/src/commands/deploy.ts +157 -93
- package/src/deploy/config-manager.ts +14 -1
- package/src/deploy/providers/cloudflare.ts +203 -80
- package/src/deploy/providers/dns-cloudflare.ts +134 -0
- package/src/deploy/providers/github.ts +44 -47
- package/src/deploy/providers/railway.ts +135 -55
- package/src/deploy/registry.ts +49 -28
- package/src/deploy/schema.ts +39 -0
- package/src/deploy/template-manager.ts +32 -0
- package/src/deploy/templates/github-workflow.yaml +23 -0
- package/src/deploy/types.ts +48 -16
- package/test/integration/commands/deploy.integration.test.ts +79 -3
- package/test/unit/commands/deploy.test.ts +96 -198
- package/test/unit/deploy/config-manager.test.ts +9 -5
- package/test/unit/deploy/providers/cloudflare.test.ts +95 -96
- package/test/unit/deploy/providers/dns-cloudflare.test.ts +148 -0
- package/test/unit/deploy/providers/github.test.ts +43 -47
- package/test/unit/deploy/providers/railway.test.ts +50 -261
- package/test/unit/deploy/registry.test.ts +20 -17
- package/tsup.config.ts +3 -0
- package/dist/chunk-2FKDEDDE.js.map +0 -1
- package/dist/chunk-EKCOW7FM.js.map +0 -1
- /package/dist/{chunk-GUUPSHWC.js.map → chunk-JEMIKBGX.js.map} +0 -0
- /package/dist/{chunk-OUGA4CB4.js.map → chunk-JS6WL5NS.js.map} +0 -0
- /package/dist/{chunk-GEESHGE4.js.map → chunk-L2RUXOL4.js.map} +0 -0
- /package/dist/{chunk-54HY52LH.js.map → chunk-QTJIGPQ3.js.map} +0 -0
- /package/dist/{chunk-2JW5BYZW.js.map → chunk-VKE7R2EZ.js.map} +0 -0
- /package/dist/{chunk-AC4B3HPJ.js.map → chunk-XONR27KC.js.map} +0 -0
- /package/dist/{chunk-PJIOCW2A.js.map → chunk-ZWNIZB3Q.js.map} +0 -0
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
__commonJS,
|
|
4
4
|
__require,
|
|
5
5
|
init_esm_shims
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-6DE5Q66O.js";
|
|
7
7
|
|
|
8
8
|
// node_modules/universalify/index.js
|
|
9
9
|
var require_universalify = __commonJS({
|
|
@@ -2205,4 +2205,4 @@ var require_lib = __commonJS({
|
|
|
2205
2205
|
export {
|
|
2206
2206
|
require_lib
|
|
2207
2207
|
};
|
|
2208
|
-
//# sourceMappingURL=chunk-
|
|
2208
|
+
//# sourceMappingURL=chunk-JS6WL5NS.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_esm_shims
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6DE5Q66O.js";
|
|
5
5
|
|
|
6
6
|
// src/utils/git.ts
|
|
7
7
|
init_esm_shims();
|
|
@@ -107,4 +107,4 @@ export {
|
|
|
107
107
|
renameRemote,
|
|
108
108
|
branchExists
|
|
109
109
|
};
|
|
110
|
-
//# sourceMappingURL=chunk-
|
|
110
|
+
//# sourceMappingURL=chunk-L2RUXOL4.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_esm_shims
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6DE5Q66O.js";
|
|
5
5
|
|
|
6
6
|
// src/utils/filter.ts
|
|
7
7
|
init_esm_shims();
|
|
@@ -35,4 +35,4 @@ function filterCommandDirectories(additionalCommands, coreCommandsDir) {
|
|
|
35
35
|
export {
|
|
36
36
|
filterCommandDirectories
|
|
37
37
|
};
|
|
38
|
-
//# sourceMappingURL=chunk-
|
|
38
|
+
//# sourceMappingURL=chunk-QTJIGPQ3.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_esm_shims
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6DE5Q66O.js";
|
|
5
5
|
|
|
6
6
|
// src/deploy/registry.ts
|
|
7
7
|
init_esm_shims();
|
|
@@ -9,45 +9,63 @@ import path from "path";
|
|
|
9
9
|
import fs from "fs/promises";
|
|
10
10
|
import { logger } from "@nexical/cli-core";
|
|
11
11
|
var ProviderRegistry = class {
|
|
12
|
-
|
|
12
|
+
hostingProviders = /* @__PURE__ */ new Map();
|
|
13
13
|
repositoryProviders = /* @__PURE__ */ new Map();
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
dnsProviders = /* @__PURE__ */ new Map();
|
|
15
|
+
registerHostingProvider(provider) {
|
|
16
|
+
this.hostingProviders.set(provider.name, provider);
|
|
16
17
|
}
|
|
17
18
|
registerRepositoryProvider(provider) {
|
|
18
19
|
this.repositoryProviders.set(provider.name, provider);
|
|
19
20
|
}
|
|
20
|
-
|
|
21
|
-
return this.
|
|
21
|
+
getHostingProvider(name) {
|
|
22
|
+
return this.hostingProviders.get(name);
|
|
22
23
|
}
|
|
23
24
|
getRepositoryProvider(name) {
|
|
24
25
|
return this.repositoryProviders.get(name);
|
|
25
26
|
}
|
|
27
|
+
registerDnsProvider(provider) {
|
|
28
|
+
this.dnsProviders.set(provider.name, provider);
|
|
29
|
+
}
|
|
30
|
+
getDnsProvider(name) {
|
|
31
|
+
return this.dnsProviders.get(name);
|
|
32
|
+
}
|
|
26
33
|
registerProviderFromModule(module, source) {
|
|
27
|
-
const
|
|
28
|
-
let
|
|
29
|
-
if (!
|
|
30
|
-
for (const key of Object.keys(
|
|
31
|
-
if (typeof
|
|
32
|
-
|
|
34
|
+
const exports = module;
|
|
35
|
+
let ProviderCandidate = exports?.default;
|
|
36
|
+
if (!ProviderCandidate && exports && Object.keys(exports).length > 0) {
|
|
37
|
+
for (const key of Object.keys(exports)) {
|
|
38
|
+
if (typeof exports[key] === "function") {
|
|
39
|
+
ProviderCandidate = exports[key];
|
|
33
40
|
break;
|
|
34
41
|
}
|
|
35
42
|
}
|
|
36
43
|
}
|
|
37
|
-
if (
|
|
44
|
+
if (!ProviderCandidate) return;
|
|
45
|
+
let instance;
|
|
46
|
+
if (typeof ProviderCandidate === "function") {
|
|
38
47
|
try {
|
|
39
|
-
|
|
48
|
+
instance = new ProviderCandidate();
|
|
40
49
|
} catch {
|
|
50
|
+
instance = ProviderCandidate;
|
|
41
51
|
}
|
|
52
|
+
} else {
|
|
53
|
+
instance = ProviderCandidate;
|
|
42
54
|
}
|
|
43
|
-
if (
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
if (!instance || typeof instance !== "object") return;
|
|
56
|
+
const provider = instance;
|
|
57
|
+
if (typeof provider.provision === "function" && typeof provider.getCIConfig === "function") {
|
|
58
|
+
const p = provider;
|
|
59
|
+
logger.info(`[Registry] Loaded ${source} hosting provider: ${p.name}`);
|
|
60
|
+
this.registerHostingProvider(p);
|
|
61
|
+
} else if (typeof provider.configureSecrets === "function" && typeof provider.generateWorkflow === "function") {
|
|
62
|
+
const p = provider;
|
|
63
|
+
logger.info(`[Registry] Loaded ${source} repository provider: ${p.name}`);
|
|
64
|
+
this.registerRepositoryProvider(p);
|
|
65
|
+
} else if (typeof provider.provision === "function" && provider.type === "dns") {
|
|
66
|
+
const p = provider;
|
|
67
|
+
logger.info(`[Registry] Loaded ${source} DNS provider: ${p.name}`);
|
|
68
|
+
this.registerDnsProvider(p);
|
|
51
69
|
}
|
|
52
70
|
}
|
|
53
71
|
async loadCoreProviders() {
|
|
@@ -115,4 +133,4 @@ var ProviderRegistry = class {
|
|
|
115
133
|
export {
|
|
116
134
|
ProviderRegistry
|
|
117
135
|
};
|
|
118
|
-
//# sourceMappingURL=chunk-
|
|
136
|
+
//# sourceMappingURL=chunk-USP2MI63.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/deploy/registry.ts"],"sourcesContent":["import path from 'node:path';\nimport fs from 'node:fs/promises';\nimport { logger } from '@nexical/cli-core';\nimport { HostingProvider, RepositoryProvider, DnsProvider } from './types';\n\nexport class ProviderRegistry {\n private hostingProviders: Map<string, HostingProvider> = new Map();\n private repositoryProviders: Map<string, RepositoryProvider> = new Map();\n private dnsProviders: Map<string, DnsProvider> = new Map();\n\n registerHostingProvider(provider: HostingProvider) {\n this.hostingProviders.set(provider.name, provider);\n }\n\n registerRepositoryProvider(provider: RepositoryProvider) {\n this.repositoryProviders.set(provider.name, provider);\n }\n\n getHostingProvider(name: string): HostingProvider | undefined {\n return this.hostingProviders.get(name);\n }\n\n getRepositoryProvider(name: string): RepositoryProvider | undefined {\n return this.repositoryProviders.get(name);\n }\n\n registerDnsProvider(provider: DnsProvider) {\n this.dnsProviders.set(provider.name, provider);\n }\n\n getDnsProvider(name: string): DnsProvider | undefined {\n return this.dnsProviders.get(name);\n }\n\n private registerProviderFromModule(module: unknown, source: string) {\n const exports = module as Record<string, unknown>;\n let ProviderCandidate = exports?.default;\n\n // Handle named exports if default is missing (fallback)\n if (!ProviderCandidate && exports && Object.keys(exports).length > 0) {\n // Try to find a class export that looks like a provider\n for (const key of Object.keys(exports)) {\n if (typeof exports[key] === 'function') {\n ProviderCandidate = exports[key];\n break;\n }\n }\n }\n\n if (!ProviderCandidate) return;\n\n let instance: unknown;\n if (typeof ProviderCandidate === 'function') {\n try {\n instance = new (ProviderCandidate as new () => unknown)();\n } catch {\n // Not a constructor or failed, could be a regular function\n instance = ProviderCandidate;\n }\n } else {\n instance = ProviderCandidate;\n }\n\n if (!instance || typeof instance !== 'object') return;\n\n const provider = instance as Record<string, unknown>;\n\n if (typeof provider.provision === 'function' && typeof provider.getCIConfig === 'function') {\n const p = provider as unknown as HostingProvider;\n logger.info(`[Registry] Loaded ${source} hosting provider: ${p.name}`);\n this.registerHostingProvider(p);\n } else if (\n typeof provider.configureSecrets === 'function' &&\n typeof provider.generateWorkflow === 'function'\n ) {\n const p = provider as unknown as RepositoryProvider;\n logger.info(`[Registry] Loaded ${source} repository provider: ${p.name}`);\n this.registerRepositoryProvider(p);\n } else if (typeof provider.provision === 'function' && provider.type === 'dns') {\n const p = provider as unknown as DnsProvider;\n logger.info(`[Registry] Loaded ${source} DNS provider: ${p.name}`);\n this.registerDnsProvider(p);\n }\n }\n\n async loadCoreProviders() {\n const dirname = path.dirname(new URL(import.meta.url).pathname);\n\n // Try multiple paths to find the providers directory\n // 1. 'providers' - Standard source structure / flattened dist\n // 2. 'src/deploy/providers' - tsup output (chunk in root, files in src/...)\n const candidates = [\n path.join(dirname, 'providers'),\n path.join(dirname, 'src/deploy/providers'),\n ];\n\n let providersDir = '';\n for (const candidate of candidates) {\n try {\n await fs.access(candidate);\n providersDir = candidate;\n break;\n } catch {\n // Ignore missing dir\n }\n }\n\n if (!providersDir) {\n logger.warn(\n `[Registry] Could not locate core providers directory. Checked: ${candidates.join(', ')}`,\n );\n return;\n }\n\n try {\n const files = await fs.readdir(providersDir);\n for (const file of files) {\n if (file.endsWith('.js') || (file.endsWith('.ts') && !file.endsWith('.d.ts'))) {\n try {\n const providerPath = path.join(providersDir, file);\n const module = await import(providerPath);\n this.registerProviderFromModule(module, 'core');\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n logger.warn(`Failed to load core provider from ${file}: ${message}`);\n }\n }\n }\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n logger.warn(`Failed to scan core providers at ${providersDir}: ${message}`);\n }\n }\n\n async loadLocalProviders(cwd: string) {\n const deployDir = path.join(cwd, 'deploy');\n try {\n const files = await fs.readdir(deployDir);\n for (const file of files) {\n if (file.endsWith('.ts') || file.endsWith('.js')) {\n try {\n const providerPath = path.join(deployDir, file);\n // Use jiti to load TS/JS files dynamically\n const jiti = (await import('jiti')).createJiti(import.meta.url);\n const module = (await jiti.import(providerPath)) as unknown;\n this.registerProviderFromModule(module, 'local');\n } catch (e: unknown) {\n const message = e instanceof Error ? e.message : String(e);\n logger.warn(`Failed to load local provider from ${file}: ${message}`);\n }\n }\n }\n } catch {\n // Ignore if deploy dir doesn't exist\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_esm_shims
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6DE5Q66O.js";
|
|
5
5
|
|
|
6
6
|
// src/deploy/utils.ts
|
|
7
7
|
init_esm_shims();
|
|
@@ -21,4 +21,4 @@ export {
|
|
|
21
21
|
execAsync,
|
|
22
22
|
checkCommand
|
|
23
23
|
};
|
|
24
|
-
//# sourceMappingURL=chunk-
|
|
24
|
+
//# sourceMappingURL=chunk-VKE7R2EZ.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_esm_shims
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6DE5Q66O.js";
|
|
5
5
|
|
|
6
6
|
// src/utils/discovery.ts
|
|
7
7
|
init_esm_shims();
|
|
@@ -90,4 +90,4 @@ function discoverCommandDirectories(projectRoot) {
|
|
|
90
90
|
export {
|
|
91
91
|
discoverCommandDirectories
|
|
92
92
|
};
|
|
93
|
-
//# sourceMappingURL=chunk-
|
|
93
|
+
//# sourceMappingURL=chunk-XONR27KC.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
init_esm_shims
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-6DE5Q66O.js";
|
|
5
5
|
|
|
6
6
|
// src/utils/url-resolver.ts
|
|
7
7
|
init_esm_shims();
|
|
@@ -39,4 +39,4 @@ function resolveGitUrl(url) {
|
|
|
39
39
|
export {
|
|
40
40
|
resolveGitUrl
|
|
41
41
|
};
|
|
42
|
-
//# sourceMappingURL=chunk-
|
|
42
|
+
//# sourceMappingURL=chunk-ZWNIZB3Q.js.map
|
package/dist/index.js
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
discoverCommandDirectories
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XONR27KC.js";
|
|
6
6
|
import {
|
|
7
7
|
filterCommandDirectories
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-QTJIGPQ3.js";
|
|
9
9
|
import {
|
|
10
10
|
init_esm_shims
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-6DE5Q66O.js";
|
|
12
12
|
|
|
13
13
|
// index.ts
|
|
14
14
|
init_esm_shims();
|
|
@@ -18,14 +18,14 @@ import { fileURLToPath } from "url";
|
|
|
18
18
|
// package.json
|
|
19
19
|
var package_default = {
|
|
20
20
|
name: "@nexical/cli",
|
|
21
|
-
version: "0.
|
|
21
|
+
version: "0.12.0",
|
|
22
22
|
license: "Apache-2.0",
|
|
23
23
|
type: "module",
|
|
24
24
|
bin: {
|
|
25
25
|
nexical: "./dist/index.js"
|
|
26
26
|
},
|
|
27
27
|
scripts: {
|
|
28
|
-
build: "tsup",
|
|
28
|
+
build: "tsup && cp -r src/deploy/templates dist/",
|
|
29
29
|
dev: "tsup --watch",
|
|
30
30
|
start: "node dist/index.js",
|
|
31
31
|
test: "npm run test:unit && npm run test:integration && npm run test:e2e",
|
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.
|
|
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":[]}
|
|
@@ -8,15 +8,15 @@ declare class DeployCommand extends BaseCommand {
|
|
|
8
8
|
options: ({
|
|
9
9
|
name: string;
|
|
10
10
|
description: string;
|
|
11
|
-
default
|
|
11
|
+
default: string;
|
|
12
12
|
} | {
|
|
13
13
|
name: string;
|
|
14
14
|
description: string;
|
|
15
|
-
default:
|
|
15
|
+
default: boolean;
|
|
16
16
|
} | {
|
|
17
17
|
name: string;
|
|
18
18
|
description: string;
|
|
19
|
-
default
|
|
19
|
+
default?: undefined;
|
|
20
20
|
})[];
|
|
21
21
|
};
|
|
22
22
|
run(options: Record<string, unknown>): Promise<void>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
2
|
import {
|
|
3
3
|
ConfigManager
|
|
4
|
-
} from "../../chunk-
|
|
4
|
+
} from "../../chunk-HOVS7SCD.js";
|
|
5
|
+
import "../../chunk-JGAMEJTL.js";
|
|
5
6
|
import {
|
|
6
7
|
ProviderRegistry
|
|
7
|
-
} from "../../chunk-
|
|
8
|
+
} from "../../chunk-USP2MI63.js";
|
|
8
9
|
import {
|
|
9
10
|
init_esm_shims
|
|
10
|
-
} from "../../chunk-
|
|
11
|
+
} from "../../chunk-6DE5Q66O.js";
|
|
11
12
|
|
|
12
13
|
// src/commands/deploy.ts
|
|
13
14
|
init_esm_shims();
|
|
@@ -17,40 +18,22 @@ import { BaseCommand } from "@nexical/cli-core";
|
|
|
17
18
|
var DeployCommand = class extends BaseCommand {
|
|
18
19
|
static usage = "deploy";
|
|
19
20
|
static description = "Deploy the application based on nexical.yaml configuration.";
|
|
20
|
-
static help = `This command orchestrates the deployment of your
|
|
21
|
+
static help = `This command orchestrates the deployment of your applications
|
|
21
22
|
by interacting with the providers specified in your configuration file.
|
|
22
23
|
|
|
23
24
|
CONFIGURATION:
|
|
24
25
|
- Requires a 'nexical.yaml' file in the project root.
|
|
25
|
-
-
|
|
26
|
-
and save the configuration for future uses.
|
|
26
|
+
- Supports definition of multiple applications under 'deploy.apps'.
|
|
27
27
|
- Supports loading environment variables from a .env file in the project root.
|
|
28
28
|
|
|
29
|
-
PROVIDERS:
|
|
30
|
-
- Backend: Railway, etc.
|
|
31
|
-
- Frontend: Cloudflare Pages, etc.
|
|
32
|
-
- Repository: GitHub, GitLab, etc.
|
|
33
|
-
|
|
34
29
|
PROCESS:
|
|
35
30
|
1. Loads environment variables from '.env'.
|
|
36
31
|
2. Loads configuration from 'nexical.yaml'.
|
|
37
|
-
3. Provisions resources
|
|
32
|
+
3. Provisions resources for each application.
|
|
38
33
|
4. Configures the repository (secrets/variables) for CI/CD.
|
|
39
|
-
5. Generates CI/CD workflow files.`;
|
|
34
|
+
5. Generates CI/CD workflow files for each application.`;
|
|
40
35
|
static args = {
|
|
41
36
|
options: [
|
|
42
|
-
{
|
|
43
|
-
name: "--backend <provider>",
|
|
44
|
-
description: "Override backend provider"
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: "--frontend <provider>",
|
|
48
|
-
description: "Override frontend provider"
|
|
49
|
-
},
|
|
50
|
-
{
|
|
51
|
-
name: "--repo <provider>",
|
|
52
|
-
description: "Override repositroy provider"
|
|
53
|
-
},
|
|
54
37
|
{
|
|
55
38
|
name: "--env <environment>",
|
|
56
39
|
description: "Deployment environment (e.g. production, staging)",
|
|
@@ -60,28 +43,52 @@ PROCESS:
|
|
|
60
43
|
name: "--dry-run",
|
|
61
44
|
description: "Simulate the deployment process",
|
|
62
45
|
default: false
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
name: "--apps <apps>",
|
|
49
|
+
description: "Comma separated list of applications to deploy"
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: "--manual",
|
|
53
|
+
description: "Perform a direct build and deployment from the local machine",
|
|
54
|
+
default: false
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
name: "--repo <provider>",
|
|
58
|
+
description: "Repository provider to use (e.g. github, gitlab)"
|
|
63
59
|
}
|
|
64
60
|
]
|
|
65
61
|
};
|
|
66
62
|
async run(options) {
|
|
67
63
|
this.info("Starting Nexical Deployment...");
|
|
68
|
-
dotenv.config({ path: path.join(process.cwd(), ".env") });
|
|
64
|
+
dotenv.config({ path: path.join(process.cwd(), ".env"), quiet: true });
|
|
69
65
|
const configManager = new ConfigManager(process.cwd());
|
|
70
66
|
const config = await configManager.load();
|
|
71
67
|
const registry = new ProviderRegistry();
|
|
72
68
|
await registry.loadCoreProviders();
|
|
73
69
|
await registry.loadLocalProviders(process.cwd());
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
70
|
+
const appsMap = config.deploy?.apps || {};
|
|
71
|
+
let apps = Object.entries(appsMap).map(([name, appConfig]) => {
|
|
72
|
+
const app = {
|
|
73
|
+
...appConfig,
|
|
74
|
+
name
|
|
75
|
+
};
|
|
76
|
+
return app;
|
|
77
|
+
});
|
|
78
|
+
const selectedApps = options.apps;
|
|
79
|
+
if (selectedApps) {
|
|
80
|
+
const appNames = selectedApps.split(",").map((s) => s.trim());
|
|
81
|
+
const filteredApps = apps.filter((app) => appNames.includes(app.name));
|
|
82
|
+
const missingApps = appNames.filter((name) => !apps.find((app) => app.name === name));
|
|
83
|
+
if (missingApps.length > 0) {
|
|
84
|
+
this.error(
|
|
85
|
+
`The following applications were not found in nexical.yaml: ${missingApps.join(", ")}`
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
apps = filteredApps;
|
|
79
89
|
}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
this.error(
|
|
83
|
-
"Frontend provider not specified. Use --frontend flag or configure 'deploy.frontend.provider' in nexical.yaml."
|
|
84
|
-
);
|
|
90
|
+
if (apps.length === 0) {
|
|
91
|
+
this.error("No applications found in nexical.yaml. Please configure [deploy.apps].");
|
|
85
92
|
}
|
|
86
93
|
const repoProviderName = options.repo || config.deploy?.repository?.provider;
|
|
87
94
|
if (!repoProviderName) {
|
|
@@ -89,59 +96,108 @@ PROCESS:
|
|
|
89
96
|
"Repository provider not specified. Use --repo flag or configure 'deploy.repository.provider' in nexical.yaml."
|
|
90
97
|
);
|
|
91
98
|
}
|
|
92
|
-
const backendProvider = registry.getDeploymentProvider(backendProviderName);
|
|
93
|
-
const frontendProvider = registry.getDeploymentProvider(frontendProviderName);
|
|
94
99
|
const repoProvider = registry.getRepositoryProvider(repoProviderName);
|
|
95
|
-
if (!backendProvider) throw new Error(`Backend provider '${backendProviderName}' not found.`);
|
|
96
|
-
if (!frontendProvider)
|
|
97
|
-
throw new Error(`Frontend provider '${frontendProviderName}' not found.`);
|
|
98
100
|
if (!repoProvider) throw new Error(`Repository provider '${repoProviderName}' not found.`);
|
|
99
101
|
const context = {
|
|
100
102
|
cwd: process.cwd(),
|
|
101
103
|
config,
|
|
102
104
|
options
|
|
103
105
|
};
|
|
104
|
-
|
|
105
|
-
await backendProvider.provision(context);
|
|
106
|
-
this.info(`Provisioning Frontend with ${frontendProvider.name}...`);
|
|
107
|
-
await frontendProvider.provision(context);
|
|
108
|
-
this.info(`Configuring Repository with ${repoProvider.name}...`);
|
|
106
|
+
const activeApps = [];
|
|
109
107
|
const secrets = {};
|
|
110
|
-
this.info(`Resolving secrets from ${backendProvider.name}...`);
|
|
111
|
-
try {
|
|
112
|
-
const backendSecrets = await backendProvider.getSecrets(context);
|
|
113
|
-
Object.assign(secrets, backendSecrets);
|
|
114
|
-
} catch (e) {
|
|
115
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
116
|
-
this.error(`Failed to resolve secrets for ${backendProvider.name}: ${message}`);
|
|
117
|
-
}
|
|
118
|
-
this.info(`Resolving secrets from ${frontendProvider.name}...`);
|
|
119
|
-
try {
|
|
120
|
-
const frontendSecrets = await frontendProvider.getSecrets(context);
|
|
121
|
-
Object.assign(secrets, frontendSecrets);
|
|
122
|
-
} catch (e) {
|
|
123
|
-
const message = e instanceof Error ? e.message : String(e);
|
|
124
|
-
this.error(`Failed to resolve secrets for ${frontendProvider.name}: ${message}`);
|
|
125
|
-
}
|
|
126
|
-
await repoProvider.configureSecrets(context, secrets);
|
|
127
108
|
const variables = {};
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
109
|
+
this.info(`Deploying ${apps.length} applications in parallel...`);
|
|
110
|
+
const isManual = !!options.manual;
|
|
111
|
+
await Promise.all(
|
|
112
|
+
apps.map(async (app) => {
|
|
113
|
+
this.info(`Processing application: ${app.name}...`);
|
|
114
|
+
const provider = registry.getHostingProvider(app.provider);
|
|
115
|
+
if (!provider) {
|
|
116
|
+
this.error(`Provider '${app.provider}' not found for application '${app.name}'.`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (isManual && app.buildCommand) {
|
|
120
|
+
this.info(` Building ${app.name} locally...`);
|
|
121
|
+
if (context.options.dryRun) {
|
|
122
|
+
this.info(` [Dry Run] Would run build: ${app.buildCommand}`);
|
|
123
|
+
} else {
|
|
124
|
+
try {
|
|
125
|
+
const { execAsync } = await import("../deploy/utils.js");
|
|
126
|
+
await execAsync(app.buildCommand);
|
|
127
|
+
} catch (e) {
|
|
128
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
129
|
+
this.error(`Build failed for ${app.name}: ${message}`);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
this.info(` Provisioning ${app.name} with ${provider.name}...`);
|
|
135
|
+
await provider.provision(context, app);
|
|
136
|
+
if (isManual && provider.deploy) {
|
|
137
|
+
this.info(` Performing direct deployment for ${app.name}...`);
|
|
138
|
+
await provider.deploy(context, app);
|
|
139
|
+
}
|
|
140
|
+
this.info(` Resolving secrets for ${app.name} from ${provider.name}...`);
|
|
141
|
+
try {
|
|
142
|
+
const appSecrets = await provider.getSecrets(context, app);
|
|
143
|
+
Object.assign(secrets, appSecrets);
|
|
144
|
+
} catch (e) {
|
|
145
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
146
|
+
this.error(`Failed to resolve secrets for ${app.name} (${provider.name}): ${message}`);
|
|
147
|
+
}
|
|
148
|
+
this.info(` Resolving variables for ${app.name} from ${provider.name}...`);
|
|
149
|
+
try {
|
|
150
|
+
const appVars = await provider.getVariables(context, app);
|
|
151
|
+
Object.assign(variables, appVars);
|
|
152
|
+
} catch (e) {
|
|
153
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
154
|
+
this.error(`Failed to resolve variables for ${app.name} (${provider.name}): ${message}`);
|
|
155
|
+
}
|
|
156
|
+
activeApps.push({ provider, app });
|
|
157
|
+
})
|
|
158
|
+
);
|
|
159
|
+
this.info(`Configuring Repository with ${repoProvider.name}...`);
|
|
160
|
+
await repoProvider.configureSecrets(context, secrets);
|
|
142
161
|
await repoProvider.configureVariables(context, variables);
|
|
143
162
|
this.info("Generating CI/CD Workflows...");
|
|
144
|
-
await repoProvider.generateWorkflow(context,
|
|
163
|
+
await repoProvider.generateWorkflow(context, activeApps);
|
|
164
|
+
const dnsConfig = config.deploy?.dns;
|
|
165
|
+
if (dnsConfig?.provider) {
|
|
166
|
+
const dnsProvider = registry.getDnsProvider(dnsConfig.provider);
|
|
167
|
+
if (!dnsProvider) {
|
|
168
|
+
this.error(`DNS provider '${dnsConfig.provider}' not found.`);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
const dnsRecords = [];
|
|
172
|
+
for (const { app, provider } of activeApps) {
|
|
173
|
+
const target = app.dnsTarget || (provider.getDefaultDnsTarget ? provider.getDefaultDnsTarget(app) : void 0);
|
|
174
|
+
if (app.domain && target) {
|
|
175
|
+
const domains = Array.isArray(app.domain) ? app.domain : [app.domain];
|
|
176
|
+
for (const domain of domains) {
|
|
177
|
+
const isIp = /^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$/.test(target);
|
|
178
|
+
dnsRecords.push({
|
|
179
|
+
type: isIp ? "A" : "CNAME",
|
|
180
|
+
name: domain,
|
|
181
|
+
content: target,
|
|
182
|
+
proxied: true
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
} else if (app.domain && !target) {
|
|
186
|
+
this.warn(
|
|
187
|
+
`App '${app.name}' specifies domain(s) but no 'dnsTarget' could be inferred. Skipping DNS auto-provisioning.`
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
if (dnsRecords.length > 0) {
|
|
192
|
+
this.info(`Configuring DNS with ${dnsProvider.name}...`);
|
|
193
|
+
try {
|
|
194
|
+
await dnsProvider.provision(context, dnsRecords);
|
|
195
|
+
} catch (e) {
|
|
196
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
197
|
+
this.warn(`DNS provisioning failed: ${message}`);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
145
201
|
this.success("Deployment configuration complete!");
|
|
146
202
|
}
|
|
147
203
|
};
|
|
@@ -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 } 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 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: '--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 };\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
|
+
{"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":[]}
|