@standards/cli 1.0.0-alpha.407 → 1.0.0-alpha.409

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.
Files changed (2) hide show
  1. package/dist/bin.mjs +33 -4
  2. package/package.json +4 -4
package/dist/bin.mjs CHANGED
@@ -12,13 +12,13 @@ import { constants, createWriteStream } from "node:fs";
12
12
  import { access, chmod, mkdir, readFile, stat, unlink, writeFile } from "node:fs/promises";
13
13
  import { basename, dirname, isAbsolute, join } from "node:path";
14
14
  import { homedir, hostname } from "node:os";
15
+ import { REMOTE_DEVICE_PLATFORMS, buildOperationPath, recordsOperations } from "@standards/schema/api";
15
16
  import { createHash, randomUUID } from "node:crypto";
16
17
  import { WebSocket } from "ws";
17
18
  import { spawn } from "node:child_process";
18
19
  import { StringDecoder } from "node:string_decoder";
19
20
  import { Readable } from "node:stream";
20
21
  import { pipeline } from "node:stream/promises";
21
- import { buildOperationPath, recordsOperations } from "@standards/schema/api";
22
22
  import { stdin, stdout } from "node:process";
23
23
  import { createInterface } from "node:readline/promises";
24
24
  //#region src/output.ts
@@ -1200,6 +1200,9 @@ function requireNamedProfile(command) {
1200
1200
  tenantId: options.tenant
1201
1201
  };
1202
1202
  }
1203
+ function isRemoteDevicePlatform(value) {
1204
+ return REMOTE_DEVICE_PLATFORMS.some((platform) => platform === value);
1205
+ }
1203
1206
  function isRecord(value) {
1204
1207
  return value !== null && typeof value === "object" && !Array.isArray(value);
1205
1208
  }
@@ -1207,7 +1210,7 @@ function parseDeviceView(value) {
1207
1210
  if (!isRecord(value)) throw new DeviceCommandError("Invalid device response");
1208
1211
  const { id, name, platform, arch, hostname: deviceHostname } = value;
1209
1212
  const { status } = value;
1210
- if (typeof id !== "string" || typeof name !== "string" || platform !== "darwin" && platform !== "linux" || typeof arch !== "string" || typeof deviceHostname !== "string" || status !== "online" && status !== "offline" && status !== "revoked") throw new DeviceCommandError("Invalid device response");
1213
+ if (typeof id !== "string" || typeof name !== "string" || !isRemoteDevicePlatform(platform) || typeof arch !== "string" || typeof deviceHostname !== "string" || status !== "online" && status !== "offline" && status !== "revoked") throw new DeviceCommandError("Invalid device response");
1211
1214
  return {
1212
1215
  id,
1213
1216
  name,
@@ -1767,6 +1770,11 @@ function buildQueryBody(opts) {
1767
1770
  if (opts.count) body.countMode = parseCountFlag(opts.count);
1768
1771
  return body;
1769
1772
  }
1773
+ /** The new parent of a move: exactly one of `--parent <id>` or `--top-level` (null). */
1774
+ function parseMoveTarget(opts) {
1775
+ if (Boolean(opts.parent) === Boolean(opts.topLevel)) throw new ValidationError("Pass exactly one of --parent <id> or --top-level", []);
1776
+ return opts.parent ?? null;
1777
+ }
1770
1778
  const COUNT_OPTION_DESCRIPTION = "total count mode (none, estimated, exact); omit for no total in page.total";
1771
1779
  function registerRecordsCommand(program) {
1772
1780
  const records = program.command("records").description("Manage records (CRUD + search)");
@@ -1783,11 +1791,12 @@ function registerRecordsCommand(program) {
1783
1791
  id
1784
1792
  }), getFormat(cmd));
1785
1793
  });
1786
- records.command("create").description("Create a new record").argument("<object>", "object name").option("--data <json>", "record data as JSON string").action(async (objectName, opts, cmd) => {
1794
+ records.command("create").description("Create a new record").argument("<object>", "object name").option("--data <json>", "record data as JSON string").option("--parent <id>", "parent record ID (hierarchical objects only)").action(async (objectName, opts, cmd) => {
1787
1795
  const data = opts.data ? JSON.parse(opts.data) : {};
1788
1796
  formatOutput(await getAppClientFromCommand(cmd).records.create({
1789
1797
  objectName,
1790
- data
1798
+ data,
1799
+ ...opts.parent ? { options: { parentId: opts.parent } } : {}
1791
1800
  }), getFormat(cmd));
1792
1801
  });
1793
1802
  records.command("update").description("Update a record").argument("<object>", "object name").argument("<id>", "record ID").option("--data <json>", "fields to update as JSON string").action(async (objectName, id, opts, cmd) => {
@@ -1805,6 +1814,26 @@ function registerRecordsCommand(program) {
1805
1814
  });
1806
1815
  process.stdout.write(`Record ${id} deleted.\n`);
1807
1816
  });
1817
+ records.command("deletion-count").description("Count what deleting records would take: broken links and descendants").argument("<object>", "object name").argument("<ids...>", "record IDs").action(async (objectName, ids, _opts, cmd) => {
1818
+ formatOutput(await getAppClientFromCommand(cmd).records.deletionCount({
1819
+ objectName,
1820
+ ids
1821
+ }), getFormat(cmd));
1822
+ });
1823
+ records.command("move-impact").description("Show who would gain and lose access if a record moved").argument("<object>", "object name").argument("<id>", "record ID").option("--parent <id>", "new parent record ID").option("--top-level", "move to the top level").action(async (objectName, id, opts, cmd) => {
1824
+ formatOutput(await getAppClientFromCommand(cmd).records.moveImpact({
1825
+ objectName,
1826
+ recordId: id,
1827
+ parentId: parseMoveTarget(opts)
1828
+ }), getFormat(cmd));
1829
+ });
1830
+ records.command("move").description("Move a record and its descendants under a parent (preview with move-impact)").argument("<object>", "object name").argument("<id>", "record ID").option("--parent <id>", "new parent record ID").option("--top-level", "move to the top level").action(async (objectName, id, opts, cmd) => {
1831
+ formatOutput(await getAppClientFromCommand(cmd).records.move({
1832
+ objectName,
1833
+ recordId: id,
1834
+ parentId: parseMoveTarget(opts)
1835
+ }), getFormat(cmd));
1836
+ });
1808
1837
  records.command("search").description("Full-text search records").argument("<object>", "object name").requiredOption("--query <q>", "search query string").option("--limit <n>", "max records to return").option("--offset <n>", "number of records to skip").option("--sort <sort>", "sort rule as \"attribute:direction\"").option("--filter <json>", "filter state as JSON string").option("--fields <names>", "comma-separated reference attributes to hydrate (empty for none, omit for all)").option("--count <mode>", COUNT_OPTION_DESCRIPTION).action(async (objectName, opts, cmd) => {
1809
1838
  const body = {
1810
1839
  q: opts.query,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@standards/cli",
3
- "version": "1.0.0-alpha.407",
3
+ "version": "1.0.0-alpha.409",
4
4
  "description": "CLI tool to interact with Standards API",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,9 +27,9 @@
27
27
  "commander": "^13.1.0",
28
28
  "jiti": "2.7.0",
29
29
  "ws": "8.21.1",
30
- "@standards/client": "1.0.0-alpha.407",
31
- "@standards/constants": "1.0.0-alpha.407",
32
- "@standards/schema": "1.0.0-alpha.407"
30
+ "@standards/client": "1.0.0-alpha.409",
31
+ "@standards/constants": "1.0.0-alpha.409",
32
+ "@standards/schema": "1.0.0-alpha.409"
33
33
  },
34
34
  "devDependencies": {
35
35
  "@types/node": "^25.6.0",