@getxflow/cli 1.3.0 → 1.4.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 CHANGED
@@ -10,7 +10,7 @@ cd my-app/apps/my-app && npm install && xflow dev
10
10
  xflow deploy -m "First version"
11
11
  ```
12
12
 
13
- Requires Node 20+. The package has no dependencies: it holds an access key, and nobody
13
+ Requires Node 22+. The package has no dependencies: it holds an access key, and nobody
14
14
  else's code belongs next to it.
15
15
 
16
16
  | Command | What it does |
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.orgList = orgList;
4
4
  exports.orgMembers = orgMembers;
5
+ exports.findOrg = findOrg;
5
6
  exports.orgSwitch = orgSwitch;
6
7
  const api_1 = require("../api");
7
8
  const config_1 = require("../config");
@@ -47,6 +48,19 @@ async function orgMembers() {
47
48
  const count = data.truncated ? `${data.members.length} of ${data.total}` : String(data.total);
48
49
  (0, ui_1.note)((0, ui_1.dim)(` ${count} in "${org ? label(org) : 'the organization'}". Inviting and removing people happens in the platform interface`));
49
50
  }
51
+ /** An organization by id, or by name ignoring case; a name shared by several asks for the id. */
52
+ function findOrg(orgs, wanted) {
53
+ const byId = orgs.find((org) => org.organizationId === wanted);
54
+ if (byId)
55
+ return byId;
56
+ const byName = orgs.filter((org) => (org.name ?? '').toLowerCase() === wanted.toLowerCase());
57
+ if (byName.length > 1) {
58
+ throw new errors_1.CliError(`Several organizations are named "${wanted}"`, `Use the id instead: ${byName.map((org) => org.organizationId).join(', ')}`);
59
+ }
60
+ if (!byName[0])
61
+ throw new errors_1.CliError(`No stored key for "${wanted}"`, 'The list: xflow org. To add one: xflow login');
62
+ return byName[0];
63
+ }
50
64
  /** Local switch of the active organization: a pointer move, no browser. */
51
65
  function orgSwitch(args) {
52
66
  const wanted = args.words[0];
@@ -57,15 +71,7 @@ function orgSwitch(args) {
57
71
  if (orgs.length === 0) {
58
72
  throw new errors_1.CliError(`No keys for ${apiUrl}`, 'Sign in: xflow login');
59
73
  }
60
- const byId = orgs.find((org) => org.organizationId === wanted);
61
- const byName = orgs.filter((org) => (org.name ?? '').toLowerCase() === wanted.toLowerCase());
62
- if (!byId && byName.length > 1) {
63
- throw new errors_1.CliError(`Several organizations are named "${wanted}"`, `Use the id instead: ${byName.map((org) => org.organizationId).join(', ')}`);
64
- }
65
- const target = byId ?? byName[0];
66
- if (!target) {
67
- throw new errors_1.CliError(`No stored key for "${wanted}"`, 'The list: xflow org. To add one: xflow login');
68
- }
74
+ const target = findOrg(orgs, wanted);
69
75
  if (target.active) {
70
76
  (0, ui_1.ok)(`"${label(target)}" is already the active organization`);
71
77
  return;
@@ -13,6 +13,7 @@ const args_1 = require("../args");
13
13
  const config_1 = require("../config");
14
14
  const credentials_1 = require("../credentials");
15
15
  const errors_1 = require("../errors");
16
+ const org_1 = require("./org");
16
17
  const session_1 = require("../session");
17
18
  const skills_1 = require("./skills");
18
19
  const sources_1 = require("./sources");
@@ -61,12 +62,25 @@ async function init(args) {
61
62
  const target = (0, node_path_1.resolve)(args.words[0] ?? '.');
62
63
  const name = (0, args_1.flagString)(args, 'name') ?? (0, node_path_1.basename)(target);
63
64
  const noApp = (0, args_1.flagBool)(args, 'no-app');
64
- const client = (0, session_1.connect)();
65
+ let client = (0, session_1.connect)();
66
+ // A person in several organizations names the one that gets the project: the active one may be a client's.
67
+ const orgs = client.source === 'env' ? [] : (0, credentials_1.listOrgs)(client.apiUrl);
68
+ const wanted = (0, args_1.flagString)(args, 'org');
69
+ if (wanted) {
70
+ if (client.source === 'env')
71
+ throw new errors_1.CliError('--org does not apply to a key from XFLOW_TOKEN', 'That key belongs to one organization: drop --org');
72
+ const org = (0, org_1.findOrg)(orgs, wanted);
73
+ client = { apiUrl: client.apiUrl, token: org.token, source: 'folder', organizationId: org.organizationId };
74
+ }
75
+ else if (orgs.length > 1) {
76
+ throw new errors_1.CliError(`You are signed in to ${orgs.length} organizations: name the one that gets the project`, `xflow init ${args.words[0] ?? '.'} --org <name>. The list: xflow org`);
77
+ }
78
+ const orgName = orgs.find((org) => org.organizationId === client.organizationId)?.name;
65
79
  if (!isEmptyEnough(target)) {
66
80
  throw new errors_1.CliError(`The directory ${target} is not empty`, 'Create the project in an empty folder: xflow init my-project. To link an existing folder to a project: xflow link <id>');
67
81
  }
68
82
  const folder = noApp ? null : checkFolder((0, args_1.flagString)(args, 'app') ?? (0, sources_1.appFolderName)(name, new Set(), 'app'));
69
- (0, ui_1.step)('Creating the project on the platform');
83
+ (0, ui_1.step)(orgName ? `Creating the project in "${orgName}"` : 'Creating the project on the platform');
70
84
  const project = await (0, api_1.apiJson)(client, '/api/v1/projects', {
71
85
  method: 'POST',
72
86
  body: { name, app: folder ? { name } : null, server: (0, args_1.flagString)(args, 'server') ?? null },
package/dist/flags.js CHANGED
@@ -44,7 +44,7 @@ exports.KNOWN = {
44
44
  'org list': [],
45
45
  'org members': [],
46
46
  'org switch': [],
47
- init: ['name', 'app', 'no-app', 'server'],
47
+ init: ['name', 'app', 'no-app', 'server', 'org'],
48
48
  link: [],
49
49
  projects: [],
50
50
  'projects list': [],
@@ -118,7 +118,7 @@ exports.KNOWN = {
118
118
  * line here, or a refusal nobody prints any more stays behind as a lie.
119
119
  */
120
120
  exports.WORKING_COPY = {
121
- pull: 'it writes the sources next to it',
121
+ pull: 'it writes the sources next to it. A project without a folder comes down whole with xflow link <id> in an empty one',
122
122
  status: 'it compares the folder with the revision on the platform',
123
123
  dev: 'it runs the dev server of the app folder it stands in',
124
124
  'apps add': 'it lays the template into apps/',
package/dist/help.js CHANGED
@@ -778,6 +778,8 @@ change them, restyle them or delete what you do not use.
778
778
  --no-app a project without apps: its functions are workflows
779
779
  --server <name> the database of the project, right away on that server:
780
780
  platform, or an own server of the organization (xflow db list)
781
+ --org <name> the organization that gets the project; required when you are
782
+ signed in to several (xflow org)
781
783
 
782
784
  More apps later: ${(0, ui_1.bold)('xflow apps add <folder>')}. If writing the files fails, the project stays
783
785
  on the platform and the CLI says how to pick it up with the link command.`,
package/dist/version.js CHANGED
@@ -2,6 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.DEFAULT_API_URL = exports.CLI_VERSION = void 0;
4
4
  /** Keep in sync with cli/package.json. */
5
- exports.CLI_VERSION = '1.3.0';
5
+ exports.CLI_VERSION = '1.4.0';
6
6
  /** Overridden by XFLOW_API_URL or the `api` field in xflow.json. */
7
7
  exports.DEFAULT_API_URL = 'https://app.getxflow.com';
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@getxflow/cli",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "CLI for the XFlow platform: projects with apps, functions and a database; source sync, deployment and publishing",
5
5
  "license": "UNLICENSED",
6
6
  "engines": {
7
- "node": ">=20"
7
+ "node": ">=22"
8
8
  },
9
9
  "bin": {
10
10
  "xflow": "dist/bin.js"