neonctl 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/package.json +13 -9
- package/src/api.js +8 -0
- package/src/commands/auth.js +39 -29
- package/src/commands/projects.js +49 -7
- package/src/commands/users.js +10 -4
- package/src/config.js +1 -4
- package/src/index.js +22 -54
- package/src/parameters.gen.js +67 -0
- package/src/utils.js +35 -0
- package/src/api/gateway.js +0 -72
- package/src/api/operations.js +0 -32
- package/src/api/projects.js +0 -13
- package/src/api/roles.js +0 -20
- package/src/api/users.js +0 -6
- package/src/commands/roles.js +0 -18
package/package.json
CHANGED
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
"type": "git",
|
|
5
5
|
"url": "git@github.com:neondatabase/neonctl.git"
|
|
6
6
|
},
|
|
7
|
-
"version": "1.
|
|
7
|
+
"version": "1.1.1",
|
|
8
8
|
"description": "CLI tool for NeonDB Cloud management",
|
|
9
9
|
"main": "index.js",
|
|
10
10
|
"author": "NeonDB",
|
|
11
11
|
"license": "MIT",
|
|
12
12
|
"private": false,
|
|
13
13
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
14
|
+
"node": ">=18"
|
|
15
15
|
},
|
|
16
16
|
"bin": {
|
|
17
17
|
"neonctl": "src/cli.js"
|
|
@@ -20,35 +20,39 @@
|
|
|
20
20
|
"@semantic-release/git": "^10.0.1",
|
|
21
21
|
"@types/cli-table": "^0.3.0",
|
|
22
22
|
"@types/node": "^18.7.13",
|
|
23
|
-
"@types/yargs": "^17.0.
|
|
23
|
+
"@types/yargs": "^17.0.24",
|
|
24
24
|
"@typescript-eslint/eslint-plugin": "^5.34.0",
|
|
25
25
|
"@typescript-eslint/parser": "^5.34.0",
|
|
26
26
|
"eslint": "^8.22.0",
|
|
27
27
|
"husky": "^8.0.1",
|
|
28
28
|
"lint-staged": "^13.0.3",
|
|
29
29
|
"prettier": "^2.7.1",
|
|
30
|
-
"semantic-release": "^
|
|
30
|
+
"semantic-release": "^21.0.2",
|
|
31
|
+
"ts-morph": "^18.0.0",
|
|
31
32
|
"ts-node": "^10.9.1",
|
|
32
33
|
"typescript": "^4.7.4"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
36
|
+
"@neondatabase/api-client": "^0.1.0",
|
|
37
|
+
"axios": "^1.4.0",
|
|
35
38
|
"cli-table": "^0.3.11",
|
|
36
39
|
"open": "^8.4.0",
|
|
37
40
|
"openid-client": "^5.1.9",
|
|
38
41
|
"yaml": "^2.1.1",
|
|
39
|
-
"yargs": "^17.
|
|
42
|
+
"yargs": "^17.7.2"
|
|
40
43
|
},
|
|
41
44
|
"publishConfig": {
|
|
42
45
|
"access": "public",
|
|
43
46
|
"registry": "https://registry.npmjs.org/"
|
|
44
47
|
},
|
|
45
48
|
"scripts": {
|
|
46
|
-
"
|
|
49
|
+
"watch": "tsc --watch",
|
|
47
50
|
"lint": "tsc --noEmit && eslint src --ext .ts",
|
|
48
|
-
"debug": "node --inspect-brk
|
|
49
|
-
"build": "npm run clean && tsc && cp src/*.html dist/src/",
|
|
51
|
+
"debug": "node --inspect-brk dist/src",
|
|
52
|
+
"build": "npm run generateParams && npm run clean && tsc && cp src/*.html dist/src/",
|
|
50
53
|
"clean": "rm -rf dist",
|
|
51
|
-
"
|
|
54
|
+
"generateParams": "ts-node generateParams.ts",
|
|
55
|
+
"start": "node src/index.js"
|
|
52
56
|
},
|
|
53
57
|
"lint-staged": {
|
|
54
58
|
"*.ts": [
|
package/src/api.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isApiError = exports.getApiClient = void 0;
|
|
4
|
+
const api_client_1 = require("@neondatabase/api-client");
|
|
5
|
+
const getApiClient = ({ apiKey, apiHost }) => (0, api_client_1.createApiClient)({ apiKey, baseURL: apiHost });
|
|
6
|
+
exports.getApiClient = getApiClient;
|
|
7
|
+
const isApiError = (err) => err instanceof Error && 'response' in err;
|
|
8
|
+
exports.isApiError = isApiError;
|
package/src/commands/auth.js
CHANGED
|
@@ -32,16 +32,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
32
32
|
});
|
|
33
33
|
};
|
|
34
34
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.ensureAuth = exports.authFlow = void 0;
|
|
35
|
+
exports.ensureAuth = exports.authFlow = exports.handler = exports.builder = exports.describe = exports.command = void 0;
|
|
36
36
|
const node_path_1 = require("node:path");
|
|
37
37
|
const node_fs_1 = require("node:fs");
|
|
38
38
|
const openid_client_1 = require("openid-client");
|
|
39
39
|
const auth_1 = require("../auth");
|
|
40
40
|
const log_1 = require("../log");
|
|
41
|
-
const
|
|
42
|
-
const gateway_1 = require("../api/gateway");
|
|
41
|
+
const api_1 = require("../api");
|
|
43
42
|
const CREDENTIALS_FILE = 'credentials.json';
|
|
44
|
-
|
|
43
|
+
exports.command = 'auth';
|
|
44
|
+
exports.describe = 'Authenticate';
|
|
45
|
+
const builder = (yargs) => yargs;
|
|
46
|
+
exports.builder = builder;
|
|
47
|
+
const handler = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
48
|
+
yield (0, exports.authFlow)(args);
|
|
49
|
+
});
|
|
50
|
+
exports.handler = handler;
|
|
51
|
+
const authFlow = ({ configDir, oauthHost, clientId, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
45
52
|
if (!clientId) {
|
|
46
53
|
throw new Error('Missing client id');
|
|
47
54
|
}
|
|
@@ -56,18 +63,6 @@ const authFlow = ({ 'config-dir': configDir, 'oauth-host': oauthHost, 'client-id
|
|
|
56
63
|
return tokenSet.access_token || '';
|
|
57
64
|
});
|
|
58
65
|
exports.authFlow = authFlow;
|
|
59
|
-
const validateToken = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
60
|
-
try {
|
|
61
|
-
yield (0, users_1.apiMe)(props);
|
|
62
|
-
}
|
|
63
|
-
catch (e) {
|
|
64
|
-
if (e instanceof gateway_1.ApiError) {
|
|
65
|
-
if (e.response.statusCode === 401) {
|
|
66
|
-
throw new Error('Invalid token');
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
66
|
// updateCredentialsFile correctly sets needed permissions for the credentials file
|
|
72
67
|
function updateCredentialsFile(path, contents) {
|
|
73
68
|
(0, node_fs_1.writeFileSync)(path, contents, {
|
|
@@ -75,31 +70,42 @@ function updateCredentialsFile(path, contents) {
|
|
|
75
70
|
});
|
|
76
71
|
}
|
|
77
72
|
const ensureAuth = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
78
|
-
|
|
73
|
+
var _a;
|
|
74
|
+
if (props._.length === 0) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
if (props.apiKey || props._[0] === 'auth') {
|
|
78
|
+
props.apiClient = (0, api_1.getApiClient)({
|
|
79
|
+
apiKey: props.apiKey,
|
|
80
|
+
apiHost: props.apiHost,
|
|
81
|
+
});
|
|
79
82
|
return;
|
|
80
83
|
}
|
|
81
|
-
const credentialsPath = (0, node_path_1.join)(props
|
|
84
|
+
const credentialsPath = (0, node_path_1.join)(props.configDir, CREDENTIALS_FILE);
|
|
82
85
|
if ((0, node_fs_1.existsSync)(credentialsPath)) {
|
|
83
86
|
try {
|
|
84
|
-
const tokenSetContents = yield Promise.resolve().then(() => __importStar(require(
|
|
87
|
+
const tokenSetContents = yield (_a = credentialsPath, Promise.resolve().then(() => __importStar(require(_a))));
|
|
85
88
|
const tokenSet = new openid_client_1.TokenSet(tokenSetContents);
|
|
86
89
|
if (tokenSet.expired()) {
|
|
87
90
|
log_1.log.info('using refresh token to update access token');
|
|
88
91
|
const refreshedTokenSet = yield (0, auth_1.refreshToken)({
|
|
89
|
-
oauthHost: props
|
|
90
|
-
clientId: props
|
|
92
|
+
oauthHost: props.oauthHost,
|
|
93
|
+
clientId: props.clientId,
|
|
91
94
|
}, tokenSet);
|
|
92
|
-
props.
|
|
95
|
+
props.apiKey = refreshedTokenSet.access_token || 'UNKNOWN';
|
|
96
|
+
props.apiClient = (0, api_1.getApiClient)({
|
|
97
|
+
apiKey: props.apiKey,
|
|
98
|
+
apiHost: props.apiHost,
|
|
99
|
+
});
|
|
93
100
|
updateCredentialsFile(credentialsPath, JSON.stringify(refreshedTokenSet));
|
|
94
101
|
return;
|
|
95
102
|
}
|
|
96
103
|
const token = tokenSet.access_token || 'UNKNOWN';
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
104
|
+
props.apiKey = token;
|
|
105
|
+
props.apiClient = (0, api_1.getApiClient)({
|
|
106
|
+
apiKey: props.apiKey,
|
|
107
|
+
apiHost: props.apiHost,
|
|
101
108
|
});
|
|
102
|
-
props.token = token;
|
|
103
109
|
return;
|
|
104
110
|
}
|
|
105
111
|
catch (e) {
|
|
@@ -107,11 +113,15 @@ const ensureAuth = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
107
113
|
// not a "file does not exist" error
|
|
108
114
|
throw e;
|
|
109
115
|
}
|
|
110
|
-
props.
|
|
116
|
+
props.apiKey = yield (0, exports.authFlow)(props);
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
else {
|
|
114
|
-
props.
|
|
120
|
+
props.apiKey = yield (0, exports.authFlow)(props);
|
|
115
121
|
}
|
|
122
|
+
props.apiClient = (0, api_1.getApiClient)({
|
|
123
|
+
apiKey: props.apiKey,
|
|
124
|
+
apiHost: props.apiHost,
|
|
125
|
+
});
|
|
116
126
|
});
|
|
117
127
|
exports.ensureAuth = ensureAuth;
|
package/src/commands/projects.js
CHANGED
|
@@ -9,16 +9,58 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
13
|
-
const
|
|
12
|
+
exports.builder = exports.describe = exports.command = void 0;
|
|
13
|
+
const parameters_gen_1 = require("../parameters.gen");
|
|
14
|
+
const utils_1 = require("../utils");
|
|
14
15
|
const writer_1 = require("../writer");
|
|
16
|
+
const PROJECT_FIELDS = ['id', 'name', 'region_id', 'created_at'];
|
|
17
|
+
exports.command = 'projects <command>';
|
|
18
|
+
exports.describe = 'Manage projects';
|
|
19
|
+
const builder = (yargs) => yargs
|
|
20
|
+
.usage('usage: $0 projects <cmd> [args]')
|
|
21
|
+
.command('list', 'List projects', (yargs) => yargs, (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
+
yield list(args);
|
|
23
|
+
}))
|
|
24
|
+
.command('create', 'Create a project', (yargs) => yargs.options(parameters_gen_1.projectCreateRequest), (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
25
|
+
yield create(args);
|
|
26
|
+
}))
|
|
27
|
+
.command('update', 'Update a project', (yargs) => yargs
|
|
28
|
+
.option('project.id', {
|
|
29
|
+
describe: 'Project ID',
|
|
30
|
+
type: 'string',
|
|
31
|
+
demandOption: true,
|
|
32
|
+
})
|
|
33
|
+
.options(parameters_gen_1.projectCreateRequest), (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
+
yield update(args);
|
|
35
|
+
}))
|
|
36
|
+
.command('delete', 'Delete a project', (yargs) => yargs.options({
|
|
37
|
+
'project.id': {
|
|
38
|
+
describe: 'Project ID',
|
|
39
|
+
type: 'string',
|
|
40
|
+
demandOption: true,
|
|
41
|
+
},
|
|
42
|
+
}), (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
yield deleteProject(args);
|
|
44
|
+
}))
|
|
45
|
+
.middleware(utils_1.showHelpMiddleware);
|
|
46
|
+
exports.builder = builder;
|
|
15
47
|
const list = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
-
(0, writer_1.writeOut)(props)(yield
|
|
17
|
-
fields:
|
|
48
|
+
(0, writer_1.writeOut)(props)((yield props.apiClient.listProjects({})).data.projects, {
|
|
49
|
+
fields: PROJECT_FIELDS,
|
|
18
50
|
});
|
|
19
51
|
});
|
|
20
|
-
exports.list = list;
|
|
21
52
|
const create = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
22
|
-
(0, writer_1.writeOut)(props)(yield
|
|
53
|
+
(0, writer_1.writeOut)(props)((yield props.apiClient.createProject({
|
|
54
|
+
project: props.project,
|
|
55
|
+
})).data.project, { fields: PROJECT_FIELDS });
|
|
56
|
+
});
|
|
57
|
+
const deleteProject = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
58
|
+
(0, writer_1.writeOut)(props)((yield props.apiClient.deleteProject(props.project.id)).data.project, {
|
|
59
|
+
fields: PROJECT_FIELDS,
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
const update = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
63
|
+
(0, writer_1.writeOut)(props)((yield props.apiClient.updateProject(props.project.id, {
|
|
64
|
+
project: props.project,
|
|
65
|
+
})).data.project, { fields: PROJECT_FIELDS });
|
|
23
66
|
});
|
|
24
|
-
exports.create = create;
|
package/src/commands/users.js
CHANGED
|
@@ -9,12 +9,18 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.
|
|
13
|
-
const users_1 = require("../api/users");
|
|
12
|
+
exports.handler = exports.builder = exports.describe = exports.command = void 0;
|
|
14
13
|
const writer_1 = require("../writer");
|
|
14
|
+
exports.command = 'me';
|
|
15
|
+
exports.describe = 'Show current user';
|
|
16
|
+
const builder = (yargs) => yargs;
|
|
17
|
+
exports.builder = builder;
|
|
18
|
+
const handler = (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
+
yield me(args);
|
|
20
|
+
});
|
|
21
|
+
exports.handler = handler;
|
|
15
22
|
const me = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
-
(0, writer_1.writeOut)(props)(yield
|
|
23
|
+
(0, writer_1.writeOut)(props)((yield props.apiClient.getCurrentUserInfo()).data, {
|
|
17
24
|
fields: ['login', 'email', 'name', 'projects_limit'],
|
|
18
25
|
});
|
|
19
26
|
});
|
|
20
|
-
exports.me = me;
|
package/src/config.js
CHANGED
|
@@ -13,10 +13,7 @@ exports.ensureConfigDir = exports.defaultDir = void 0;
|
|
|
13
13
|
const node_path_1 = require("node:path");
|
|
14
14
|
const node_os_1 = require("node:os");
|
|
15
15
|
const node_fs_1 = require("node:fs");
|
|
16
|
-
|
|
17
|
-
const cwdDir = (0, node_path_1.join)(process.cwd(), DIR_NAME);
|
|
18
|
-
const homeConfigDir = (0, node_path_1.join)((0, node_os_1.homedir)(), process.env.XDG_CONFIG_HOME || '.config', DIR_NAME);
|
|
19
|
-
exports.defaultDir = (0, node_fs_1.existsSync)(cwdDir) ? cwdDir : homeConfigDir;
|
|
16
|
+
exports.defaultDir = (0, node_path_1.join)((0, node_os_1.homedir)(), process.env.XDG_CONFIG_HOME || '.config', 'neonctl');
|
|
20
17
|
const ensureConfigDir = ({ 'config-dir': configDir, }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
21
18
|
if (!(0, node_fs_1.existsSync)(configDir)) {
|
|
22
19
|
(0, node_fs_1.mkdirSync)(configDir);
|
package/src/index.js
CHANGED
|
@@ -36,18 +36,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
36
36
|
};
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
38
38
|
const yargs = __importStar(require("yargs"));
|
|
39
|
+
const node_path_1 = require("node:path");
|
|
39
40
|
const package_json_1 = __importDefault(require("../package.json"));
|
|
40
|
-
const gateway_1 = require("./api/gateway");
|
|
41
41
|
const auth_1 = require("./commands/auth");
|
|
42
42
|
const config_1 = require("./config");
|
|
43
43
|
const log_1 = require("./log");
|
|
44
44
|
const auth_2 = require("./auth");
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
yargs.showHelp();
|
|
48
|
-
process.exit(0);
|
|
49
|
-
}
|
|
50
|
-
};
|
|
45
|
+
const api_1 = require("./api");
|
|
46
|
+
const utils_1 = require("./utils");
|
|
51
47
|
const builder = yargs
|
|
52
48
|
.scriptName(package_json_1.default.name)
|
|
53
49
|
.usage('usage: $0 <cmd> [args]')
|
|
@@ -60,7 +56,7 @@ const builder = yargs
|
|
|
60
56
|
})
|
|
61
57
|
.option('api-host', {
|
|
62
58
|
describe: 'The API host',
|
|
63
|
-
default: 'https://console.neon.tech',
|
|
59
|
+
default: 'https://console.neon.tech/api/v2',
|
|
64
60
|
})
|
|
65
61
|
// Setup config directory
|
|
66
62
|
.option('config-dir', {
|
|
@@ -79,56 +75,28 @@ const builder = yargs
|
|
|
79
75
|
type: 'string',
|
|
80
76
|
default: auth_2.defaultClientID,
|
|
81
77
|
})
|
|
82
|
-
.
|
|
83
|
-
|
|
84
|
-
}))
|
|
85
|
-
// Ensure auth token
|
|
86
|
-
.option('token', {
|
|
87
|
-
describe: 'Auth token',
|
|
78
|
+
.option('api-key', {
|
|
79
|
+
describe: 'API key',
|
|
88
80
|
type: 'string',
|
|
89
81
|
default: '',
|
|
90
82
|
})
|
|
91
|
-
.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
describe: 'Project ID',
|
|
100
|
-
type: 'string',
|
|
101
|
-
demandOption: true,
|
|
102
|
-
})
|
|
103
|
-
.option('role-name', {
|
|
104
|
-
describe: 'Role name',
|
|
105
|
-
type: 'string',
|
|
106
|
-
demandOption: true,
|
|
107
|
-
}), (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
108
|
-
yield (yield Promise.resolve().then(() => __importStar(require('./commands/roles')))).resetPwd(Object.assign(Object.assign({}, args), { role_name: args['role-name'], project_id: args['project-id'] }));
|
|
109
|
-
}))
|
|
110
|
-
.middleware(showHelpMiddleware)
|
|
111
|
-
.middleware(auth_1.ensureAuth);
|
|
112
|
-
}))
|
|
113
|
-
.command('projects', 'Manage projects', (yargs) => __awaiter(void 0, void 0, void 0, function* () {
|
|
114
|
-
yargs
|
|
115
|
-
.usage('usage: $0 projects <cmd> [args]')
|
|
116
|
-
.command('list', 'List projects', (yargs) => yargs, (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
117
|
-
yield (yield Promise.resolve().then(() => __importStar(require('./commands/projects')))).list(args);
|
|
118
|
-
}))
|
|
119
|
-
.command('create', 'Create a project', (yargs) => yargs.option('name', {
|
|
120
|
-
describe: 'Project name',
|
|
121
|
-
type: 'string',
|
|
122
|
-
}), (args) => __awaiter(void 0, void 0, void 0, function* () {
|
|
123
|
-
yield (yield Promise.resolve().then(() => __importStar(require('./commands/projects')))).create(args);
|
|
124
|
-
}))
|
|
125
|
-
.middleware(showHelpMiddleware)
|
|
126
|
-
.middleware(auth_1.ensureAuth);
|
|
127
|
-
}))
|
|
128
|
-
.strict()
|
|
83
|
+
.option('apiClient', {
|
|
84
|
+
hidden: true,
|
|
85
|
+
coerce: (v) => v,
|
|
86
|
+
default: true,
|
|
87
|
+
})
|
|
88
|
+
.middleware((args) => (0, utils_1.fillInArgs)(args), true)
|
|
89
|
+
.middleware(auth_1.ensureAuth)
|
|
90
|
+
.commandDir((0, node_path_1.join)(__dirname, './commands'))
|
|
129
91
|
.fail((msg, err) => __awaiter(void 0, void 0, void 0, function* () {
|
|
130
|
-
|
|
131
|
-
|
|
92
|
+
var _a;
|
|
93
|
+
if ((0, api_1.isApiError)(err)) {
|
|
94
|
+
if (err.response.status === 401) {
|
|
95
|
+
log_1.log.error('Authentication failed, please run `neonctl auth`');
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
log_1.log.error('%d: %s\n%s', err.response.status, err.response.statusText, (_a = err.response.data) === null || _a === void 0 ? void 0 : _a.message);
|
|
99
|
+
}
|
|
132
100
|
}
|
|
133
101
|
else {
|
|
134
102
|
log_1.log.error(msg || err.message);
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// FILE IS GENERATED, DO NOT EDIT
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.projectCreateRequest = void 0;
|
|
5
|
+
exports.projectCreateRequest = {
|
|
6
|
+
'project.settings.quota.active_time_seconds': {
|
|
7
|
+
type: 'number',
|
|
8
|
+
description: "The total amount of wall-clock time allowed to be spent by project's compute endpoints.",
|
|
9
|
+
},
|
|
10
|
+
'project.settings.quota.compute_time_seconds': {
|
|
11
|
+
type: 'number',
|
|
12
|
+
description: "The total amount of CPU seconds allowed to be spent by project's compute endpoints.",
|
|
13
|
+
},
|
|
14
|
+
'project.settings.quota.written_data_bytes': {
|
|
15
|
+
type: 'number',
|
|
16
|
+
description: "Total amount of data written to all project's branches.",
|
|
17
|
+
},
|
|
18
|
+
'project.settings.quota.data_transfer_bytes': {
|
|
19
|
+
type: 'number',
|
|
20
|
+
description: "Total amount of data transferred from all project's branches using proxy.",
|
|
21
|
+
},
|
|
22
|
+
'project.settings.quota.logical_size_bytes': {
|
|
23
|
+
type: 'number',
|
|
24
|
+
description: "Limit on the logical size of every project's branch.",
|
|
25
|
+
},
|
|
26
|
+
'project.name': {
|
|
27
|
+
type: 'string',
|
|
28
|
+
description: "The project name",
|
|
29
|
+
},
|
|
30
|
+
'project.branch.name': {
|
|
31
|
+
type: 'string',
|
|
32
|
+
description: "The branch name. If not specified, the default branch name will be used.",
|
|
33
|
+
},
|
|
34
|
+
'project.branch.role_name': {
|
|
35
|
+
type: 'string',
|
|
36
|
+
description: "The role name. If not specified, the default role name will be used.",
|
|
37
|
+
},
|
|
38
|
+
'project.branch.database_name': {
|
|
39
|
+
type: 'string',
|
|
40
|
+
description: "The database name. If not specified, the default database name will be used.",
|
|
41
|
+
},
|
|
42
|
+
'project.autoscaling_limit_min_cu': {
|
|
43
|
+
type: 'number',
|
|
44
|
+
description: "The minimum number of CPU units",
|
|
45
|
+
},
|
|
46
|
+
'project.autoscaling_limit_max_cu': {
|
|
47
|
+
type: 'number',
|
|
48
|
+
description: "The maximum number of CPU units",
|
|
49
|
+
},
|
|
50
|
+
'project.provisioner': {
|
|
51
|
+
type: 'string',
|
|
52
|
+
choices: ["k8s-pod", "k8s-neonvm", "docker"],
|
|
53
|
+
description: "The Neon compute provisioner.",
|
|
54
|
+
},
|
|
55
|
+
'project.region_id': {
|
|
56
|
+
type: 'string',
|
|
57
|
+
description: "The region identifier. See [the documentation](https://neon.tech/docs/introduction/regions) for the list of supported regions.",
|
|
58
|
+
},
|
|
59
|
+
'project.pg_version': {
|
|
60
|
+
type: 'number',
|
|
61
|
+
description: "The major PostgreSQL version number. Currently supported version are `14` and `15`.",
|
|
62
|
+
},
|
|
63
|
+
'project.store_passwords': {
|
|
64
|
+
type: 'boolean',
|
|
65
|
+
description: "Whether or not passwords are stored for roles in the Neon project. Storing passwords facilitates access to Neon features that require authorization.",
|
|
66
|
+
},
|
|
67
|
+
};
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.showHelpMiddleware = exports.fillInArgs = void 0;
|
|
7
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
8
|
+
/**
|
|
9
|
+
* This middleware is needed to fill in the args for nested objects,
|
|
10
|
+
* so that required arguments would work
|
|
11
|
+
* otherwise yargs just throws an error
|
|
12
|
+
*/
|
|
13
|
+
const fillInArgs = (args, currentArgs = args, acc = []) => {
|
|
14
|
+
Object.entries(currentArgs).forEach(([k, v]) => {
|
|
15
|
+
if (k === '_') {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// check if the value is an Object
|
|
19
|
+
if (typeof v === 'object' && v !== null) {
|
|
20
|
+
(0, exports.fillInArgs)(args, v, [...acc, k]);
|
|
21
|
+
}
|
|
22
|
+
else if (acc.length > 0) {
|
|
23
|
+
// if it's not an object, and we have a path, fill it in
|
|
24
|
+
args[acc.join('.') + '.' + k] = v;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
};
|
|
28
|
+
exports.fillInArgs = fillInArgs;
|
|
29
|
+
const showHelpMiddleware = (argv) => {
|
|
30
|
+
if (argv._.length === 1) {
|
|
31
|
+
yargs_1.default.showHelp();
|
|
32
|
+
process.exit(0);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
exports.showHelpMiddleware = showHelpMiddleware;
|
package/src/api/gateway.js
DELETED
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.apiCall = exports.ApiError = void 0;
|
|
13
|
-
const node_https_1 = require("node:https");
|
|
14
|
-
class ApiError extends Error {
|
|
15
|
-
constructor(response) {
|
|
16
|
-
super(response.statusMessage);
|
|
17
|
-
this.response = response;
|
|
18
|
-
}
|
|
19
|
-
getApiError() {
|
|
20
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
-
return new Promise((resolve, reject) => {
|
|
22
|
-
const data = [];
|
|
23
|
-
this.response
|
|
24
|
-
.on('data', (chunk) => {
|
|
25
|
-
data.push(chunk);
|
|
26
|
-
})
|
|
27
|
-
.on('end', () => {
|
|
28
|
-
try {
|
|
29
|
-
const json = JSON.parse(data.join(''));
|
|
30
|
-
resolve((json === null || json === void 0 ? void 0 : json.message) ||
|
|
31
|
-
`${this.response.statusCode}:${this.message}:${data.join('')}`);
|
|
32
|
-
}
|
|
33
|
-
catch (e) {
|
|
34
|
-
reject(e);
|
|
35
|
-
}
|
|
36
|
-
})
|
|
37
|
-
.on('error', (e) => {
|
|
38
|
-
reject(e);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
exports.ApiError = ApiError;
|
|
45
|
-
const apiCall = ({ apiHost, token, path, body, method = 'GET', }) => new Promise((resolve, reject) => {
|
|
46
|
-
const req = (0, node_https_1.request)(`${apiHost}/api/v1/${path}`, {
|
|
47
|
-
headers: {
|
|
48
|
-
Authorization: `Bearer ${token}`,
|
|
49
|
-
Accept: 'application/json',
|
|
50
|
-
'Content-Type': 'application/json',
|
|
51
|
-
},
|
|
52
|
-
method,
|
|
53
|
-
}, (res) => {
|
|
54
|
-
if (!res.statusCode || res.statusCode >= 400) {
|
|
55
|
-
reject(new ApiError(res));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
let result = '';
|
|
59
|
-
res.on('data', (data) => {
|
|
60
|
-
result += data;
|
|
61
|
-
});
|
|
62
|
-
res.on('end', () => {
|
|
63
|
-
resolve(JSON.parse(result));
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
req.on('error', reject);
|
|
67
|
-
if (body) {
|
|
68
|
-
req.write(JSON.stringify(body));
|
|
69
|
-
}
|
|
70
|
-
req.end();
|
|
71
|
-
});
|
|
72
|
-
exports.apiCall = apiCall;
|
package/src/api/operations.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.getOperation = exports.waitOperationFinalState = void 0;
|
|
13
|
-
const log_1 = require("../log");
|
|
14
|
-
const gateway_1 = require("./gateway");
|
|
15
|
-
function sleep(ms) {
|
|
16
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
17
|
-
}
|
|
18
|
-
// wait 20 sec max.
|
|
19
|
-
const waitOperationFinalState = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
20
|
-
for (let i = 0; i < 20; i++) {
|
|
21
|
-
const operation = yield (0, exports.getOperation)(Object.assign({}, props));
|
|
22
|
-
if (operation.status == 'finished') {
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
log_1.log.info(`Waiting for operation "${props.operation_id}" to finish`);
|
|
26
|
-
yield sleep(1000);
|
|
27
|
-
}
|
|
28
|
-
throw Error(`timeout while waiting for operation ${props.operation_id}`);
|
|
29
|
-
});
|
|
30
|
-
exports.waitOperationFinalState = waitOperationFinalState;
|
|
31
|
-
const getOperation = (props) => (0, gateway_1.apiCall)(Object.assign(Object.assign({}, props), { path: `projects/${props.project_id}/operations/${props.operation_id}`, method: 'GET' }));
|
|
32
|
-
exports.getOperation = getOperation;
|
package/src/api/projects.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createProject = exports.listProjects = void 0;
|
|
4
|
-
const gateway_1 = require("./gateway");
|
|
5
|
-
const listProjects = (props) => (0, gateway_1.apiCall)(Object.assign(Object.assign({}, props), { path: 'projects', method: 'GET' }));
|
|
6
|
-
exports.listProjects = listProjects;
|
|
7
|
-
const createProject = (props) => (0, gateway_1.apiCall)(Object.assign(Object.assign({}, props), { body: {
|
|
8
|
-
project: {
|
|
9
|
-
settings: props.settings,
|
|
10
|
-
name: props.name,
|
|
11
|
-
},
|
|
12
|
-
}, path: 'projects', method: 'POST' }));
|
|
13
|
-
exports.createProject = createProject;
|
package/src/api/roles.js
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.resetPassword = void 0;
|
|
13
|
-
const gateway_1 = require("./gateway");
|
|
14
|
-
const operations_1 = require("./operations");
|
|
15
|
-
const resetPassword = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
-
const response = yield (0, gateway_1.apiCall)(Object.assign(Object.assign({}, props), { path: `projects/${props.project_id}/roles/${props.role_name}/reset_password`, method: 'POST' }));
|
|
17
|
-
yield (0, operations_1.waitOperationFinalState)(Object.assign(Object.assign({}, props), response));
|
|
18
|
-
return response;
|
|
19
|
-
});
|
|
20
|
-
exports.resetPassword = resetPassword;
|
package/src/api/users.js
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.apiMe = void 0;
|
|
4
|
-
const gateway_1 = require("./gateway");
|
|
5
|
-
const apiMe = (props) => (0, gateway_1.apiCall)(Object.assign(Object.assign({}, props), { path: 'users/me', method: 'GET' }));
|
|
6
|
-
exports.apiMe = apiMe;
|
package/src/commands/roles.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.resetPwd = void 0;
|
|
13
|
-
const writer_1 = require("../writer");
|
|
14
|
-
const roles_1 = require("../api/roles");
|
|
15
|
-
const resetPwd = (props) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
-
(0, writer_1.writeOut)(props)(yield (0, roles_1.resetPassword)(props), { fields: ['dsn'] });
|
|
17
|
-
});
|
|
18
|
-
exports.resetPwd = resetPwd;
|