@thingd/cli 0.39.0 → 0.40.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.
@@ -0,0 +1,3 @@
1
+ import { type CliContext } from "../index.js";
2
+ export declare function runCloud(context: CliContext): Promise<void>;
3
+ //# sourceMappingURL=cloud.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud.d.ts","sourceRoot":"","sources":["../../src/commands/cloud.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAA2C,MAAM,aAAa,CAAC;AAiBvF,wBAAsB,QAAQ,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA4BjE"}
@@ -0,0 +1,162 @@
1
+ import pc from "picocolors";
2
+ import { requiredFlag, requiredToken, stringFlag } from "../index.js";
3
+ import { CloudApiError, createApiKey, createInstance, createProject, getMe, listInstances, listProjects, } from "../lib/cloud-api.js";
4
+ import { readCloudConfig, removeCloudConfig, writeCloudConfig, } from "../lib/cloud-config.js";
5
+ export async function runCloud(context) {
6
+ const sub = requiredToken(context.parsed, 1, "subcommand");
7
+ switch (sub) {
8
+ case "login":
9
+ await runLogin(context);
10
+ return;
11
+ case "logout":
12
+ await runLogout(context);
13
+ return;
14
+ case "status":
15
+ await runCloudStatus(context);
16
+ return;
17
+ case "project":
18
+ await runProject(context);
19
+ return;
20
+ case "instance":
21
+ await runInstance(context);
22
+ return;
23
+ case "api-key":
24
+ await runApiKey(context);
25
+ return;
26
+ default:
27
+ context.stderr.write(`Unknown cloud subcommand: ${sub}\n` +
28
+ "Available: login, logout, status, project, instance, api-key\n");
29
+ }
30
+ }
31
+ async function runLogin(context) {
32
+ const code = context.parsed.tokens[2] ?? requiredFlag(context.parsed, "code");
33
+ const token = context.parsed.tokens[3] ?? stringFlag(context.parsed, "token");
34
+ if (!token) {
35
+ context.stdout.write(`First, open this URL in your browser:\n\n` +
36
+ ` ${pc.cyan(`https://thingd.cloud/cli/auth?code=${code}`)}\n\n` +
37
+ `Then paste the token shown after logging in:\n\n` +
38
+ ` ${pc.dim("$ thingd cloud login --code <code> --token <token>")}\n`);
39
+ return;
40
+ }
41
+ // Verify token by calling /api/users/me
42
+ const config = { token };
43
+ try {
44
+ const { user } = await getMe(config);
45
+ writeCloudConfig({ ...config, email: user.email });
46
+ context.stdout.write(pc.green(`✓ Logged in as ${user.email}\n`));
47
+ }
48
+ catch (err) {
49
+ if (err instanceof CloudApiError && err.status === 401) {
50
+ context.stderr.write(pc.red("Invalid token. Please try again.\n"));
51
+ }
52
+ else {
53
+ context.stderr.write(pc.red(`Failed to verify token: ${err}\n`));
54
+ }
55
+ }
56
+ }
57
+ async function runLogout(context) {
58
+ removeCloudConfig();
59
+ context.stdout.write(pc.green("✓ Logged out\n"));
60
+ }
61
+ async function runCloudStatus(context) {
62
+ const config = readCloudConfig();
63
+ if (!config) {
64
+ context.stdout.write(`Not logged in. Run ${pc.cyan("thingd cloud login")}\n`);
65
+ return;
66
+ }
67
+ try {
68
+ const { user } = await getMe(config);
69
+ context.stdout.write(`Logged in as ${pc.green(user.email)} (${user.role})\n` +
70
+ `API: ${config.url ?? "https://api.thingd.cloud"}\n`);
71
+ }
72
+ catch {
73
+ context.stdout.write(`Token expired. Run ${pc.cyan("thingd cloud login")}\n`);
74
+ }
75
+ }
76
+ async function requireConfig(context) {
77
+ const config = readCloudConfig();
78
+ if (!config) {
79
+ context.stderr.write(`Not logged in. Run ${pc.cyan("thingd cloud login")} first.\n`);
80
+ throw new Error("not_logged_in");
81
+ }
82
+ return config;
83
+ }
84
+ async function runProject(context) {
85
+ const config = await requireConfig(context);
86
+ const action = requiredToken(context.parsed, 2, "action");
87
+ if (action === "list") {
88
+ const { projects } = await listProjects(config);
89
+ if (projects.length === 0) {
90
+ context.stdout.write("No projects found.\n");
91
+ return;
92
+ }
93
+ for (const p of projects) {
94
+ context.stdout.write(`${pc.cyan(p.slug)} ${p.name} ${pc.dim(p.createdAt.slice(0, 10))}\n`);
95
+ }
96
+ return;
97
+ }
98
+ if (action === "create") {
99
+ const name = requiredToken(context.parsed, 3, "name");
100
+ const { project } = await createProject(config, name);
101
+ context.stdout.write(pc.green(`✓ Created project: ${project.slug}\n`));
102
+ return;
103
+ }
104
+ context.stderr.write(`Unknown project action: ${action}. Available: list, create\n`);
105
+ }
106
+ async function runInstance(context) {
107
+ const config = await requireConfig(context);
108
+ const action = requiredToken(context.parsed, 2, "action");
109
+ if (action === "list") {
110
+ const projectSlug = requiredToken(context.parsed, 3, "project");
111
+ // Resolve project slug to ID by listing all projects
112
+ const { projects } = await listProjects(config);
113
+ const project = projects.find((p) => p.slug === projectSlug || p.id === projectSlug);
114
+ if (!project) {
115
+ context.stderr.write(pc.red(`Project not found: ${projectSlug}\n`));
116
+ return;
117
+ }
118
+ const { instances } = await listInstances(config, project.id);
119
+ if (instances.length === 0) {
120
+ context.stdout.write("No instances found.\n");
121
+ return;
122
+ }
123
+ for (const inst of instances) {
124
+ context.stdout.write(`${pc.cyan(inst.slug)} ${inst.name} ${pc.dim(inst.mcpUrl || "no URL")}\n`);
125
+ }
126
+ return;
127
+ }
128
+ if (action === "create") {
129
+ const projectSlug = requiredToken(context.parsed, 3, "project");
130
+ const name = requiredToken(context.parsed, 4, "name");
131
+ const { projects } = await listProjects(config);
132
+ const project = projects.find((p) => p.slug === projectSlug || p.id === projectSlug);
133
+ if (!project) {
134
+ context.stderr.write(pc.red(`Project not found: ${projectSlug}\n`));
135
+ return;
136
+ }
137
+ const { instance } = await createInstance(config, project.id, name);
138
+ context.stdout.write(pc.green(`✓ Created instance: ${instance.slug}\n`));
139
+ return;
140
+ }
141
+ context.stderr.write(`Unknown instance action: ${action}. Available: list, create\n`);
142
+ }
143
+ async function runApiKey(context) {
144
+ const config = await requireConfig(context);
145
+ const action = requiredToken(context.parsed, 2, "action");
146
+ if (action === "create") {
147
+ const projectSlug = requiredToken(context.parsed, 3, "project");
148
+ const name = context.parsed.tokens[4];
149
+ const { projects } = await listProjects(config);
150
+ const project = projects.find((p) => p.slug === projectSlug || p.id === projectSlug);
151
+ if (!project) {
152
+ context.stderr.write(pc.red(`Project not found: ${projectSlug}\n`));
153
+ return;
154
+ }
155
+ const { key } = await createApiKey(config, project.id, name);
156
+ context.stdout.write(pc.green(`✓ Created API key: ${key.prefix}\n`) +
157
+ `${pc.yellow("Save this token — it won't be shown again:")}\n` +
158
+ `${pc.bold(key.token ?? "(token not returned)")}\n`);
159
+ return;
160
+ }
161
+ context.stderr.write(`Unknown api-key action: ${action}. Available: create\n`);
162
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAQA,OAAO,EASL,MAAM,EACN,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAOrB,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAsCF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAuEF,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA6EjB;AA8zBD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAcf;AA4BD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,iBAAiB,CA2BxE;AAiDD,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAGlF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrF;AAyFD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEpF;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAQA,OAAO,EASL,MAAM,EACN,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAOrB,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAsCF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAuEF,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA6EjB;AAo0BD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAcf;AA4BD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,iBAAiB,CA2BxE;AAiDD,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAGlF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrF;AAyFD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEpF;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE"}
package/dist/index.js CHANGED
@@ -197,6 +197,11 @@ async function runCommand(context) {
197
197
  await runBench(context);
198
198
  return;
199
199
  }
200
+ if (command === "cloud") {
201
+ const { runCloud } = await import("./commands/cloud.js");
202
+ await runCloud(context);
203
+ return;
204
+ }
200
205
  if (command === "objects") {
201
206
  await runObjects(context);
202
207
  return;
@@ -0,0 +1,49 @@
1
+ import type { CloudConfig } from "./cloud-config.js";
2
+ export type CloudProject = {
3
+ id: string;
4
+ name: string;
5
+ slug: string;
6
+ createdAt: string;
7
+ };
8
+ export type CloudInstance = {
9
+ id: string;
10
+ name: string;
11
+ slug: string;
12
+ mcpUrl: string;
13
+ createdAt: string;
14
+ };
15
+ export type CloudApiKey = {
16
+ id: string;
17
+ name: string;
18
+ prefix: string;
19
+ token?: string;
20
+ createdAt: string;
21
+ };
22
+ export declare class CloudApiError extends Error {
23
+ status: number;
24
+ constructor(status: number, message: string);
25
+ }
26
+ export declare function getMe(config: CloudConfig): Promise<{
27
+ user: {
28
+ id: string;
29
+ email: string;
30
+ name: string;
31
+ role: string;
32
+ };
33
+ }>;
34
+ export declare function listProjects(config: CloudConfig): Promise<{
35
+ projects: CloudProject[];
36
+ }>;
37
+ export declare function createProject(config: CloudConfig, name: string): Promise<{
38
+ project: CloudProject;
39
+ }>;
40
+ export declare function listInstances(config: CloudConfig, projectId: string): Promise<{
41
+ instances: CloudInstance[];
42
+ }>;
43
+ export declare function createInstance(config: CloudConfig, projectId: string, name: string): Promise<{
44
+ instance: CloudInstance;
45
+ }>;
46
+ export declare function createApiKey(config: CloudConfig, projectId: string, name?: string): Promise<{
47
+ key: CloudApiKey;
48
+ }>;
49
+ //# sourceMappingURL=cloud-api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-api.d.ts","sourceRoot":"","sources":["../../src/lib/cloud-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AASrD,MAAM,MAAM,YAAY,GAAG;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,qBAAa,aAAc,SAAQ,KAAK;IACtC,MAAM,EAAE,MAAM,CAAC;gBAEH,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C;AA0BD,wBAAsB,KAAK,CACzB,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC;IAAE,IAAI,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAE9E;AAED,wBAAsB,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC,CAE7F;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,CAAA;CAAE,CAAC,CAEpC;AAED,wBAAsB,aAAa,CACjC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC;IAAE,SAAS,EAAE,aAAa,EAAE,CAAA;CAAE,CAAC,CAEzC;AAED,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,QAAQ,EAAE,aAAa,CAAA;CAAE,CAAC,CAKtC;AAED,wBAAsB,YAAY,CAChC,MAAM,EAAE,WAAW,EACnB,SAAS,EAAE,MAAM,EACjB,IAAI,CAAC,EAAE,MAAM,GACZ,OAAO,CAAC;IAAE,GAAG,EAAE,WAAW,CAAA;CAAE,CAAC,CAK/B"}
@@ -0,0 +1,53 @@
1
+ const DEFAULT_API_URL = "https://api.thingd.cloud";
2
+ export class CloudApiError extends Error {
3
+ status;
4
+ constructor(status, message) {
5
+ super(message);
6
+ this.status = status;
7
+ this.name = "CloudApiError";
8
+ }
9
+ }
10
+ async function request(config, path, opts = {}) {
11
+ const url = `${config.url ?? DEFAULT_API_URL}${path}`;
12
+ const headers = {
13
+ authorization: `Bearer ${config.token}`,
14
+ "content-type": "application/json",
15
+ };
16
+ const res = await fetch(url, {
17
+ method: opts.method ?? "GET",
18
+ headers,
19
+ body: opts.body ? JSON.stringify(opts.body) : undefined,
20
+ });
21
+ if (!res.ok) {
22
+ if (res.status === 401) {
23
+ throw new CloudApiError(401, "Token expired or invalid. Run `thingd cloud login` again.");
24
+ }
25
+ const body = await res.json().catch(() => ({ message: res.statusText }));
26
+ throw new CloudApiError(res.status, body.message ?? res.statusText);
27
+ }
28
+ return res.json();
29
+ }
30
+ export async function getMe(config) {
31
+ return request(config, "/api/users/me");
32
+ }
33
+ export async function listProjects(config) {
34
+ return request(config, "/api/projects");
35
+ }
36
+ export async function createProject(config, name) {
37
+ return request(config, "/api/projects", { method: "POST", body: { name } });
38
+ }
39
+ export async function listInstances(config, projectId) {
40
+ return request(config, `/api/projects/${projectId}/instances`);
41
+ }
42
+ export async function createInstance(config, projectId, name) {
43
+ return request(config, `/api/projects/${projectId}/instances`, {
44
+ method: "POST",
45
+ body: { name },
46
+ });
47
+ }
48
+ export async function createApiKey(config, projectId, name) {
49
+ return request(config, `/api/projects/${projectId}/api-keys`, {
50
+ method: "POST",
51
+ body: { name: name ?? "CLI key" },
52
+ });
53
+ }
@@ -0,0 +1,10 @@
1
+ export type CloudConfig = {
2
+ token: string;
3
+ email?: string;
4
+ url?: string;
5
+ };
6
+ export declare function cloudConfigPath(): string;
7
+ export declare function readCloudConfig(): CloudConfig | null;
8
+ export declare function writeCloudConfig(config: CloudConfig): void;
9
+ export declare function removeCloudConfig(): void;
10
+ //# sourceMappingURL=cloud-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-config.d.ts","sourceRoot":"","sources":["../../src/lib/cloud-config.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,wBAAgB,eAAe,IAAI,WAAW,GAAG,IAAI,CAUpD;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAG1D;AAED,wBAAgB,iBAAiB,IAAI,IAAI,CAMxC"}
@@ -0,0 +1,31 @@
1
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { defaultThingdDir, ensureThingdDir } from "../paths.js";
4
+ const CONFIG_FILE = "cloud-config.json";
5
+ export function cloudConfigPath() {
6
+ return join(defaultThingdDir(), CONFIG_FILE);
7
+ }
8
+ export function readCloudConfig() {
9
+ const path = cloudConfigPath();
10
+ if (!existsSync(path)) {
11
+ return null;
12
+ }
13
+ try {
14
+ return JSON.parse(readFileSync(path, "utf-8"));
15
+ }
16
+ catch {
17
+ return null;
18
+ }
19
+ }
20
+ export function writeCloudConfig(config) {
21
+ ensureThingdDir();
22
+ writeFileSync(cloudConfigPath(), JSON.stringify(config, null, 2), "utf-8");
23
+ }
24
+ export function removeCloudConfig() {
25
+ try {
26
+ unlinkSync(cloudConfigPath());
27
+ }
28
+ catch {
29
+ // File may not exist
30
+ }
31
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thingd/cli",
3
- "version": "0.39.0",
3
+ "version": "0.40.1",
4
4
  "description": "CLI, Interactive TUI Dashboard, and MCP server for thingd — a fast object-first data engine for applications and AI agents.",
5
5
  "type": "module",
6
6
  "author": "Sayan Mohsin",
@@ -44,7 +44,7 @@
44
44
  "cli-table3": "^0.6.5",
45
45
  "picocolors": "^1.1.1",
46
46
  "zod": "^4.4.3",
47
- "@thingd/sdk": "0.39.0"
47
+ "@thingd/sdk": "0.40.1"
48
48
  },
49
49
  "engines": {
50
50
  "node": ">=24.0.0"