@seliseblocks/cli-os 0.1.3 → 0.1.4

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.
@@ -0,0 +1 @@
1
+ export declare function deselectProject(argv: string[]): Promise<void>;
@@ -0,0 +1,31 @@
1
+ import { normalizeAccountName, readConfig } from "../lib/config.js";
2
+ import { readTokenStore, writeTokenStore } from "../lib/token-store.js";
3
+ import { requestContext } from "../lib/request-context.js";
4
+ import { clearSelectedProject, parseCommand } from "../lib/workspace.js";
5
+ export async function deselectProject(argv) {
6
+ const { flags } = parseCommand(argv);
7
+ const config = await readConfig();
8
+ const { accountName } = requestContext(flags);
9
+ const account = normalizeAccountName(accountName ?? config.activeAccount);
10
+ const tenantId = await clearSelectedProject();
11
+ if (!tenantId) {
12
+ console.log("No project is currently selected.");
13
+ return;
14
+ }
15
+ const store = await readTokenStore();
16
+ const projects = store.accounts[account]?.projects;
17
+ if (projects && tenantId in projects) {
18
+ const { [tenantId]: _removed, ...remainingProjects } = projects;
19
+ await writeTokenStore({
20
+ accounts: {
21
+ ...store.accounts,
22
+ [account]: {
23
+ ...store.accounts[account],
24
+ projects: remainingProjects
25
+ }
26
+ }
27
+ });
28
+ }
29
+ console.log(`Deselected project tenant ${tenantId}.`);
30
+ console.log("Run 'blocks-os use <tenantId>' to select a project again.");
31
+ }
@@ -2,13 +2,15 @@ import { stringFlag } from "../../../lib/args.js";
2
2
  import { blocksRequest } from "../../../lib/api.js";
3
3
  import { writeOutput } from "../../../lib/output.js";
4
4
  import { requestContext } from "../../../lib/request-context.js";
5
- import { parseCommand } from "../../../lib/workspace.js";
5
+ import { parseCommand, selectedProject } from "../../../lib/workspace.js";
6
6
  export async function releaseBuildsList(argv) {
7
7
  const { args, flags } = parseCommand(argv);
8
8
  const repoId = args[0] || stringFlag(flags, "repo-id", { required: true });
9
+ const projectKey = await selectedProject(flags);
9
10
  const result = await blocksRequest("/release/v4/api/Build/repo-details", {
10
- accountAuth: true,
11
+ impersonatedProjectAuth: true,
11
12
  ...requestContext(flags),
13
+ projectTenantId: projectKey,
12
14
  query: { RepoId: repoId }
13
15
  });
14
16
  writeOutput(result, flags);
@@ -3,7 +3,7 @@ import { blocksRequest } from "../../lib/api.js";
3
3
  import { confirmMutation } from "../../lib/confirm.js";
4
4
  import { writeOutput } from "../../lib/output.js";
5
5
  import { requestContext } from "../../lib/request-context.js";
6
- import { parseCommand, pathsFromWorkspace, readWorkspaceConfig } from "../../lib/workspace.js";
6
+ import { parseCommand, pathsFromWorkspace, readWorkspaceConfig, selectedProject } from "../../lib/workspace.js";
7
7
  import { readFile } from "node:fs/promises";
8
8
  export async function releaseDeploy(argv) {
9
9
  const { flags } = parseCommand(argv);
@@ -20,10 +20,12 @@ export async function releaseDeploy(argv) {
20
20
  return;
21
21
  }
22
22
  await confirmMutation(flags, `Trigger configured release build for repo '${repoId}'.`);
23
+ const projectKey = await selectedProject(flags);
23
24
  const result = await blocksRequest("/release/v4/api/Build/manual", {
24
- accountAuth: true,
25
+ impersonatedProjectAuth: true,
25
26
  ...requestContext(flags),
26
- body
27
+ body,
28
+ projectTenantId: projectKey
27
29
  });
28
30
  writeOutput(result, flags);
29
31
  }
@@ -2,13 +2,15 @@ import { stringFlag } from "../../lib/args.js";
2
2
  import { blocksRequest } from "../../lib/api.js";
3
3
  import { writeOutput } from "../../lib/output.js";
4
4
  import { requestContext } from "../../lib/request-context.js";
5
- import { parseCommand } from "../../lib/workspace.js";
5
+ import { parseCommand, selectedProject } from "../../lib/workspace.js";
6
6
  export async function releaseStatus(argv) {
7
7
  const { args, flags } = parseCommand(argv);
8
8
  const buildId = args[0] || stringFlag(flags, "build-id", { required: true });
9
+ const projectKey = await selectedProject(flags);
9
10
  const result = await blocksRequest("/release/v4/api/Build", {
10
- accountAuth: true,
11
+ impersonatedProjectAuth: true,
11
12
  ...requestContext(flags),
13
+ projectTenantId: projectKey,
12
14
  query: { buildId }
13
15
  });
14
16
  writeOutput(result, flags);
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { authRefresh } from "./commands/auth/refresh.js";
2
2
  import { authRemove } from "./commands/auth/remove.js";
3
3
  import { authStatus } from "./commands/auth/status.js";
4
+ import { deselectProject } from "./commands/deselect.js";
4
5
  import { doctor } from "./commands/doctor.js";
5
6
  import { dataReload } from "./commands/data/reload.js";
6
7
  import { dataValidate } from "./commands/data/validate.js";
@@ -79,6 +80,9 @@ try {
79
80
  else if (command === "use") {
80
81
  await useProject([subcommand, ...rest].filter(Boolean));
81
82
  }
83
+ else if (command === "deselect") {
84
+ await deselectProject([subcommand, ...rest].filter(Boolean));
85
+ }
82
86
  else if (command === "new" && subcommand === "web") {
83
87
  await newWeb(rest);
84
88
  }
@@ -226,6 +230,12 @@ Projects:
226
230
  Save the selected project tenant globally and in blocks.json when present.
227
231
  Does not call cloud APIs.
228
232
 
233
+ blocks-os deselect
234
+ Clear the selected project tenant (globally and in blocks.json) and drop
235
+ its cached impersonation token. Use this to recover when an impersonated
236
+ project token has expired or failed, then run 'blocks-os use <tenantId>'
237
+ again to reselect and re-impersonate.
238
+
229
239
  IAM:
230
240
  blocks-os iam:me [--json]
231
241
  Read the current user from IAM using the account token. This is the only IAM
@@ -275,23 +285,31 @@ Localization:
275
285
 
276
286
  Release:
277
287
  blocks-os release:deploy --repo-id <repoId> [--dry-run] [--yes] [--json]
278
- Trigger a manual Release build/deploy for a configured repository. Mutating;
279
- no artifact upload is performed by this CLI.
288
+ Trigger a manual Release build/deploy for a configured repository using an
289
+ impersonated project token. Mutating; no artifact upload is performed by
290
+ this CLI.
280
291
 
281
292
  blocks-os release:status <buildId> [--json]
282
- Read Release build status by build id. Read-only.
293
+ Read Release build status by build id using an impersonated project
294
+ token. Read-only.
283
295
 
284
296
  blocks-os release:builds:list --repo-id <repoId> [--json]
285
- List Release build details for a repository. Read-only.
297
+ List Release build details for a repository using an impersonated project
298
+ token. Read-only.
286
299
 
287
300
  blocks-os release:builds:get <buildId> [--json]
288
301
  Alias for release:status. Read-only.
289
302
 
290
303
  Scaffold:
291
304
  blocks-os new web <name> --x-blocks-key <tenantId> --app-domain <domain> [--client-id <oidcClientId>]
305
+ [--blocks-api-url <url>] [--oidc-url <url>]
292
306
  Create a Vite React starter app with a real browser Authorization Code +
293
307
  PKCE login flow against Blocks IAM (login page, /login/callback handler,
294
308
  route guards), plus Data schema listing, Release build lookup, environment
295
309
  config, and safe .gitignore defaults.
310
+ --blocks-api-url defaults to the OS API (os.seliseblocks.com) if omitted -
311
+ pass the runtime Data/IAM/Localization gateway URL explicitly (typically
312
+ https://api.seliseblocks.com) for the scaffolded app to work at runtime.
313
+ --oidc-url defaults to https://iam.seliseblocks.com.
296
314
  `);
297
315
  }
@@ -20,6 +20,7 @@ export declare function readWorkspaceConfig(): Promise<BlocksWorkspaceConfig>;
20
20
  export declare function writeWorkspaceConfig(config: BlocksWorkspaceConfig): Promise<void>;
21
21
  export declare function selectedProject(flags: Record<string, string | boolean>): Promise<string>;
22
22
  export declare function saveSelectedProject(tenantId: string): Promise<void>;
23
+ export declare function clearSelectedProject(): Promise<string | undefined>;
23
24
  export declare function pathsFromWorkspace(config: BlocksWorkspaceConfig): {
24
25
  dictionaries: string;
25
26
  releaseConfig: string;
@@ -47,6 +47,23 @@ export async function saveSelectedProject(tenantId) {
47
47
  });
48
48
  }
49
49
  }
50
+ export async function clearSelectedProject() {
51
+ const global = await readConfig();
52
+ const tenantId = global.selectedProject?.tenantId;
53
+ if (!tenantId)
54
+ return undefined;
55
+ const { selectedProject: _dropped, ...rest } = global;
56
+ await writeConfig(rest);
57
+ const local = await readWorkspaceConfig();
58
+ if (local.project?.tenantId) {
59
+ const { tenantId: _localTenantId, ...restProject } = local.project;
60
+ await writeWorkspaceConfig({
61
+ ...local,
62
+ project: Object.keys(restProject).length > 0 ? restProject : undefined
63
+ });
64
+ }
65
+ return tenantId;
66
+ }
50
67
  export function pathsFromWorkspace(config) {
51
68
  return {
52
69
  dictionaries: config.localization?.dictionaries ?? "blocks/localization",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seliseblocks/cli-os",
3
- "version": "0.1.3",
3
+ "version": "0.1.4",
4
4
  "description": "CLI for SELISE Blocks OS project setup and configuration.",
5
5
  "license": "MIT",
6
6
  "type": "module",