neonctl 1.35.0 → 1.36.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.
@@ -24,7 +24,12 @@ export const aliases = ['project'];
24
24
  export const builder = (argv) => {
25
25
  return argv
26
26
  .usage('$0 projects <sub-command> [options]')
27
- .command('list', 'List projects', (yargs) => yargs, async (args) => {
27
+ .command('list', 'List projects', (yargs) => yargs.options({
28
+ 'org-id': {
29
+ describe: 'List projects of a given organization',
30
+ type: 'string',
31
+ },
32
+ }), async (args) => {
28
33
  await list(args);
29
34
  })
30
35
  .command('create', 'Create a project', (yargs) => yargs.options({
@@ -36,6 +41,10 @@ export const builder = (argv) => {
36
41
  describe: `The region ID. Possible values: ${REGIONS.join(', ')}`,
37
42
  type: 'string',
38
43
  },
44
+ 'org-id': {
45
+ describe: "The project's organization ID",
46
+ type: 'string',
47
+ },
39
48
  psql: {
40
49
  type: 'boolean',
41
50
  describe: 'Connect to a new project via psql',
@@ -103,6 +112,7 @@ const list = async (props) => {
103
112
  while (!end) {
104
113
  const { data } = await fn({
105
114
  limit: PROJECTS_LIST_LIMIT,
115
+ org_id: props.orgId,
106
116
  cursor,
107
117
  });
108
118
  result.push(...data.projects);
@@ -114,19 +124,21 @@ const list = async (props) => {
114
124
  }
115
125
  return result;
116
126
  };
117
- const [ownedProjects, sharedProjects] = await Promise.all([
118
- getList(props.apiClient.listProjects),
119
- getList(props.apiClient.listSharedProjects),
120
- ]);
127
+ const ownedProjects = getList(props.apiClient.listProjects);
128
+ const sharedProjects = props.orgId
129
+ ? undefined
130
+ : getList(props.apiClient.listSharedProjects);
121
131
  const out = writer(props);
122
- out.write(ownedProjects, {
132
+ out.write(await ownedProjects, {
123
133
  fields: PROJECT_FIELDS,
124
134
  title: 'Projects',
125
135
  });
126
- out.write(sharedProjects, {
127
- fields: PROJECT_FIELDS,
128
- title: 'Shared with me',
129
- });
136
+ if (sharedProjects) {
137
+ out.write(await sharedProjects, {
138
+ fields: PROJECT_FIELDS,
139
+ title: 'Shared with me',
140
+ });
141
+ }
130
142
  out.end();
131
143
  };
132
144
  const create = async (props) => {
@@ -137,6 +149,9 @@ const create = async (props) => {
137
149
  if (props.regionId) {
138
150
  project.region_id = props.regionId;
139
151
  }
152
+ if (props.orgId) {
153
+ project.org_id = props.orgId;
154
+ }
140
155
  project.branch = {};
141
156
  if (props.database) {
142
157
  project.branch.database_name = props.database;
@@ -7,9 +7,22 @@ describe('projects', () => {
7
7
  test('list', async ({ testCliCommand }) => {
8
8
  await testCliCommand(['projects', 'list']);
9
9
  });
10
+ test('list with org id', async ({ testCliCommand }) => {
11
+ await testCliCommand(['projects', 'list', '--org-id', 'org-2']);
12
+ });
10
13
  test('create', async ({ testCliCommand }) => {
11
14
  await testCliCommand(['projects', 'create', '--name', 'test_project']);
12
15
  });
16
+ test('create with org id', async ({ testCliCommand }) => {
17
+ await testCliCommand([
18
+ 'projects',
19
+ 'create',
20
+ '--name',
21
+ 'test_project',
22
+ '--org-id',
23
+ 'org-2',
24
+ ]);
25
+ });
13
26
  test('create with database and role', async ({ testCliCommand }) => {
14
27
  await testCliCommand([
15
28
  'projects',
@@ -6,10 +6,15 @@ export const builder = (argv) => argv.usage('$0 set-context [options]').options(
6
6
  describe: 'Project ID',
7
7
  type: 'string',
8
8
  },
9
+ 'org-id': {
10
+ describe: 'Organization ID',
11
+ type: 'string',
12
+ },
9
13
  });
10
14
  export const handler = (props) => {
11
15
  const context = {
12
16
  projectId: props.projectId,
17
+ orgId: props.orgId,
13
18
  };
14
19
  updateContextFile(props.contextFile, context);
15
20
  };
@@ -28,7 +28,7 @@ const test = originalTest.extend({
28
28
  },
29
29
  });
30
30
  describe('set_context', () => {
31
- describe('should set the context', () => {
31
+ describe('should set the context to project', () => {
32
32
  test('set-context', async ({ testCliCommand, readFile }) => {
33
33
  await testCliCommand([
34
34
  'set-context',
@@ -93,4 +93,67 @@ describe('set_context', () => {
93
93
  });
94
94
  });
95
95
  });
96
+ describe('should set the context to organization', () => {
97
+ test('set-context', async ({ testCliCommand, readFile }) => {
98
+ await testCliCommand([
99
+ 'set-context',
100
+ '--org-id',
101
+ 'org-2',
102
+ '--context-file',
103
+ CONTEXT_FILE,
104
+ ]);
105
+ expect(readFile(CONTEXT_FILE)).toMatchSnapshot();
106
+ });
107
+ test('list projects selecting organization from the context', async ({ testCliCommand, writeFile, }) => {
108
+ writeFile(CONTEXT_FILE, {
109
+ orgId: 'org-2',
110
+ });
111
+ await testCliCommand([
112
+ 'projects',
113
+ 'list',
114
+ '--context-file',
115
+ CONTEXT_FILE,
116
+ ]);
117
+ });
118
+ test('list projects with explicit org id overrides context', async ({ testCliCommand, writeFile, }) => {
119
+ writeFile(CONTEXT_FILE, {
120
+ orgId: 'org-2',
121
+ });
122
+ await testCliCommand([
123
+ 'project',
124
+ 'list',
125
+ '--org-id',
126
+ 'org-3',
127
+ '--context-file',
128
+ CONTEXT_FILE,
129
+ ]);
130
+ });
131
+ test('create projects selecting organization from the context', async ({ testCliCommand, writeFile, }) => {
132
+ writeFile(CONTEXT_FILE, {
133
+ orgId: 'org-2',
134
+ });
135
+ await testCliCommand([
136
+ 'projects',
137
+ 'create',
138
+ '--name',
139
+ 'test_project',
140
+ '--context-file',
141
+ CONTEXT_FILE,
142
+ ]);
143
+ });
144
+ });
145
+ describe('can set the context to project and organization at the same time', () => {
146
+ test('set-context', async ({ testCliCommand, readFile }) => {
147
+ await testCliCommand([
148
+ 'set-context',
149
+ '--project-id',
150
+ 'test_project',
151
+ '--org-id',
152
+ 'org-2',
153
+ '--context-file',
154
+ CONTEXT_FILE,
155
+ ]);
156
+ expect(readFile(CONTEXT_FILE)).toMatchSnapshot();
157
+ });
158
+ });
96
159
  });
package/context.js CHANGED
@@ -36,6 +36,9 @@ export const enrichFromContext = (args) => {
36
36
  return;
37
37
  }
38
38
  const context = readContextFile(args.contextFile);
39
+ if (!args.orgId) {
40
+ args.orgId = context.orgId;
41
+ }
39
42
  if (!args.projectId) {
40
43
  args.projectId = context.projectId;
41
44
  }
package/package.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "url": "git+ssh://git@github.com/neondatabase/neonctl.git"
6
6
  },
7
7
  "type": "module",
8
- "version": "1.35.0",
8
+ "version": "1.36.0",
9
9
  "description": "CLI tool for NeonDB Cloud management",
10
10
  "main": "index.js",
11
11
  "author": "NeonDB",