@enter-pro/enter-cli 0.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.
Files changed (51) hide show
  1. package/README.md +0 -0
  2. package/dist/auth.d.ts +12 -0
  3. package/dist/auth.js +39 -0
  4. package/dist/auth.js.map +1 -0
  5. package/dist/client.d.ts +11 -0
  6. package/dist/client.js +140 -0
  7. package/dist/client.js.map +1 -0
  8. package/dist/commands/config.d.ts +2 -0
  9. package/dist/commands/config.js +37 -0
  10. package/dist/commands/config.js.map +1 -0
  11. package/dist/commands/domain.d.ts +2 -0
  12. package/dist/commands/domain.js +65 -0
  13. package/dist/commands/domain.js.map +1 -0
  14. package/dist/commands/login.d.ts +2 -0
  15. package/dist/commands/login.js +143 -0
  16. package/dist/commands/login.js.map +1 -0
  17. package/dist/commands/logout.d.ts +2 -0
  18. package/dist/commands/logout.js +9 -0
  19. package/dist/commands/logout.js.map +1 -0
  20. package/dist/commands/models.d.ts +2 -0
  21. package/dist/commands/models.js +27 -0
  22. package/dist/commands/project.d.ts +2 -0
  23. package/dist/commands/project.js +452 -0
  24. package/dist/commands/project.js.map +1 -0
  25. package/dist/commands/skill.d.ts +2 -0
  26. package/dist/commands/skill.js +118 -0
  27. package/dist/commands/thread.d.ts +2 -0
  28. package/dist/commands/thread.js +578 -0
  29. package/dist/commands/thread.js.map +1 -0
  30. package/dist/commands/whoami.d.ts +2 -0
  31. package/dist/commands/whoami.js +28 -0
  32. package/dist/commands/whoami.js.map +1 -0
  33. package/dist/commands/workspace.d.ts +2 -0
  34. package/dist/commands/workspace.js +178 -0
  35. package/dist/commands/workspace.js.map +1 -0
  36. package/dist/config.d.ts +13 -0
  37. package/dist/config.js +68 -0
  38. package/dist/config.js.map +1 -0
  39. package/dist/errors.d.ts +13 -0
  40. package/dist/errors.js +33 -0
  41. package/dist/index.d.ts +2 -0
  42. package/dist/index.js +45 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/lifecycle.d.ts +9 -0
  45. package/dist/lifecycle.js +47 -0
  46. package/dist/output.d.ts +26 -0
  47. package/dist/output.js +89 -0
  48. package/dist/output.js.map +1 -0
  49. package/dist/poll.d.ts +9 -0
  50. package/dist/poll.js +24 -0
  51. package/package.json +41 -0
@@ -0,0 +1,178 @@
1
+ import { Command } from "commander";
2
+ import * as client from "../client.js";
3
+ import { print, printMessage, printTable, pickList } from "../output.js";
4
+ export const workspaceCmd = new Command("workspace")
5
+ .alias("ws")
6
+ .description("Manage workspaces");
7
+ function getFormat(cmd) {
8
+ return cmd.optsWithGlobals().output || "json";
9
+ }
10
+ workspaceCmd
11
+ .command("list")
12
+ .description("List workspaces")
13
+ .action(async (_opts, cmd) => {
14
+ const data = await client.get("/v1/workspaces");
15
+ const resp = data;
16
+ const items = pickList(resp.workspaces || [], [
17
+ "id", "name", "plan_type", "role", "member_count", "subscription_status",
18
+ ]);
19
+ const format = getFormat(cmd);
20
+ if (format !== "table") {
21
+ print(format, items);
22
+ return;
23
+ }
24
+ const rows = items.map((ws) => [
25
+ String(ws.id),
26
+ String(ws.name ?? ""),
27
+ String(ws.plan_type ?? ""),
28
+ String(ws.role ?? ""),
29
+ String(ws.member_count ?? ""),
30
+ String(ws.subscription_status ?? ""),
31
+ ]);
32
+ printTable(["ID", "Name", "Plan", "Role", "Members", "Status"], rows);
33
+ });
34
+ workspaceCmd
35
+ .command("get <workspace_id>")
36
+ .description("Get workspace details")
37
+ .action(async (id, _opts, cmd) => {
38
+ const data = await client.get(`/v1/workspaces/${id}`);
39
+ const format = getFormat(cmd);
40
+ if (format !== "table") {
41
+ print(format, data);
42
+ return;
43
+ }
44
+ const ws = data;
45
+ printTable(["ID", "Public ID", "Name", "Plan", "Role", "Members", "Subscription"], [
46
+ [
47
+ String(ws.id),
48
+ ws.public_id,
49
+ ws.name,
50
+ ws.plan_type,
51
+ ws.role,
52
+ String(ws.member_count),
53
+ ws.subscription_status,
54
+ ],
55
+ ]);
56
+ });
57
+ workspaceCmd
58
+ .command("create <name>")
59
+ .description("Create a new workspace")
60
+ .option("--image <url>", "Workspace image URL")
61
+ .action(async (name, opts, cmd) => {
62
+ const body = { name };
63
+ if (opts.image)
64
+ body.image = opts.image;
65
+ const data = await client.post("/v1/workspaces", body);
66
+ print(getFormat(cmd), data);
67
+ });
68
+ workspaceCmd
69
+ .command("delete <workspace_id>")
70
+ .description("Delete a workspace")
71
+ .action(async (id) => {
72
+ await client.del(`/v1/workspaces/${id}`);
73
+ printMessage("Workspace deleted successfully.");
74
+ });
75
+ // Members subcommand group
76
+ const membersCmd = new Command("members").description("Manage workspace members");
77
+ membersCmd
78
+ .command("list <workspace_id>")
79
+ .description("List workspace members")
80
+ .action(async (id, _opts, cmd) => {
81
+ const data = await client.get(`/v1/workspaces/${id}/members`);
82
+ const resp = data;
83
+ const items = pickList(resp.members || [], [
84
+ "user_id", "email", "name", "role", "created_at",
85
+ ]);
86
+ const format = getFormat(cmd);
87
+ if (format !== "table") {
88
+ print(format, items);
89
+ return;
90
+ }
91
+ const rows = items.map((m) => [
92
+ String(m.user_id ?? ""),
93
+ String(m.email ?? ""),
94
+ String(m.name ?? ""),
95
+ String(m.role ?? ""),
96
+ String(m.created_at ?? ""),
97
+ ]);
98
+ printTable(["User ID", "Email", "Name", "Role", "Joined"], rows);
99
+ });
100
+ membersCmd
101
+ .command("add <workspace_id>")
102
+ .description("Add a member to workspace")
103
+ .requiredOption("--email <email>", "Member email")
104
+ .option("--role <role>", "Member role: owner, admin, editor, viewer")
105
+ .action(async (id, opts, cmd) => {
106
+ const validRoles = ["owner", "admin", "editor", "viewer"];
107
+ if (opts.role && !validRoles.includes(opts.role)) {
108
+ throw new Error(`Invalid role "${opts.role}". Valid values: ${validRoles.join(", ")}`);
109
+ }
110
+ const body = { email: opts.email };
111
+ if (opts.role)
112
+ body.role = opts.role;
113
+ const data = await client.post(`/v1/workspaces/${id}/members`, body);
114
+ print(getFormat(cmd), data);
115
+ });
116
+ membersCmd
117
+ .command("remove <workspace_id>")
118
+ .description("Remove a member from workspace")
119
+ .option("--email <email>", "Member email")
120
+ .option("--user-id <id>", "Member user ID")
121
+ .action(async (id, opts) => {
122
+ if (!opts.email && !opts.userId) {
123
+ throw new Error("--email or --user-id is required");
124
+ }
125
+ const body = {};
126
+ if (opts.email)
127
+ body.email = opts.email;
128
+ if (opts.userId)
129
+ body.user_id = Number(opts.userId);
130
+ await client.post(`/v1/workspaces/${id}/members/remove`, body);
131
+ printMessage("Member removed successfully.");
132
+ });
133
+ membersCmd
134
+ .command("update-role <workspace_id>")
135
+ .description("Update a member's role in the workspace")
136
+ .option("--email <email>", "Member email")
137
+ .option("--user-id <id>", "Member user ID")
138
+ .requiredOption("--role <role>", "New role: owner, admin, editor, viewer")
139
+ .action(async (id, opts, cmd) => {
140
+ const validRoles = ["owner", "admin", "editor", "viewer"];
141
+ if (!validRoles.includes(opts.role)) {
142
+ throw new Error(`Invalid role "${opts.role}". Valid values: ${validRoles.join(", ")}`);
143
+ }
144
+ if (!opts.email && !opts.userId) {
145
+ throw new Error("--email or --user-id is required");
146
+ }
147
+ const body = { role: opts.role };
148
+ if (opts.email)
149
+ body.email = opts.email;
150
+ if (opts.userId)
151
+ body.user_id = Number(opts.userId);
152
+ const data = await client.post(`/v1/workspaces/${id}/members/update-role`, body);
153
+ print(getFormat(cmd), data);
154
+ });
155
+ membersCmd
156
+ .command("leave <workspace_id>")
157
+ .description("Leave a workspace")
158
+ .action(async (id) => {
159
+ await client.post(`/v1/workspaces/${id}/leave`);
160
+ printMessage("Left workspace successfully.");
161
+ });
162
+ workspaceCmd.addCommand(membersCmd);
163
+ // Credits subcommand group
164
+ const creditsCmd = new Command("credits").description("Manage workspace credits");
165
+ creditsCmd
166
+ .command("dashboard <workspace_id>")
167
+ .description("Show credits dashboard")
168
+ .option("--page <number>", "Page number", "1")
169
+ .option("--page-size <number>", "Page size", "8")
170
+ .action(async (id, opts, cmd) => {
171
+ const params = {
172
+ page: opts.page,
173
+ page_size: opts.pageSize,
174
+ };
175
+ const data = await client.get(`/v1/workspaces/${id}/credits/dashboard`, params);
176
+ print(getFormat(cmd), data);
177
+ });
178
+ workspaceCmd.addCommand(creditsCmd);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"workspace.js","sourceRoot":"","sources":["../../src/commands/workspace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export interface Config {
2
+ api_url: string;
3
+ base_path: string;
4
+ output: string;
5
+ default_workspace: string;
6
+ }
7
+ export declare function configDir(): string;
8
+ export declare function loadConfig(): Config;
9
+ export declare function setConfig(key: string, value: string): void;
10
+ export declare function getConfig(key: string): string;
11
+ export declare function allSettings(): Record<string, string>;
12
+ export declare function baseURL(): string;
13
+ export declare function workURL(): string;
package/dist/config.js ADDED
@@ -0,0 +1,68 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
2
+ import { join } from "path";
3
+ import { homedir } from "os";
4
+ import yaml from "js-yaml";
5
+ const CONFIG_DIR = join(homedir(), ".enter");
6
+ const CONFIG_FILE = join(CONFIG_DIR, "config.yaml");
7
+ const defaults = {
8
+ api_url: "https://api.enter.pro",
9
+ base_path: "/code/api",
10
+ output: "json",
11
+ default_workspace: "",
12
+ };
13
+ function ensureConfigDir() {
14
+ if (!existsSync(CONFIG_DIR)) {
15
+ mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
16
+ }
17
+ }
18
+ function loadFromFile() {
19
+ try {
20
+ const content = readFileSync(CONFIG_FILE, "utf-8");
21
+ return yaml.load(content) || {};
22
+ }
23
+ catch {
24
+ return {};
25
+ }
26
+ }
27
+ function getEnvOverrides() {
28
+ const overrides = {};
29
+ if (process.env.ENTER_API_URL)
30
+ overrides.api_url = process.env.ENTER_API_URL;
31
+ if (process.env.ENTER_BASE_PATH)
32
+ overrides.base_path = process.env.ENTER_BASE_PATH;
33
+ if (process.env.ENTER_OUTPUT)
34
+ overrides.output = process.env.ENTER_OUTPUT;
35
+ if (process.env.ENTER_DEFAULT_WORKSPACE)
36
+ overrides.default_workspace = process.env.ENTER_DEFAULT_WORKSPACE;
37
+ return overrides;
38
+ }
39
+ export function configDir() {
40
+ return CONFIG_DIR;
41
+ }
42
+ export function loadConfig() {
43
+ const fileConfig = loadFromFile();
44
+ const envOverrides = getEnvOverrides();
45
+ return { ...defaults, ...fileConfig, ...envOverrides };
46
+ }
47
+ export function setConfig(key, value) {
48
+ ensureConfigDir();
49
+ const current = loadFromFile();
50
+ current[key] = value;
51
+ writeFileSync(CONFIG_FILE, yaml.dump(current), "utf-8");
52
+ }
53
+ export function getConfig(key) {
54
+ const cfg = loadConfig();
55
+ return cfg[key] || "";
56
+ }
57
+ export function allSettings() {
58
+ const cfg = loadConfig();
59
+ return cfg;
60
+ }
61
+ export function baseURL() {
62
+ const cfg = loadConfig();
63
+ return `${cfg.api_url}${cfg.base_path}`;
64
+ }
65
+ export function workURL() {
66
+ const cfg = loadConfig();
67
+ return `${cfg.api_url}/work/api`;
68
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export declare class APIError extends Error {
2
+ code: number | string;
3
+ detail: string;
4
+ hint?: string;
5
+ retryable: boolean;
6
+ constructor(code: number | string, message: string, detail: string);
7
+ }
8
+ interface ErrorHint {
9
+ hint: string;
10
+ retryable: boolean;
11
+ }
12
+ export declare const ERROR_HINTS: Record<number | string, ErrorHint>;
13
+ export {};
package/dist/errors.js ADDED
@@ -0,0 +1,33 @@
1
+ export class APIError extends Error {
2
+ code;
3
+ detail;
4
+ hint;
5
+ retryable;
6
+ constructor(code, message, detail) {
7
+ const hint = ERROR_HINTS[code]?.hint;
8
+ super(hint ? `[${code}] ${message}\nHint: ${hint}` : `[${code}] ${message}${detail ? ": " + detail : ""}`);
9
+ this.name = "APIError";
10
+ this.code = code;
11
+ this.detail = detail;
12
+ this.hint = hint;
13
+ this.retryable = ERROR_HINTS[code]?.retryable ?? false;
14
+ }
15
+ }
16
+ export const ERROR_HINTS = {
17
+ 1001: {
18
+ hint: "Invalid chat task input. If your message contains quotes, newlines, or special characters, the shell may have mangled it. Write the message to a file and use --file <path> instead of -m.",
19
+ retryable: false,
20
+ },
21
+ 1003: {
22
+ hint: "无权访问此资源。请检查工作区成员权限。",
23
+ retryable: false,
24
+ },
25
+ 1004: {
26
+ hint: "操作重复。该请求已被执行过。",
27
+ retryable: false,
28
+ },
29
+ VIP_REQUIRED: {
30
+ hint: "This feature requires a paid plan. As a workaround, use `enter-cli thread diff <project_id> <turn>` to export per-turn changes, or `enter-cli proj source-code <project_id>` to view the source code inline.",
31
+ retryable: false,
32
+ },
33
+ };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { createRequire } from "module";
4
+ import { setVerbose } from "./client.js";
5
+ import { loadConfig } from "./config.js";
6
+ const require = createRequire(import.meta.url);
7
+ const { version } = require("../package.json");
8
+ import { loginCmd } from "./commands/login.js";
9
+ import { logoutCmd } from "./commands/logout.js";
10
+ import { whoamiCmd } from "./commands/whoami.js";
11
+ import { configCmd } from "./commands/config.js";
12
+ import { workspaceCmd } from "./commands/workspace.js";
13
+ import { projectCmd } from "./commands/project.js";
14
+ import { threadCmd } from "./commands/thread.js";
15
+ import { domainCmd } from "./commands/domain.js";
16
+ import { modelsCmd } from "./commands/models.js";
17
+ const program = new Command();
18
+ program
19
+ .name("enter-cli")
20
+ .description("Enter CLI - manage Enter platform resources")
21
+ .version(version)
22
+ .option("-o, --output <format>", "Output format: table, json, yaml")
23
+ .option("-v, --verbose", "Verbose output (show HTTP requests)")
24
+ .hook("preAction", () => {
25
+ const opts = program.opts();
26
+ if (opts.verbose)
27
+ setVerbose(true);
28
+ if (!opts.output) {
29
+ const cfg = loadConfig();
30
+ program.setOptionValue("output", cfg.output);
31
+ }
32
+ });
33
+ program.addCommand(loginCmd);
34
+ program.addCommand(logoutCmd);
35
+ program.addCommand(whoamiCmd);
36
+ program.addCommand(configCmd);
37
+ program.addCommand(workspaceCmd);
38
+ program.addCommand(projectCmd);
39
+ program.addCommand(threadCmd);
40
+ program.addCommand(domainCmd);
41
+ program.addCommand(modelsCmd);
42
+ program.parseAsync().catch((err) => {
43
+ console.error(`Error: ${err.message}`);
44
+ process.exit(1);
45
+ });
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEjD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,OAAO,CAAC,OAAO,CAAC;KAChB,MAAM,CAAC,uBAAuB,EAAE,kCAAkC,CAAC;KACnE,MAAM,CAAC,eAAe,EAAE,qCAAqC,CAAC;KAC9D,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;IACtB,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC5B,IAAI,IAAI,CAAC,OAAO;QAAE,UAAU,CAAC,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,GAAG,GAAG,UAAU,EAAE,CAAC;QACzB,OAAO,CAAC,cAAc,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;AAC7B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAC9B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAC9B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAC9B,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;AACjC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC;AAC/B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAC9B,OAAO,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;AAE9B,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;IACxC,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type LifecycleStatus = "initializing" | "building" | "ready" | "publishing" | "active" | "failed" | "archived" | "unknown";
2
+ /**
3
+ * Resolves a unified lifecycle status from project detail fields.
4
+ *
5
+ * Backend project statuses: initializing | active | archived | error | deleted
6
+ * Build status: { success: bool, error_detail? }
7
+ * Publish status: { unpublished_changes, last_published_commit_id }
8
+ */
9
+ export declare function resolveLifecycleStatus(project: Record<string, unknown>): LifecycleStatus;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Resolves a unified lifecycle status from project detail fields.
3
+ *
4
+ * Backend project statuses: initializing | active | archived | error | deleted
5
+ * Build status: { success: bool, error_detail? }
6
+ * Publish status: { unpublished_changes, last_published_commit_id }
7
+ */
8
+ export function resolveLifecycleStatus(project) {
9
+ const status = String(project.status ?? "");
10
+ const buildStatus = project.build_status;
11
+ const publishStatus = project.publish_status;
12
+ if (status === "initializing")
13
+ return "initializing";
14
+ if (status === "archived")
15
+ return "archived";
16
+ if (status === "error")
17
+ return "failed";
18
+ // active — determine more granular state
19
+ if (status === "active") {
20
+ // If build failed
21
+ if (buildStatus && buildStatus.success === false)
22
+ return "failed";
23
+ // If has unpublished changes being pushed (heuristic: publish_url exists but unpublished_changes)
24
+ if (publishStatus) {
25
+ const hasPublishUrl = Boolean(project.publish_url);
26
+ const hasUnpublished = Boolean(publishStatus.unpublished_changes);
27
+ if (hasPublishUrl && hasUnpublished) {
28
+ // project has been published before and has new changes
29
+ return "active";
30
+ }
31
+ if (hasPublishUrl && !hasUnpublished) {
32
+ return "active";
33
+ }
34
+ }
35
+ // Has been built (build_status.success = true)
36
+ if (buildStatus && buildStatus.success === true) {
37
+ if (project.publish_url)
38
+ return "active";
39
+ return "ready";
40
+ }
41
+ // No build status yet
42
+ if (!buildStatus)
43
+ return "building";
44
+ return "ready";
45
+ }
46
+ return "unknown";
47
+ }
@@ -0,0 +1,26 @@
1
+ export declare function printJSON(data: unknown): void;
2
+ export declare function printYAML(data: unknown): void;
3
+ export declare function printTable(headers: string[], rows: string[][]): void;
4
+ export declare function print(format: string, data: unknown): void;
5
+ export declare function printMessage(msg: string): void;
6
+ export declare function printResult(format: string, structured: unknown, message: string): void;
7
+ import type { Command } from "commander";
8
+ export declare function getFormat(cmd: Command): string;
9
+ export declare function printError(err: Error | string): void;
10
+ export declare function pick<T extends Record<string, unknown>>(obj: T, keys: string[]): Record<string, unknown>;
11
+ export declare function pickList(items: Record<string, unknown>[], keys: string[]): Record<string, unknown>[];
12
+ export interface ListEnvelope {
13
+ items: unknown[];
14
+ total?: number;
15
+ page?: number;
16
+ page_size?: number;
17
+ }
18
+ export interface TableConfig {
19
+ headers: string[];
20
+ rowMapper: (item: Record<string, unknown>) => string[];
21
+ }
22
+ export declare function printList(format: string, data: ListEnvelope, tableConfig?: TableConfig): void;
23
+ export declare function printSingle(format: string, data: unknown, tableConfig?: {
24
+ headers: string[];
25
+ rowMapper: (item: Record<string, unknown>) => string[];
26
+ }): void;
package/dist/output.js ADDED
@@ -0,0 +1,89 @@
1
+ import yaml from "js-yaml";
2
+ export function printJSON(data) {
3
+ console.log(JSON.stringify(data, null, 2));
4
+ }
5
+ export function printYAML(data) {
6
+ process.stdout.write(yaml.dump(data));
7
+ }
8
+ export function printTable(headers, rows) {
9
+ if (rows.length === 0) {
10
+ console.log("No results found.");
11
+ return;
12
+ }
13
+ const widths = headers.map((h) => h.length);
14
+ for (const row of rows) {
15
+ for (let i = 0; i < row.length && i < widths.length; i++) {
16
+ const cell = row[i] ?? "";
17
+ row[i] = cell;
18
+ if (cell.length > widths[i])
19
+ widths[i] = cell.length;
20
+ }
21
+ }
22
+ const headerLine = headers
23
+ .map((h, i) => h.toUpperCase().padEnd(widths[i]))
24
+ .join(" ");
25
+ console.log(headerLine);
26
+ for (const row of rows) {
27
+ const line = row
28
+ .map((cell, i) => (i < widths.length ? cell.padEnd(widths[i]) : cell))
29
+ .join(" ");
30
+ console.log(line);
31
+ }
32
+ }
33
+ export function print(format, data) {
34
+ switch (format) {
35
+ case "json":
36
+ printJSON(data);
37
+ break;
38
+ case "yaml":
39
+ printYAML(data);
40
+ break;
41
+ default:
42
+ printJSON(data);
43
+ break;
44
+ }
45
+ }
46
+ export function printMessage(msg) {
47
+ console.log(msg);
48
+ }
49
+ // For commands that have both a structured payload (consumed by agents/scripts)
50
+ // and a human-readable confirmation. Picks based on output format.
51
+ export function printResult(format, structured, message) {
52
+ if (format === "json" || format === "yaml") {
53
+ print(format, structured);
54
+ }
55
+ else {
56
+ printMessage(message);
57
+ }
58
+ }
59
+ export function getFormat(cmd) {
60
+ return cmd.optsWithGlobals().output || "json";
61
+ }
62
+ export function printError(err) {
63
+ console.error(`Error: ${typeof err === "string" ? err : err.message}`);
64
+ }
65
+ export function pick(obj, keys) {
66
+ const result = {};
67
+ for (const key of keys) {
68
+ result[key] = obj[key];
69
+ }
70
+ return result;
71
+ }
72
+ export function pickList(items, keys) {
73
+ return items.map((item) => pick(item, keys));
74
+ }
75
+ export function printList(format, data, tableConfig) {
76
+ if (format === "table" && tableConfig) {
77
+ const rows = data.items.map(tableConfig.rowMapper);
78
+ printTable(tableConfig.headers, rows);
79
+ return;
80
+ }
81
+ print(format, data);
82
+ }
83
+ export function printSingle(format, data, tableConfig) {
84
+ if (format === "table" && tableConfig) {
85
+ printTable(tableConfig.headers, [tableConfig.rowMapper(data)]);
86
+ return;
87
+ }
88
+ print(format, data);
89
+ }
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"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"}
package/dist/poll.d.ts ADDED
@@ -0,0 +1,9 @@
1
+ export declare class TimeoutError extends Error {
2
+ constructor(elapsedMs: number);
3
+ }
4
+ export interface PollOptions {
5
+ intervalMs?: number;
6
+ timeoutMs?: number;
7
+ onTick?: (elapsed: number, data: unknown) => void;
8
+ }
9
+ export declare function pollUntil<T>(fetcher: () => Promise<T>, predicate: (data: T) => boolean, options?: PollOptions): Promise<T>;
package/dist/poll.js ADDED
@@ -0,0 +1,24 @@
1
+ export class TimeoutError extends Error {
2
+ constructor(elapsedMs) {
3
+ super(`Timed out after ${Math.round(elapsedMs / 1000)}s`);
4
+ this.name = "TimeoutError";
5
+ }
6
+ }
7
+ export async function pollUntil(fetcher, predicate, options) {
8
+ const intervalMs = options?.intervalMs ?? 2000;
9
+ const timeoutMs = options?.timeoutMs ?? 300000;
10
+ const onTick = options?.onTick;
11
+ const start = Date.now();
12
+ while (true) {
13
+ const data = await fetcher();
14
+ const elapsed = Date.now() - start;
15
+ if (predicate(data)) {
16
+ return data;
17
+ }
18
+ if (elapsed >= timeoutMs) {
19
+ throw new TimeoutError(elapsed);
20
+ }
21
+ onTick?.(elapsed, data);
22
+ await new Promise((resolve) => setTimeout(resolve, intervalMs));
23
+ }
24
+ }
package/package.json ADDED
@@ -0,0 +1,41 @@
1
+ {
2
+ "name": "@enter-pro/enter-cli",
3
+ "version": "0.4.0",
4
+ "description": "Enter CLI - manage Enter platform resources from the command line",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "enter-cli": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "tsc --watch",
13
+ "start": "node dist/index.js",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "publishConfig": {
20
+ "access": "public"
21
+ },
22
+ "keywords": [
23
+ "enter",
24
+ "cli",
25
+ "cloud",
26
+ "ai"
27
+ ],
28
+ "license": "MIT",
29
+ "engines": {
30
+ "node": ">=18.0.0"
31
+ },
32
+ "dependencies": {
33
+ "commander": "^13.0.0",
34
+ "js-yaml": "^4.1.0"
35
+ },
36
+ "devDependencies": {
37
+ "@types/js-yaml": "^4.0.9",
38
+ "@types/node": "^22.0.0",
39
+ "typescript": "^5.7.0"
40
+ }
41
+ }