@aetherionfw/cli 1.0.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +42 -0
- package/dist/bin/aetherion.js +5 -0
- package/dist/commands/check-env.d.ts +1 -0
- package/dist/commands/check-env.js +120 -0
- package/dist/commands/docs.js +6 -1
- package/package.json +12 -4
- package/template/.env.example +12 -0
- package/template/aetherion.config.ts +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# @aetherionfw/cli
|
|
2
|
+
|
|
3
|
+
> Command Line Interface for the Aetherion Serverless Framework.
|
|
4
|
+
|
|
5
|
+
Aetherion is a modern, TypeScript-first serverless framework designed to bring the developer experience of frameworks like NestJS to AWS serverless architectures.
|
|
6
|
+
|
|
7
|
+
## Overview
|
|
8
|
+
|
|
9
|
+
This package provides the `aetherion` command to initialize, synthesize, deploy, and manage your applications.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @aetherionfw/cli
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
*Note: The CLI is typically installed locally in your project as a dev dependency.*
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
### `aetherion init <project-name>`
|
|
22
|
+
Scaffolds a new Aetherion project with the recommended directory structure, TypeScript configuration, and boilerplate code.
|
|
23
|
+
|
|
24
|
+
### `aetherion check-env`
|
|
25
|
+
Verifies your AWS credentials and connection using the STS `GetCallerIdentity` action. It reads your `aetherion.config.ts` and ensures you are deploying to the correct AWS account.
|
|
26
|
+
|
|
27
|
+
### `aetherion synth`
|
|
28
|
+
Synthesizes your infrastructure decorators into Terraform JSON (runs `cdktf synth` under the hood).
|
|
29
|
+
|
|
30
|
+
### `aetherion deploy`
|
|
31
|
+
Deploys your infrastructure to AWS (runs `cdktf deploy --auto-approve` under the hood).
|
|
32
|
+
|
|
33
|
+
### `aetherion docs`
|
|
34
|
+
Generates an OpenAPI specification from your `@Route` decorators and serves a local documentation UI using Scalar.
|
|
35
|
+
|
|
36
|
+
## Documentation
|
|
37
|
+
|
|
38
|
+
For full documentation, visit [https://github.com/CrisD3v/Aetherion-framework](https://github.com/CrisD3v/Aetherion-framework).
|
|
39
|
+
|
|
40
|
+
## License
|
|
41
|
+
|
|
42
|
+
MIT
|
package/dist/bin/aetherion.js
CHANGED
|
@@ -10,6 +10,7 @@ const init_1 = require("../commands/init");
|
|
|
10
10
|
const synth_1 = require("../commands/synth");
|
|
11
11
|
const deploy_1 = require("../commands/deploy");
|
|
12
12
|
const docs_1 = require("../commands/docs");
|
|
13
|
+
const check_env_1 = require("../commands/check-env");
|
|
13
14
|
const program = new commander_1.Command();
|
|
14
15
|
program
|
|
15
16
|
.name('aetherion')
|
|
@@ -32,6 +33,10 @@ program
|
|
|
32
33
|
.description('Generate OpenAPI documentation')
|
|
33
34
|
.option('-s, --serve', 'Serve the documentation using Scalar UI locally')
|
|
34
35
|
.action(docs_1.docsCommand);
|
|
36
|
+
program
|
|
37
|
+
.command('check-env')
|
|
38
|
+
.description('Verify AWS credentials and connection using STS GetCallerIdentity')
|
|
39
|
+
.action(check_env_1.checkEnvCommand);
|
|
35
40
|
program.parse(process.argv);
|
|
36
41
|
if (!process.argv.slice(2).length) {
|
|
37
42
|
program.outputHelp();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function checkEnvCommand(): Promise<void>;
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.checkEnvCommand = checkEnvCommand;
|
|
40
|
+
const path = __importStar(require("path"));
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
43
|
+
const ora_1 = __importDefault(require("ora"));
|
|
44
|
+
const client_sts_1 = require("@aws-sdk/client-sts");
|
|
45
|
+
const credential_providers_1 = require("@aws-sdk/credential-providers");
|
|
46
|
+
/**
|
|
47
|
+
* Loads aetherion.config.ts/js from the current working directory.
|
|
48
|
+
* Returns null if not found (will fall back to env vars / default profile).
|
|
49
|
+
*/
|
|
50
|
+
function loadConfig() {
|
|
51
|
+
const candidates = [
|
|
52
|
+
path.resolve(process.cwd(), 'aetherion.config.ts'),
|
|
53
|
+
path.resolve(process.cwd(), 'aetherion.config.js'),
|
|
54
|
+
];
|
|
55
|
+
for (const candidate of candidates) {
|
|
56
|
+
if (fs.existsSync(candidate)) {
|
|
57
|
+
try {
|
|
58
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
59
|
+
const mod = require(candidate);
|
|
60
|
+
return mod.default ?? mod;
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
// Ignore require errors — will be reported separately
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
async function checkEnvCommand() {
|
|
70
|
+
const spinner = (0, ora_1.default)('Reading Aetherion config...').start();
|
|
71
|
+
const fileConfig = loadConfig();
|
|
72
|
+
// Env vars always override the config file (CI/CD friendly)
|
|
73
|
+
const region = process.env.AWS_REGION ??
|
|
74
|
+
process.env.AWS_DEFAULT_REGION ??
|
|
75
|
+
fileConfig?.region ??
|
|
76
|
+
'us-east-1';
|
|
77
|
+
const profile = process.env.AWS_PROFILE ?? fileConfig?.profile;
|
|
78
|
+
const expectedAccountId = process.env.AWS_ACCOUNT_ID ?? fileConfig?.accountId;
|
|
79
|
+
spinner.text = 'Connecting to AWS STS...';
|
|
80
|
+
try {
|
|
81
|
+
const clientConfig = { region };
|
|
82
|
+
// Use named profile credentials when a profile is configured
|
|
83
|
+
if (profile) {
|
|
84
|
+
clientConfig.credentials = (0, credential_providers_1.fromIni)({ profile });
|
|
85
|
+
}
|
|
86
|
+
const client = new client_sts_1.STSClient(clientConfig);
|
|
87
|
+
const response = await client.send(new client_sts_1.GetCallerIdentityCommand({}));
|
|
88
|
+
spinner.succeed(chalk_1.default.green('AWS connection verified successfully!\n'));
|
|
89
|
+
console.log(chalk_1.default.bold(' Identity:'));
|
|
90
|
+
console.log(` ${chalk_1.default.dim('Account :')} ${chalk_1.default.cyan(response.Account)}`);
|
|
91
|
+
console.log(` ${chalk_1.default.dim('UserId :')} ${chalk_1.default.cyan(response.UserId)}`);
|
|
92
|
+
console.log(` ${chalk_1.default.dim('ARN :')} ${chalk_1.default.cyan(response.Arn)}`);
|
|
93
|
+
console.log(` ${chalk_1.default.dim('Region :')} ${chalk_1.default.cyan(region)}`);
|
|
94
|
+
if (profile) {
|
|
95
|
+
console.log(` ${chalk_1.default.dim('Profile :')} ${chalk_1.default.cyan(profile)}`);
|
|
96
|
+
}
|
|
97
|
+
// Warn if the resolved account differs from what is configured
|
|
98
|
+
if (expectedAccountId && response.Account !== expectedAccountId) {
|
|
99
|
+
console.log();
|
|
100
|
+
console.log(chalk_1.default.yellow(` ⚠ Warning: The active AWS account (${response.Account}) does not match` +
|
|
101
|
+
` the accountId in your config (${expectedAccountId}).`));
|
|
102
|
+
}
|
|
103
|
+
else if (expectedAccountId) {
|
|
104
|
+
console.log();
|
|
105
|
+
console.log(chalk_1.default.green(` ✔ Account matches aetherion.config.ts (${response.Account})`));
|
|
106
|
+
}
|
|
107
|
+
console.log();
|
|
108
|
+
}
|
|
109
|
+
catch (err) {
|
|
110
|
+
spinner.fail(chalk_1.default.red('AWS connection failed.'));
|
|
111
|
+
console.error();
|
|
112
|
+
console.error(chalk_1.default.red(` Error: ${err.message}`));
|
|
113
|
+
console.error();
|
|
114
|
+
console.error(chalk_1.default.dim(' Troubleshooting:'));
|
|
115
|
+
console.error(chalk_1.default.dim(' • Make sure your AWS credentials are configured (~/.aws/credentials or environment variables).'));
|
|
116
|
+
console.error(chalk_1.default.dim(' • If using a named profile, ensure it is set in aetherion.config.ts under the `profile` field.'));
|
|
117
|
+
console.error(chalk_1.default.dim(' • Verify that the profile has permission to call sts:GetCallerIdentity.'));
|
|
118
|
+
process.exit(1);
|
|
119
|
+
}
|
|
120
|
+
}
|
package/dist/commands/docs.js
CHANGED
|
@@ -44,6 +44,7 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
44
44
|
const docs_1 = require("@aetherionfw/docs");
|
|
45
45
|
const path = __importStar(require("path"));
|
|
46
46
|
const fs = __importStar(require("fs"));
|
|
47
|
+
const open_1 = __importDefault(require("open"));
|
|
47
48
|
async function docsCommand(options) {
|
|
48
49
|
const isServe = options.serve;
|
|
49
50
|
const spinner = (0, ora_1.default)('Preparing OpenAPI documentation...').start();
|
|
@@ -61,13 +62,17 @@ async function docsCommand(options) {
|
|
|
61
62
|
else {
|
|
62
63
|
spinner.warn(chalk_1.default.yellow('src/app.module.ts not found. API documentation might be empty.'));
|
|
63
64
|
}
|
|
65
|
+
// Always generate the static docs
|
|
66
|
+
(0, docs_1.generateStaticDocs)(process.cwd());
|
|
64
67
|
if (isServe) {
|
|
65
68
|
spinner.succeed(chalk_1.default.green('Starting Scalar API Reference Server...'));
|
|
66
69
|
(0, docs_1.startScalarServer)(3000);
|
|
70
|
+
const url = 'http://localhost:3000/docs';
|
|
71
|
+
console.log(chalk_1.default.cyan(`\nOpening browser at ${url}`));
|
|
72
|
+
await (0, open_1.default)(url);
|
|
67
73
|
// Keep process alive
|
|
68
74
|
}
|
|
69
75
|
else {
|
|
70
|
-
(0, docs_1.generateStaticDocs)(process.cwd());
|
|
71
76
|
spinner.succeed(chalk_1.default.green('Documentation generated at openapi.json'));
|
|
72
77
|
}
|
|
73
78
|
}
|
package/package.json
CHANGED
|
@@ -1,25 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aetherionfw/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "CLI for Aetherion Framework",
|
|
5
5
|
"bin": {
|
|
6
6
|
"aetherion": "dist/bin/aetherion.js"
|
|
7
7
|
},
|
|
8
8
|
"dependencies": {
|
|
9
|
+
"@aws-sdk/client-sts": "^3.0.0",
|
|
10
|
+
"@aws-sdk/credential-providers": "^3.0.0",
|
|
9
11
|
"chalk": "^4.1.2",
|
|
10
12
|
"commander": "^11.0.0",
|
|
11
13
|
"fs-extra": "^11.1.1",
|
|
14
|
+
"open": "^8.4.2",
|
|
12
15
|
"ora": "^5.4.1",
|
|
13
16
|
"ts-node": "^10.9.2",
|
|
14
|
-
"@aetherionfw/docs": "1.
|
|
17
|
+
"@aetherionfw/docs": "1.1.1"
|
|
15
18
|
},
|
|
16
19
|
"devDependencies": {
|
|
17
20
|
"@types/fs-extra": "^11.0.1",
|
|
18
21
|
"@types/node": "^20.0.0",
|
|
19
22
|
"typescript": "^5.5.4",
|
|
20
23
|
"vitest": "^2.0.5",
|
|
21
|
-
"@aetherionfw/core": "1.
|
|
22
|
-
"@aetherionfw/infra": "1.
|
|
24
|
+
"@aetherionfw/core": "1.1.1",
|
|
25
|
+
"@aetherionfw/infra": "1.1.1"
|
|
23
26
|
},
|
|
24
27
|
"publishConfig": {
|
|
25
28
|
"access": "public"
|
|
@@ -32,6 +35,11 @@
|
|
|
32
35
|
],
|
|
33
36
|
"author": "CrisD3v",
|
|
34
37
|
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "https://github.com/CrisD3v/Aetherion-framework.git",
|
|
41
|
+
"directory": "packages/cli"
|
|
42
|
+
},
|
|
35
43
|
"scripts": {
|
|
36
44
|
"build": "tsc",
|
|
37
45
|
"clean": "rm -rf dist"
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Aetherion deployment environment variables
|
|
2
|
+
# Copy this file to .env and fill in your values.
|
|
3
|
+
# Never commit .env to version control.
|
|
4
|
+
|
|
5
|
+
# Your AWS Account ID (12-digit number)
|
|
6
|
+
AWS_ACCOUNT_ID=123456789012
|
|
7
|
+
|
|
8
|
+
# Target AWS region
|
|
9
|
+
AWS_REGION=us-east-1
|
|
10
|
+
|
|
11
|
+
# Named AWS CLI profile from ~/.aws/credentials (leave empty in CI/CD)
|
|
12
|
+
AWS_PROFILE=default
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { defineConfig } from '@aetherionfw/core';
|
|
2
|
+
import 'dotenv/config';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Aetherion deployment configuration.
|
|
6
|
+
*
|
|
7
|
+
* Environment variables always override these values — useful for CI/CD pipelines.
|
|
8
|
+
* Sensitive values (account IDs, secrets) should be loaded from environment variables
|
|
9
|
+
* or a secrets manager rather than hardcoded here.
|
|
10
|
+
*
|
|
11
|
+
* Required env vars (can be set in a .env file):
|
|
12
|
+
* AWS_ACCOUNT_ID - Your AWS account ID
|
|
13
|
+
* AWS_REGION - Target region (e.g. us-east-1)
|
|
14
|
+
* AWS_PROFILE - Named profile from ~/.aws/credentials (optional for CI/CD)
|
|
15
|
+
*/
|
|
16
|
+
export default defineConfig({
|
|
17
|
+
/**
|
|
18
|
+
* AWS Account ID.
|
|
19
|
+
* Run `aws sts get-caller-identity` or `aetherion check-env` to find yours.
|
|
20
|
+
*/
|
|
21
|
+
accountId: process.env.AWS_ACCOUNT_ID!,
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* AWS region where all resources will be deployed.
|
|
25
|
+
*/
|
|
26
|
+
region: process.env.AWS_REGION ?? 'us-east-1',
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Named AWS CLI profile for local development.
|
|
30
|
+
* Remove or leave undefined when deploying from CI/CD using IAM roles or env vars.
|
|
31
|
+
*/
|
|
32
|
+
profile: process.env.AWS_PROFILE ?? 'default',
|
|
33
|
+
});
|