@rooaak/cli 0.1.0-beta.1

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 (82) hide show
  1. package/README.md +121 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.d.ts.map +1 -0
  4. package/dist/cli.js +4 -0
  5. package/dist/index.d.ts +2 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +1 -0
  8. package/dist/src/commands/auth-login.d.ts +3 -0
  9. package/dist/src/commands/auth-login.d.ts.map +1 -0
  10. package/dist/src/commands/auth-login.js +97 -0
  11. package/dist/src/commands/config-profile-use.d.ts +3 -0
  12. package/dist/src/commands/config-profile-use.d.ts.map +1 -0
  13. package/dist/src/commands/config-profile-use.js +88 -0
  14. package/dist/src/commands/config-whoami.d.ts +3 -0
  15. package/dist/src/commands/config-whoami.d.ts.map +1 -0
  16. package/dist/src/commands/config-whoami.js +101 -0
  17. package/dist/src/commands/help.d.ts +3 -0
  18. package/dist/src/commands/help.d.ts.map +1 -0
  19. package/dist/src/commands/help.js +61 -0
  20. package/dist/src/commands/init/index.d.ts +3 -0
  21. package/dist/src/commands/init/index.d.ts.map +1 -0
  22. package/dist/src/commands/init/index.js +756 -0
  23. package/dist/src/commands/init/prompting.d.ts +16 -0
  24. package/dist/src/commands/init/prompting.d.ts.map +1 -0
  25. package/dist/src/commands/init/prompting.js +63 -0
  26. package/dist/src/commands/init/wait-for-message.d.ts +45 -0
  27. package/dist/src/commands/init/wait-for-message.d.ts.map +1 -0
  28. package/dist/src/commands/init/wait-for-message.js +27 -0
  29. package/dist/src/commands/version.d.ts +3 -0
  30. package/dist/src/commands/version.d.ts.map +1 -0
  31. package/dist/src/commands/version.js +14 -0
  32. package/dist/src/generated/handlers.d.ts +5 -0
  33. package/dist/src/generated/handlers.d.ts.map +1 -0
  34. package/dist/src/generated/handlers.js +17 -0
  35. package/dist/src/generated/manifest.d.ts +3 -0
  36. package/dist/src/generated/manifest.d.ts.map +1 -0
  37. package/dist/src/generated/manifest.js +56 -0
  38. package/dist/src/lib/argv.d.ts +16 -0
  39. package/dist/src/lib/argv.d.ts.map +1 -0
  40. package/dist/src/lib/argv.js +68 -0
  41. package/dist/src/lib/base-url.d.ts +7 -0
  42. package/dist/src/lib/base-url.d.ts.map +1 -0
  43. package/dist/src/lib/base-url.js +6 -0
  44. package/dist/src/lib/exit-codes.d.ts +11 -0
  45. package/dist/src/lib/exit-codes.d.ts.map +1 -0
  46. package/dist/src/lib/exit-codes.js +29 -0
  47. package/dist/src/lib/generated-command.d.ts +25 -0
  48. package/dist/src/lib/generated-command.d.ts.map +1 -0
  49. package/dist/src/lib/generated-command.js +357 -0
  50. package/dist/src/lib/normalize-error.d.ts +45 -0
  51. package/dist/src/lib/normalize-error.d.ts.map +1 -0
  52. package/dist/src/lib/normalize-error.js +128 -0
  53. package/dist/src/lib/options.d.ts +12 -0
  54. package/dist/src/lib/options.d.ts.map +1 -0
  55. package/dist/src/lib/options.js +49 -0
  56. package/dist/src/lib/package-version.d.ts +2 -0
  57. package/dist/src/lib/package-version.d.ts.map +1 -0
  58. package/dist/src/lib/package-version.js +22 -0
  59. package/dist/src/lib/paths.d.ts +2 -0
  60. package/dist/src/lib/paths.d.ts.map +1 -0
  61. package/dist/src/lib/paths.js +21 -0
  62. package/dist/src/lib/profile-name.d.ts +2 -0
  63. package/dist/src/lib/profile-name.d.ts.map +1 -0
  64. package/dist/src/lib/profile-name.js +4 -0
  65. package/dist/src/lib/profile-store.d.ts +31 -0
  66. package/dist/src/lib/profile-store.d.ts.map +1 -0
  67. package/dist/src/lib/profile-store.js +179 -0
  68. package/dist/src/lib/renderer.d.ts +10 -0
  69. package/dist/src/lib/renderer.d.ts.map +1 -0
  70. package/dist/src/lib/renderer.js +25 -0
  71. package/dist/src/lib/run.d.ts +12 -0
  72. package/dist/src/lib/run.d.ts.map +1 -0
  73. package/dist/src/lib/run.js +108 -0
  74. package/dist/src/lib/transport.d.ts +37 -0
  75. package/dist/src/lib/transport.d.ts.map +1 -0
  76. package/dist/src/lib/transport.js +65 -0
  77. package/dist/src/lib/types.d.ts +22 -0
  78. package/dist/src/lib/types.d.ts.map +1 -0
  79. package/dist/src/lib/types.js +1 -0
  80. package/package.json +46 -0
  81. package/rooaak.js +39 -0
  82. package/schemas/openapi.v1.json +6013 -0
@@ -0,0 +1,31 @@
1
+ export type ProfileName = string;
2
+ export type Profile = {
3
+ apiKey: string;
4
+ baseUrl?: string;
5
+ updatedAt: string;
6
+ };
7
+ export type ProfileConfig = {
8
+ version: 1;
9
+ currentProfile: ProfileName;
10
+ profiles: Record<ProfileName, Profile>;
11
+ };
12
+ export type ProfileStore = {
13
+ readConfig(): ReadConfigResult;
14
+ writeConfig(config: ProfileConfig): void;
15
+ getConfigPath(): string;
16
+ };
17
+ export type ReadConfigResult = {
18
+ kind: "ok";
19
+ config: ProfileConfig;
20
+ } | {
21
+ kind: "missing";
22
+ path: string;
23
+ } | {
24
+ kind: "corrupt";
25
+ path: string;
26
+ message: string;
27
+ };
28
+ export declare function createProfileStore(options?: {
29
+ configPath?: string;
30
+ }): ProfileStore;
31
+ //# sourceMappingURL=profile-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-store.d.ts","sourceRoot":"","sources":["../../../src/lib/profile-store.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC;AAEjC,MAAM,MAAM,OAAO,GAAG;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,CAAC,CAAC;IACX,cAAc,EAAE,WAAW,CAAC;IAC5B,QAAQ,EAAE,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;CACxC,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,IAAI,gBAAgB,CAAC;IAC/B,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAAC;IACzC,aAAa,IAAI,MAAM,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAiCvD,wBAAgB,kBAAkB,CAAC,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,YAAY,CAwIlF"}
@@ -0,0 +1,179 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import { randomUUID } from "node:crypto";
4
+ import { getDefaultConfigDir } from "./paths.js";
5
+ function isPlainObject(value) {
6
+ return typeof value === "object" && value !== null && !Array.isArray(value);
7
+ }
8
+ function normalizeConfig(raw) {
9
+ if (!isPlainObject(raw))
10
+ return null;
11
+ if (raw.version !== 1)
12
+ return null;
13
+ if (typeof raw.currentProfile !== "string" || raw.currentProfile.length === 0)
14
+ return null;
15
+ if (!isPlainObject(raw.profiles))
16
+ return null;
17
+ const profiles = {};
18
+ for (const [name, value] of Object.entries(raw.profiles)) {
19
+ if (!isPlainObject(value))
20
+ continue;
21
+ const apiKey = value.apiKey;
22
+ const baseUrl = value.baseUrl;
23
+ const updatedAt = value.updatedAt;
24
+ if (typeof apiKey !== "string" || apiKey.length === 0)
25
+ continue;
26
+ if (baseUrl !== undefined && typeof baseUrl !== "string")
27
+ continue;
28
+ if (typeof updatedAt !== "string" || updatedAt.length === 0)
29
+ continue;
30
+ profiles[name] = { apiKey, baseUrl, updatedAt };
31
+ }
32
+ if (!profiles[raw.currentProfile])
33
+ return null;
34
+ return {
35
+ version: 1,
36
+ currentProfile: raw.currentProfile,
37
+ profiles,
38
+ };
39
+ }
40
+ export function createProfileStore(options) {
41
+ const configPath = options?.configPath ?? path.join(getDefaultConfigDir("rooaak"), "config.json");
42
+ function readConfig() {
43
+ try {
44
+ if (!fs.existsSync(configPath))
45
+ return { kind: "missing", path: configPath };
46
+ const raw = fs.readFileSync(configPath, "utf8");
47
+ const parsed = JSON.parse(raw);
48
+ const normalized = normalizeConfig(parsed);
49
+ if (!normalized) {
50
+ return {
51
+ kind: "corrupt",
52
+ path: configPath,
53
+ message: `Config file is unreadable or corrupt: ${configPath}`,
54
+ };
55
+ }
56
+ return { kind: "ok", config: normalized };
57
+ }
58
+ catch {
59
+ return {
60
+ kind: "corrupt",
61
+ path: configPath,
62
+ message: `Config file is unreadable or corrupt: ${configPath}`,
63
+ };
64
+ }
65
+ }
66
+ function writeConfig(config) {
67
+ const dir = path.dirname(configPath);
68
+ fs.mkdirSync(dir, { recursive: true });
69
+ const json = JSON.stringify(config, null, 2) + "\n";
70
+ const tmpPath = path.join(dir, `.${path.basename(configPath)}.tmp-${process.pid}-${randomUUID()}`);
71
+ // Atomic write: write temp file (0600), fsync, rename into place, then best-effort fsync dir.
72
+ let fd = null;
73
+ let backupPath = null;
74
+ try {
75
+ fd = fs.openSync(tmpPath, "w", 0o600);
76
+ fs.writeFileSync(fd, json, "utf8");
77
+ try {
78
+ fs.fsyncSync(fd);
79
+ }
80
+ catch {
81
+ // Ignore (filesystem dependent).
82
+ }
83
+ }
84
+ finally {
85
+ if (fd !== null) {
86
+ try {
87
+ fs.closeSync(fd);
88
+ }
89
+ catch {
90
+ // Ignore.
91
+ }
92
+ }
93
+ }
94
+ try {
95
+ if (process.platform !== "win32") {
96
+ fs.renameSync(tmpPath, configPath);
97
+ }
98
+ else {
99
+ // Windows: rename() won't reliably overwrite an existing file.
100
+ if (fs.existsSync(configPath)) {
101
+ backupPath = `${configPath}.bak-${process.pid}-${randomUUID()}`;
102
+ fs.renameSync(configPath, backupPath);
103
+ }
104
+ fs.renameSync(tmpPath, configPath);
105
+ if (backupPath) {
106
+ try {
107
+ fs.unlinkSync(backupPath);
108
+ }
109
+ catch {
110
+ // Ignore; worst case we leave a backup file.
111
+ }
112
+ backupPath = null;
113
+ }
114
+ }
115
+ }
116
+ catch (err) {
117
+ // Best-effort rollback + cleanup.
118
+ try {
119
+ if (process.platform === "win32" && backupPath) {
120
+ if (!fs.existsSync(configPath) && fs.existsSync(backupPath)) {
121
+ fs.renameSync(backupPath, configPath);
122
+ }
123
+ }
124
+ }
125
+ catch {
126
+ // Ignore.
127
+ }
128
+ try {
129
+ if (fs.existsSync(tmpPath))
130
+ fs.unlinkSync(tmpPath);
131
+ }
132
+ catch {
133
+ // Ignore.
134
+ }
135
+ throw err;
136
+ }
137
+ finally {
138
+ // Always cleanup any leftover temp file.
139
+ try {
140
+ if (fs.existsSync(tmpPath))
141
+ fs.unlinkSync(tmpPath);
142
+ }
143
+ catch {
144
+ // Ignore.
145
+ }
146
+ // If we still have a backup path and the new file exists, best-effort remove the backup.
147
+ if (backupPath && fs.existsSync(configPath)) {
148
+ try {
149
+ fs.unlinkSync(backupPath);
150
+ }
151
+ catch {
152
+ // Ignore.
153
+ }
154
+ }
155
+ }
156
+ try {
157
+ fs.chmodSync(configPath, 0o600);
158
+ }
159
+ catch {
160
+ // Ignore (platform/filesystem dependent).
161
+ }
162
+ try {
163
+ const dirFd = fs.openSync(dir, "r");
164
+ try {
165
+ fs.fsyncSync(dirFd);
166
+ }
167
+ finally {
168
+ fs.closeSync(dirFd);
169
+ }
170
+ }
171
+ catch {
172
+ // Ignore (platform/filesystem dependent).
173
+ }
174
+ }
175
+ function getConfigPath() {
176
+ return configPath;
177
+ }
178
+ return { readConfig, writeConfig, getConfigPath };
179
+ }
@@ -0,0 +1,10 @@
1
+ import type { CommandContext } from "./types.js";
2
+ export type Renderer = {
3
+ json(value: unknown): void;
4
+ text(line: string): void;
5
+ error(line: string): void;
6
+ warn(line: string): void;
7
+ debug(line: string): void;
8
+ };
9
+ export declare function createRenderer(ctx: CommandContext): Renderer;
10
+ //# sourceMappingURL=renderer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"renderer.d.ts","sourceRoot":"","sources":["../../../src/lib/renderer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD,MAAM,MAAM,QAAQ,GAAG;IACrB,IAAI,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B,CAAC;AAEF,wBAAgB,cAAc,CAAC,GAAG,EAAE,cAAc,GAAG,QAAQ,CA0B5D"}
@@ -0,0 +1,25 @@
1
+ export function createRenderer(ctx) {
2
+ function json(value) {
3
+ ctx.stdout.write(`${JSON.stringify(value)}\n`);
4
+ }
5
+ function text(line) {
6
+ ctx.stdout.write(`${line}\n`);
7
+ }
8
+ function error(line) {
9
+ // `--quiet` must not suppress real errors.
10
+ ctx.stderr.write(`${line}\n`);
11
+ }
12
+ function warn(line) {
13
+ if (ctx.flags.quiet)
14
+ return;
15
+ ctx.stderr.write(`${line}\n`);
16
+ }
17
+ function debug(line) {
18
+ if (ctx.flags.quiet)
19
+ return;
20
+ if (!ctx.flags.verbose)
21
+ return;
22
+ ctx.stderr.write(`${line}\n`);
23
+ }
24
+ return { json, text, error, warn, debug };
25
+ }
@@ -0,0 +1,12 @@
1
+ export type RunCliOptions = {
2
+ cwd?: string;
3
+ env?: NodeJS.ProcessEnv;
4
+ stdin?: NodeJS.ReadableStream;
5
+ stdinIsTTY?: boolean;
6
+ stdout?: NodeJS.WritableStream;
7
+ stderr?: NodeJS.WritableStream;
8
+ profileConfigPath?: string;
9
+ fetchFn?: typeof fetch;
10
+ };
11
+ export declare function runCli(argv: string[], options?: RunCliOptions): Promise<number>;
12
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/lib/run.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB,CAAC;AAEF,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CA4GrF"}
@@ -0,0 +1,108 @@
1
+ import { helpCommand } from "../commands/help.js";
2
+ import { versionCommand } from "../commands/version.js";
3
+ import { authLoginCommand } from "../commands/auth-login.js";
4
+ import { configWhoamiCommand } from "../commands/config-whoami.js";
5
+ import { configProfileUseCommand } from "../commands/config-profile-use.js";
6
+ import { initCommand } from "../commands/init/index.js";
7
+ import { parseArgv } from "./argv.js";
8
+ import { ExitCode } from "./exit-codes.js";
9
+ import { createRenderer } from "./renderer.js";
10
+ import { normalizeLocalUsageError, toJsonErrorEnvelope } from "./normalize-error.js";
11
+ import { renderGeneratedCommandHelp } from "./generated-command.js";
12
+ import { dispatchGeneratedCommand, findGeneratedCommand } from "../generated/handlers.js";
13
+ export async function runCli(argv, options) {
14
+ const parsed = parseArgv(argv);
15
+ const flags = {
16
+ help: parsed.flags.help,
17
+ version: parsed.flags.version,
18
+ json: parsed.flags.json,
19
+ nonInteractive: parsed.flags.nonInteractive,
20
+ quiet: parsed.flags.quiet,
21
+ verbose: parsed.flags.verbose,
22
+ baseUrl: parsed.flags.baseUrl,
23
+ };
24
+ const stdin = options?.stdin ?? process.stdin;
25
+ const stdinIsTTY = options?.stdinIsTTY ??
26
+ ((options?.stdin?.isTTY ?? process.stdin?.isTTY) === true);
27
+ const ctx = {
28
+ argv,
29
+ cwd: options?.cwd ?? process.cwd(),
30
+ env: options?.env ?? process.env,
31
+ stdin,
32
+ stdinIsTTY,
33
+ stdout: options?.stdout ?? process.stdout,
34
+ stderr: options?.stderr ?? process.stderr,
35
+ flags,
36
+ profileConfigPath: options?.profileConfigPath,
37
+ fetchFn: options?.fetchFn,
38
+ };
39
+ const r = createRenderer(ctx);
40
+ if (parsed.missingValueOption) {
41
+ const err = normalizeLocalUsageError(`Missing value for: ${parsed.missingValueOption}`);
42
+ if (ctx.flags.json)
43
+ r.json(toJsonErrorEnvelope(err));
44
+ else {
45
+ r.error(err.message);
46
+ ctx.stderr.write("\n");
47
+ helpCommand(ctx);
48
+ }
49
+ return ExitCode.Usage;
50
+ }
51
+ if (parsed.unknownOption) {
52
+ const err = normalizeLocalUsageError(`Unknown option: ${parsed.unknownOption}`);
53
+ if (ctx.flags.json)
54
+ r.json(toJsonErrorEnvelope(err));
55
+ else {
56
+ r.error(err.message);
57
+ ctx.stderr.write("\n");
58
+ helpCommand(ctx);
59
+ }
60
+ return ExitCode.Usage;
61
+ }
62
+ if (parsed.flags.version || parsed.positionals[0] === "version") {
63
+ return versionCommand(ctx);
64
+ }
65
+ if (parsed.positionals.length === 0)
66
+ return helpCommand(ctx);
67
+ const group = parsed.positionals[0];
68
+ const sub = parsed.positionals[1];
69
+ if (group === "help") {
70
+ return helpCommand(ctx);
71
+ }
72
+ if (group === "init" && parsed.flags.help) {
73
+ return initCommand(ctx, ["--help"]);
74
+ }
75
+ if (parsed.flags.help) {
76
+ // If a user asks for help on a specific generated command, show derived flags.
77
+ const spec = findGeneratedCommand(group, sub);
78
+ if (spec)
79
+ return renderGeneratedCommandHelp(ctx, spec);
80
+ return helpCommand(ctx);
81
+ }
82
+ if (group === "init") {
83
+ return initCommand(ctx, parsed.positionals.slice(1));
84
+ }
85
+ if (group === "auth" && sub === "login") {
86
+ return authLoginCommand(ctx, parsed.positionals.slice(2));
87
+ }
88
+ if (group === "config" && sub === "whoami") {
89
+ return configWhoamiCommand(ctx, parsed.positionals.slice(2));
90
+ }
91
+ if (group === "config" && sub === "profile" && parsed.positionals[2] === "use") {
92
+ return configProfileUseCommand(ctx, parsed.positionals.slice(3));
93
+ }
94
+ if (typeof sub === "string") {
95
+ const spec = findGeneratedCommand(group, sub);
96
+ if (spec)
97
+ return dispatchGeneratedCommand(ctx, group, sub, parsed.positionals.slice(2));
98
+ }
99
+ const err = normalizeLocalUsageError(`Unknown command: ${parsed.positionals.join(" ")}`);
100
+ if (ctx.flags.json)
101
+ r.json(toJsonErrorEnvelope(err));
102
+ else {
103
+ r.error(err.message);
104
+ ctx.stderr.write("\n");
105
+ helpCommand(ctx);
106
+ }
107
+ return ExitCode.Usage;
108
+ }
@@ -0,0 +1,37 @@
1
+ import { normalizeHttpError } from "./normalize-error.js";
2
+ export type TransportOk<T> = {
3
+ ok: true;
4
+ status: number;
5
+ requestId?: string;
6
+ data: T;
7
+ };
8
+ export type TransportErr = {
9
+ ok: false;
10
+ status?: number;
11
+ requestId?: string;
12
+ error: ReturnType<typeof normalizeHttpError> | {
13
+ code: string;
14
+ message: string;
15
+ details: Record<string, unknown>;
16
+ meta: {
17
+ status?: number;
18
+ requestId?: string;
19
+ };
20
+ };
21
+ };
22
+ export type TransportResult<T> = TransportOk<T> | TransportErr;
23
+ export type Transport = {
24
+ getJson<T>(path: string): Promise<TransportResult<T>>;
25
+ requestJson<T>(input: {
26
+ method: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
27
+ path: string;
28
+ headers?: Record<string, string>;
29
+ body?: unknown;
30
+ }): Promise<TransportResult<T>>;
31
+ };
32
+ export declare function createTransport(options: {
33
+ baseUrl: string;
34
+ apiKey: string;
35
+ fetchFn?: typeof fetch;
36
+ }): Transport;
37
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../../src/lib/transport.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAEnF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,CAAC,CAAC;CACT,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,GAAG;QAC7C,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjC,IAAI,EAAE;YAAE,MAAM,CAAC,EAAE,MAAM,CAAC;YAAC,SAAS,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;KAC/C,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,eAAe,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,CAAC,GAAG,YAAY,CAAC;AAE/D,MAAM,MAAM,SAAS,GAAG;IACtB,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACtD,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE;QACpB,MAAM,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,QAAQ,CAAC;QACpD,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,OAAO,CAAC;KAChB,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;CACjC,CAAC;AAgBF,wBAAgB,eAAe,CAAC,OAAO,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB,GAAG,SAAS,CA4DZ"}
@@ -0,0 +1,65 @@
1
+ import { getRequestIdFromHeaders, normalizeHttpError } from "./normalize-error.js";
2
+ function isPlainObject(value) {
3
+ return typeof value === "object" && value !== null && !Array.isArray(value);
4
+ }
5
+ async function safeReadJson(response) {
6
+ try {
7
+ const text = await response.text();
8
+ if (!text)
9
+ return null;
10
+ return JSON.parse(text);
11
+ }
12
+ catch {
13
+ return null;
14
+ }
15
+ }
16
+ export function createTransport(options) {
17
+ const fetchFn = options.fetchFn ?? fetch;
18
+ const baseUrl = options.baseUrl;
19
+ const apiKey = options.apiKey;
20
+ async function requestJson(input) {
21
+ const p = input.path;
22
+ const url = `${baseUrl}${p.startsWith("/") ? "" : "/"}${p}`;
23
+ try {
24
+ const headers = {
25
+ Authorization: `Bearer ${apiKey}`,
26
+ Accept: "application/json",
27
+ ...(input.headers ?? {}),
28
+ };
29
+ const init = {
30
+ method: input.method,
31
+ headers,
32
+ };
33
+ if (input.body !== undefined) {
34
+ if (!headers["Content-Type"])
35
+ headers["Content-Type"] = "application/json";
36
+ init.body = JSON.stringify(input.body);
37
+ }
38
+ const res = await fetchFn(url, init);
39
+ const requestId = getRequestIdFromHeaders(res.headers);
40
+ if (res.ok) {
41
+ const body = (await safeReadJson(res));
42
+ return { ok: true, status: res.status, requestId, data: body };
43
+ }
44
+ const body = await safeReadJson(res);
45
+ const normalized = normalizeHttpError({ status: res.status, requestId, body });
46
+ return { ok: false, status: res.status, requestId, error: normalized };
47
+ }
48
+ catch (err) {
49
+ const message = err instanceof Error ? err.message : String(err);
50
+ return {
51
+ ok: false,
52
+ error: {
53
+ code: "network.error",
54
+ message: "Network error",
55
+ details: isPlainObject(err) ? { message } : { message },
56
+ meta: {},
57
+ },
58
+ };
59
+ }
60
+ }
61
+ async function getJson(path) {
62
+ return requestJson({ method: "GET", path });
63
+ }
64
+ return { getJson, requestJson };
65
+ }
@@ -0,0 +1,22 @@
1
+ export type CommandContext = {
2
+ argv: string[];
3
+ cwd: string;
4
+ env: NodeJS.ProcessEnv;
5
+ stdin: NodeJS.ReadableStream;
6
+ stdinIsTTY: boolean;
7
+ stdout: NodeJS.WritableStream;
8
+ stderr: NodeJS.WritableStream;
9
+ flags: GlobalFlags;
10
+ profileConfigPath?: string;
11
+ fetchFn?: typeof fetch;
12
+ };
13
+ export type GlobalFlags = {
14
+ help: boolean;
15
+ version: boolean;
16
+ json: boolean;
17
+ nonInteractive: boolean;
18
+ quiet: boolean;
19
+ verbose: boolean;
20
+ baseUrl?: string;
21
+ };
22
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,cAAc,CAAC;IAC7B,UAAU,EAAE,OAAO,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,MAAM,EAAE,MAAM,CAAC,cAAc,CAAC;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@rooaak/cli",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Rooaak CLI (companion to the Rooaak SDK)",
5
+ "private": false,
6
+ "type": "module",
7
+ "bin": {
8
+ "rooaak": "./rooaak.js"
9
+ },
10
+ "main": "dist/index.js",
11
+ "types": "dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "import": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ },
17
+ "./schemas/openapi.v1.json": "./schemas/openapi.v1.json"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "rooaak.js",
22
+ "README.md",
23
+ "schemas"
24
+ ],
25
+ "scripts": {
26
+ "build": "npm run build:clean && tsc -p tsconfig.json",
27
+ "build:clean": "node -e \"const fs=require('fs');for (const p of ['dist','tsconfig.tsbuildinfo']) fs.rmSync(p,{recursive:true,force:true});\"",
28
+ "prepublishOnly": "npm run build"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/adilastudio/rooaak-core.git",
33
+ "directory": "packages/rooaak-cli"
34
+ },
35
+ "license": "MIT",
36
+ "engines": {
37
+ "node": ">=18"
38
+ },
39
+ "publishConfig": {
40
+ "access": "public"
41
+ },
42
+ "devDependencies": {
43
+ "@types/node": "^20",
44
+ "typescript": "^5"
45
+ }
46
+ }
package/rooaak.js ADDED
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ import fs from "node:fs";
3
+ import path from "node:path";
4
+ import { fileURLToPath, pathToFileURL } from "node:url";
5
+
6
+ const __filename = fileURLToPath(import.meta.url);
7
+ const __dirname = path.dirname(__filename);
8
+ const distCliPath = path.join(__dirname, "dist", "cli.js");
9
+
10
+ async function run() {
11
+ if (!fs.existsSync(distCliPath)) {
12
+ process.stderr.write(
13
+ "rooaak CLI is not built. Run `npm run build` in packages/rooaak-cli.\n"
14
+ );
15
+ process.exitCode = 1;
16
+ return;
17
+ }
18
+
19
+ const mod = await import(pathToFileURL(distCliPath).href);
20
+ const main = mod?.main;
21
+ if (typeof main !== "function") {
22
+ process.stderr.write("Invalid CLI build: missing export `main`.\n");
23
+ process.exitCode = 1;
24
+ return;
25
+ }
26
+
27
+ const code = await main(process.argv.slice(2));
28
+ process.exitCode = typeof code === "number" ? code : 0;
29
+ }
30
+
31
+ run().catch((err) => {
32
+ const msg =
33
+ err && typeof err === "object" && "stack" in err && typeof err.stack === "string"
34
+ ? err.stack
35
+ : String(err);
36
+ process.stderr.write(`${msg}\n`);
37
+ process.exitCode = 1;
38
+ });
39
+