@podge/cli 0.2.0-beta.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.
- package/README.md +97 -0
- package/dist/commands/apikeys.d.ts +2 -0
- package/dist/commands/apikeys.js +103 -0
- package/dist/commands/auth.d.ts +2 -0
- package/dist/commands/auth.js +110 -0
- package/dist/commands/collections.d.ts +2 -0
- package/dist/commands/collections.js +90 -0
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +38 -0
- package/dist/commands/debug.d.ts +2 -0
- package/dist/commands/debug.js +41 -0
- package/dist/commands/environments.d.ts +2 -0
- package/dist/commands/environments.js +71 -0
- package/dist/commands/items.d.ts +2 -0
- package/dist/commands/items.js +170 -0
- package/dist/commands/search.d.ts +2 -0
- package/dist/commands/search.js +60 -0
- package/dist/commands/workspaces.d.ts +2 -0
- package/dist/commands/workspaces.js +53 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +31 -0
- package/dist/lib/auth-server.d.ts +7 -0
- package/dist/lib/auth-server.js +95 -0
- package/dist/lib/client.d.ts +3 -0
- package/dist/lib/client.js +78 -0
- package/dist/lib/config.d.ts +18 -0
- package/dist/lib/config.js +95 -0
- package/dist/lib/open-browser.d.ts +1 -0
- package/dist/lib/open-browser.js +17 -0
- package/dist/lib/output.d.ts +4 -0
- package/dist/lib/output.js +29 -0
- package/package.json +36 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.registerItemCommands = void 0;
|
|
30
|
+
const fs = __importStar(require("fs"));
|
|
31
|
+
const client_1 = require("../lib/client");
|
|
32
|
+
const config_1 = require("../lib/config");
|
|
33
|
+
const output_1 = require("../lib/output");
|
|
34
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
35
|
+
function requireFullContext(opts) {
|
|
36
|
+
const cfg = (0, config_1.getConfig)();
|
|
37
|
+
const ws = opts.workspace || cfg.workspace;
|
|
38
|
+
const env = opts.environment || cfg.environment;
|
|
39
|
+
const col = opts.collection;
|
|
40
|
+
if (!ws || !env || !col) {
|
|
41
|
+
console.error(chalk_1.default.red("Workspace, environment, and collection required. Use flags or `podge config set`."));
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
return { ws, env, col };
|
|
45
|
+
}
|
|
46
|
+
function registerItemCommands(program) {
|
|
47
|
+
const items = program.command("items").description("Manage collection items");
|
|
48
|
+
items
|
|
49
|
+
.command("create")
|
|
50
|
+
.description("Create an item from JSON")
|
|
51
|
+
.requiredOption("-c, --collection <key>", "Collection key")
|
|
52
|
+
.option("-w, --workspace <key>", "Workspace key")
|
|
53
|
+
.option("-e, --environment <key>", "Environment key")
|
|
54
|
+
.option("-f, --file <path>", "JSON file path")
|
|
55
|
+
.option("-d, --data <json>", "Inline JSON data")
|
|
56
|
+
.option("--dry-run", "Validate without persisting")
|
|
57
|
+
.action(async (opts) => {
|
|
58
|
+
try {
|
|
59
|
+
const { ws, env, col } = requireFullContext(opts);
|
|
60
|
+
let body;
|
|
61
|
+
if (opts.file) {
|
|
62
|
+
body = JSON.parse(fs.readFileSync(opts.file, "utf-8"));
|
|
63
|
+
}
|
|
64
|
+
else if (opts.data) {
|
|
65
|
+
body = JSON.parse(opts.data);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.error(chalk_1.default.red("Provide --file or --data"));
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
const url = `/api/v1/workspace/${ws}/environment/${env}/collection/${col}/item${opts.dryRun ? "?dryRun=true" : ""}`;
|
|
72
|
+
const { data } = await (0, client_1.getClient)().post(url, body);
|
|
73
|
+
if (opts.dryRun) {
|
|
74
|
+
(0, output_1.printSuccess)("Dry run successful");
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
(0, output_1.printSuccess)("Item created");
|
|
78
|
+
}
|
|
79
|
+
(0, output_1.printJson)(data);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
(0, client_1.handleError)(err);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
items
|
|
86
|
+
.command("get <documentId>")
|
|
87
|
+
.description("Get a document by ID")
|
|
88
|
+
.requiredOption("-c, --collection <key>", "Collection key")
|
|
89
|
+
.option("-w, --workspace <key>", "Workspace key")
|
|
90
|
+
.option("-e, --environment <key>", "Environment key")
|
|
91
|
+
.action(async (documentId, opts) => {
|
|
92
|
+
try {
|
|
93
|
+
const { ws, env, col } = requireFullContext(opts);
|
|
94
|
+
const { data } = await (0, client_1.getClient)().get(`/api/v1/workspace/${ws}/environment/${env}/collection/${col}/document/${documentId}`);
|
|
95
|
+
(0, output_1.printJson)(data);
|
|
96
|
+
}
|
|
97
|
+
catch (err) {
|
|
98
|
+
(0, client_1.handleError)(err);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
items
|
|
102
|
+
.command("import")
|
|
103
|
+
.description("Create a bulk import job from a file")
|
|
104
|
+
.requiredOption("-c, --collection <key>", "Collection key")
|
|
105
|
+
.requiredOption("-f, --file <path>", "JSON file with items array")
|
|
106
|
+
.option("-w, --workspace <key>", "Workspace key")
|
|
107
|
+
.option("-e, --environment <key>", "Environment key")
|
|
108
|
+
.action(async (opts) => {
|
|
109
|
+
try {
|
|
110
|
+
const { ws, env, col } = requireFullContext(opts);
|
|
111
|
+
const body = JSON.parse(fs.readFileSync(opts.file, "utf-8"));
|
|
112
|
+
const items = Array.isArray(body) ? body : body.items || [body];
|
|
113
|
+
const url = `/api/v1/workspace/${ws}/environment/${env}/collection/${col}/items`;
|
|
114
|
+
const { data } = await (0, client_1.getClient)().post(url, { items });
|
|
115
|
+
(0, output_1.printSuccess)(`Batch import submitted (${items.length} items)`);
|
|
116
|
+
(0, output_1.printJson)(data);
|
|
117
|
+
}
|
|
118
|
+
catch (err) {
|
|
119
|
+
(0, client_1.handleError)(err);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
items
|
|
123
|
+
.command("delete <documentId>")
|
|
124
|
+
.description("Delete a document by ID")
|
|
125
|
+
.requiredOption("-c, --collection <slug>", "Collection slug")
|
|
126
|
+
.option("-w, --workspace <slug>", "Workspace slug")
|
|
127
|
+
.option("-e, --environment <slug>", "Environment slug")
|
|
128
|
+
.action(async (documentId, opts) => {
|
|
129
|
+
try {
|
|
130
|
+
const { ws, env, col } = requireFullContext(opts);
|
|
131
|
+
const { data } = await (0, client_1.getClient)().delete(`/api/v1/workspace/${ws}/environment/${env}/collection/${col}/document/${documentId}`);
|
|
132
|
+
(0, output_1.printSuccess)(`Document ${documentId} deleted`);
|
|
133
|
+
(0, output_1.printJson)(data);
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
(0, client_1.handleError)(err);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
items
|
|
140
|
+
.command("update <documentId>")
|
|
141
|
+
.description("Update a document by ID")
|
|
142
|
+
.requiredOption("-c, --collection <slug>", "Collection slug")
|
|
143
|
+
.option("-w, --workspace <slug>", "Workspace slug")
|
|
144
|
+
.option("-e, --environment <slug>", "Environment slug")
|
|
145
|
+
.option("-f, --file <path>", "JSON file path")
|
|
146
|
+
.option("-d, --data <json>", "Inline JSON data")
|
|
147
|
+
.action(async (documentId, opts) => {
|
|
148
|
+
try {
|
|
149
|
+
const { ws, env, col } = requireFullContext(opts);
|
|
150
|
+
let body;
|
|
151
|
+
if (opts.file) {
|
|
152
|
+
body = JSON.parse(fs.readFileSync(opts.file, "utf-8"));
|
|
153
|
+
}
|
|
154
|
+
else if (opts.data) {
|
|
155
|
+
body = JSON.parse(opts.data);
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
console.error(chalk_1.default.red("Provide --file or --data"));
|
|
159
|
+
process.exit(1);
|
|
160
|
+
}
|
|
161
|
+
const { data } = await (0, client_1.getClient)().patch(`/api/v1/workspace/${ws}/environment/${env}/collection/${col}/document/${documentId}`, body);
|
|
162
|
+
(0, output_1.printSuccess)(`Document ${documentId} update submitted`);
|
|
163
|
+
(0, output_1.printJson)(data);
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
(0, client_1.handleError)(err);
|
|
167
|
+
}
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
exports.registerItemCommands = registerItemCommands;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.registerSearchCommands = void 0;
|
|
7
|
+
const client_1 = require("../lib/client");
|
|
8
|
+
const config_1 = require("../lib/config");
|
|
9
|
+
const output_1 = require("../lib/output");
|
|
10
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
+
function registerSearchCommands(program) {
|
|
12
|
+
const search = program
|
|
13
|
+
.command("search <query>")
|
|
14
|
+
.description("Search a collection")
|
|
15
|
+
.requiredOption("-c, --collection <key>", "Collection key")
|
|
16
|
+
.option("-w, --workspace <key>", "Workspace key")
|
|
17
|
+
.option("-e, --environment <key>", "Environment key")
|
|
18
|
+
.option("--json", "Output as JSON")
|
|
19
|
+
.option("--no-cache", "Bypass query cache")
|
|
20
|
+
.option("--mode <mode>", "Search mode: keyword, semantic, or hybrid")
|
|
21
|
+
.action(async (query, opts) => {
|
|
22
|
+
try {
|
|
23
|
+
const cfg = (0, config_1.getConfig)();
|
|
24
|
+
const ws = opts.workspace || cfg.workspace;
|
|
25
|
+
const env = opts.environment || cfg.environment;
|
|
26
|
+
const col = opts.collection;
|
|
27
|
+
if (!ws || !env || !col) {
|
|
28
|
+
console.error(chalk_1.default.red("Workspace, environment, and collection required."));
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
const headers = {};
|
|
32
|
+
if (opts.noCache === false) {
|
|
33
|
+
headers["x-no-query-cache"] = "true";
|
|
34
|
+
}
|
|
35
|
+
const body = { search: query };
|
|
36
|
+
if (opts.mode) {
|
|
37
|
+
body.options = { mode: opts.mode };
|
|
38
|
+
}
|
|
39
|
+
const { data } = await (0, client_1.getClient)().post(`/api/v1/workspace/${ws}/environment/${env}/collection/${col}/search`, body, { headers });
|
|
40
|
+
if (opts.json) {
|
|
41
|
+
(0, output_1.printJson)(data);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const hits = data.hits || data.results || data;
|
|
45
|
+
if (Array.isArray(hits) && hits.length > 0) {
|
|
46
|
+
const keys = Object.keys(hits[0]).slice(0, 5);
|
|
47
|
+
const rows = hits.map((h) => keys.map((k) => String(h[k] ?? "")));
|
|
48
|
+
(0, output_1.printTable)(keys.map((k) => k.toUpperCase()), rows);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log("No results found.");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
(0, client_1.handleError)(err);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
exports.registerSearchCommands = registerSearchCommands;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.registerWorkspaceCommands = void 0;
|
|
4
|
+
const client_1 = require("../lib/client");
|
|
5
|
+
const output_1 = require("../lib/output");
|
|
6
|
+
function registerWorkspaceCommands(program) {
|
|
7
|
+
const ws = program
|
|
8
|
+
.command("workspaces")
|
|
9
|
+
.alias("ws")
|
|
10
|
+
.description("Manage workspaces");
|
|
11
|
+
ws.command("list")
|
|
12
|
+
.description("List all workspaces")
|
|
13
|
+
.option("--json", "Output as JSON")
|
|
14
|
+
.action(async (opts) => {
|
|
15
|
+
try {
|
|
16
|
+
const { data } = await (0, client_1.getClient)().get("/api/v1/workspaces");
|
|
17
|
+
if (opts.json) {
|
|
18
|
+
(0, output_1.printJson)(data);
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
const rows = (Array.isArray(data) ? data : [data]).map((w) => [
|
|
22
|
+
String(w.id),
|
|
23
|
+
w.key,
|
|
24
|
+
w.name,
|
|
25
|
+
]);
|
|
26
|
+
(0, output_1.printTable)(["ID", "KEY", "NAME"], rows);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
(0, client_1.handleError)(err);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
ws.command("get <key>")
|
|
34
|
+
.description("Get workspace details")
|
|
35
|
+
.option("--json", "Output as JSON")
|
|
36
|
+
.action(async (key, opts) => {
|
|
37
|
+
try {
|
|
38
|
+
const { data } = await (0, client_1.getClient)().get(`/api/v1/workspace/${key}`);
|
|
39
|
+
if (opts.json) {
|
|
40
|
+
(0, output_1.printJson)(data);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
console.log(`Name: ${data.name}`);
|
|
44
|
+
console.log(`Key: ${data.key}`);
|
|
45
|
+
console.log(`Description: ${data.description || "(none)"}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
(0, client_1.handleError)(err);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
exports.registerWorkspaceCommands = registerWorkspaceCommands;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
const commander_1 = require("commander");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const auth_1 = require("./commands/auth");
|
|
8
|
+
const config_1 = require("./commands/config");
|
|
9
|
+
const workspaces_1 = require("./commands/workspaces");
|
|
10
|
+
const environments_1 = require("./commands/environments");
|
|
11
|
+
const collections_1 = require("./commands/collections");
|
|
12
|
+
const items_1 = require("./commands/items");
|
|
13
|
+
const search_1 = require("./commands/search");
|
|
14
|
+
const apikeys_1 = require("./commands/apikeys");
|
|
15
|
+
const debug_1 = require("./commands/debug");
|
|
16
|
+
const pkg = JSON.parse((0, fs_1.readFileSync)((0, path_1.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
17
|
+
const program = new commander_1.Command();
|
|
18
|
+
program
|
|
19
|
+
.name("podge")
|
|
20
|
+
.description("Podge CLI — manage workspaces, collections, and search")
|
|
21
|
+
.version(pkg.version);
|
|
22
|
+
(0, auth_1.registerAuthCommands)(program);
|
|
23
|
+
(0, config_1.registerConfigCommands)(program);
|
|
24
|
+
(0, workspaces_1.registerWorkspaceCommands)(program);
|
|
25
|
+
(0, environments_1.registerEnvironmentCommands)(program);
|
|
26
|
+
(0, collections_1.registerCollectionCommands)(program);
|
|
27
|
+
(0, items_1.registerItemCommands)(program);
|
|
28
|
+
(0, search_1.registerSearchCommands)(program);
|
|
29
|
+
(0, apikeys_1.registerApiKeyCommands)(program);
|
|
30
|
+
(0, debug_1.registerDebugCommands)(program);
|
|
31
|
+
program.parse();
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.startAuthServer = void 0;
|
|
27
|
+
const http = __importStar(require("http"));
|
|
28
|
+
const url = __importStar(require("url"));
|
|
29
|
+
function startAuthServer(expectedState, timeoutMs = 120000) {
|
|
30
|
+
return new Promise((resolve, reject) => {
|
|
31
|
+
let settled = false;
|
|
32
|
+
const server = http.createServer();
|
|
33
|
+
const tokenPromise = new Promise((resToken, rejToken) => {
|
|
34
|
+
const timer = setTimeout(() => {
|
|
35
|
+
if (!settled) {
|
|
36
|
+
settled = true;
|
|
37
|
+
server.close();
|
|
38
|
+
rejToken(new Error("Authentication timed out after 120 seconds."));
|
|
39
|
+
}
|
|
40
|
+
}, timeoutMs);
|
|
41
|
+
server.on("request", (req, res) => {
|
|
42
|
+
const parsed = url.parse(req.url ?? "", true);
|
|
43
|
+
if (parsed.pathname !== "/callback") {
|
|
44
|
+
res.writeHead(404);
|
|
45
|
+
res.end("Not found");
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const { token, state, error } = parsed.query;
|
|
49
|
+
// Always respond with HTML
|
|
50
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
51
|
+
if (error) {
|
|
52
|
+
res.end("<html><body><h2>Authentication failed</h2><p>You can close this tab.</p></body></html>");
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
settled = true;
|
|
55
|
+
server.close();
|
|
56
|
+
rejToken(new Error(`Authentication failed: ${error}`));
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (state !== expectedState) {
|
|
60
|
+
res.end("<html><body><h2>Authentication failed</h2><p>Invalid state parameter.</p></body></html>");
|
|
61
|
+
clearTimeout(timer);
|
|
62
|
+
settled = true;
|
|
63
|
+
server.close();
|
|
64
|
+
rejToken(new Error("Invalid state parameter — possible CSRF attack."));
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (!token) {
|
|
68
|
+
res.end("<html><body><h2>Authentication failed</h2><p>No token received.</p></body></html>");
|
|
69
|
+
clearTimeout(timer);
|
|
70
|
+
settled = true;
|
|
71
|
+
server.close();
|
|
72
|
+
rejToken(new Error("No token received from the browser."));
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
res.end("<html><body><h2>Authentication successful!</h2><p>You can close this tab and return to the terminal.</p></body></html>");
|
|
76
|
+
clearTimeout(timer);
|
|
77
|
+
settled = true;
|
|
78
|
+
server.close();
|
|
79
|
+
resToken({ token });
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
server.listen(0, "127.0.0.1", () => {
|
|
83
|
+
const addr = server.address();
|
|
84
|
+
if (!addr || typeof addr === "string") {
|
|
85
|
+
reject(new Error("Failed to start auth server"));
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
resolve({ port: addr.port, tokenPromise });
|
|
89
|
+
});
|
|
90
|
+
server.on("error", (err) => {
|
|
91
|
+
reject(err);
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
exports.startAuthServer = startAuthServer;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
+
exports.handleError = exports.getClient = void 0;
|
|
30
|
+
const axios_1 = __importStar(require("axios"));
|
|
31
|
+
const config_1 = require("./config");
|
|
32
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
33
|
+
let clientInstance = null;
|
|
34
|
+
function getClient() {
|
|
35
|
+
if (clientInstance)
|
|
36
|
+
return clientInstance;
|
|
37
|
+
const creds = (0, config_1.getCredentials)();
|
|
38
|
+
if (!creds) {
|
|
39
|
+
console.error(chalk_1.default.red("Not authenticated. Run `podge auth login` first."));
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
clientInstance = axios_1.default.create({
|
|
43
|
+
baseURL: creds.apiUrl,
|
|
44
|
+
headers: {
|
|
45
|
+
Authorization: `Bearer ${creds.token}`,
|
|
46
|
+
"Content-Type": "application/json",
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
return clientInstance;
|
|
50
|
+
}
|
|
51
|
+
exports.getClient = getClient;
|
|
52
|
+
function handleError(err) {
|
|
53
|
+
if (err instanceof axios_1.AxiosError) {
|
|
54
|
+
const status = err.response?.status;
|
|
55
|
+
const data = err.response?.data;
|
|
56
|
+
const envelope = data?.error;
|
|
57
|
+
if (envelope) {
|
|
58
|
+
const code = envelope.code || "UNKNOWN";
|
|
59
|
+
const message = envelope.message || err.message;
|
|
60
|
+
console.error(chalk_1.default.red(`Error ${status} [${code}]: ${message}`));
|
|
61
|
+
if (envelope.details) {
|
|
62
|
+
console.error(chalk_1.default.dim(JSON.stringify(envelope.details, null, 2)));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
const message = data?.message || err.message;
|
|
67
|
+
console.error(chalk_1.default.red(`Error (${status}): ${message}`));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
else if (err instanceof Error) {
|
|
71
|
+
console.error(chalk_1.default.red(`Error: ${err.message}`));
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
console.error(chalk_1.default.red("An unexpected error occurred"));
|
|
75
|
+
}
|
|
76
|
+
process.exit(1);
|
|
77
|
+
}
|
|
78
|
+
exports.handleError = handleError;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface Credentials {
|
|
2
|
+
token: string;
|
|
3
|
+
apiUrl: string;
|
|
4
|
+
}
|
|
5
|
+
export interface Config {
|
|
6
|
+
workspace?: string;
|
|
7
|
+
environment?: string;
|
|
8
|
+
appUrl?: string;
|
|
9
|
+
apiUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function getCredentials(): Credentials | null;
|
|
12
|
+
export declare function saveCredentials(creds: Credentials): void;
|
|
13
|
+
export declare function clearCredentials(): void;
|
|
14
|
+
export declare function getConfig(): Config;
|
|
15
|
+
export declare function saveConfig(config: Config): void;
|
|
16
|
+
export declare function writeConfig(config: Config): void;
|
|
17
|
+
export declare function getApiUrl(): string;
|
|
18
|
+
export declare function getAppUrl(): string;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.getAppUrl = exports.getApiUrl = exports.writeConfig = exports.saveConfig = exports.getConfig = exports.clearCredentials = exports.saveCredentials = exports.getCredentials = void 0;
|
|
27
|
+
const fs = __importStar(require("fs"));
|
|
28
|
+
const path = __importStar(require("path"));
|
|
29
|
+
const os = __importStar(require("os"));
|
|
30
|
+
const CONFIG_DIR = path.join(os.homedir(), ".podge");
|
|
31
|
+
const CREDENTIALS_FILE = path.join(CONFIG_DIR, "credentials.json");
|
|
32
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
33
|
+
function ensureConfigDir() {
|
|
34
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
35
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
function getCredentials() {
|
|
39
|
+
if (!fs.existsSync(CREDENTIALS_FILE))
|
|
40
|
+
return null;
|
|
41
|
+
try {
|
|
42
|
+
return JSON.parse(fs.readFileSync(CREDENTIALS_FILE, "utf-8"));
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
return null;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.getCredentials = getCredentials;
|
|
49
|
+
function saveCredentials(creds) {
|
|
50
|
+
ensureConfigDir();
|
|
51
|
+
fs.writeFileSync(CREDENTIALS_FILE, JSON.stringify(creds, null, 2), {
|
|
52
|
+
mode: 0o600,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
exports.saveCredentials = saveCredentials;
|
|
56
|
+
function clearCredentials() {
|
|
57
|
+
if (fs.existsSync(CREDENTIALS_FILE)) {
|
|
58
|
+
fs.unlinkSync(CREDENTIALS_FILE);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.clearCredentials = clearCredentials;
|
|
62
|
+
function getConfig() {
|
|
63
|
+
if (!fs.existsSync(CONFIG_FILE))
|
|
64
|
+
return {};
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(fs.readFileSync(CONFIG_FILE, "utf-8"));
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return {};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.getConfig = getConfig;
|
|
73
|
+
function saveConfig(config) {
|
|
74
|
+
ensureConfigDir();
|
|
75
|
+
const existing = getConfig();
|
|
76
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify({ ...existing, ...config }, null, 2));
|
|
77
|
+
}
|
|
78
|
+
exports.saveConfig = saveConfig;
|
|
79
|
+
function writeConfig(config) {
|
|
80
|
+
ensureConfigDir();
|
|
81
|
+
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
82
|
+
}
|
|
83
|
+
exports.writeConfig = writeConfig;
|
|
84
|
+
const DEFAULT_API_URL = "https://dev.podge.dev/api";
|
|
85
|
+
const DEFAULT_APP_URL = "https://app.podge.io";
|
|
86
|
+
function getApiUrl() {
|
|
87
|
+
const config = getConfig();
|
|
88
|
+
return config.apiUrl ?? DEFAULT_API_URL;
|
|
89
|
+
}
|
|
90
|
+
exports.getApiUrl = getApiUrl;
|
|
91
|
+
function getAppUrl() {
|
|
92
|
+
const config = getConfig();
|
|
93
|
+
return config.appUrl ?? DEFAULT_APP_URL;
|
|
94
|
+
}
|
|
95
|
+
exports.getAppUrl = getAppUrl;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function openBrowser(url: string): void;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.openBrowser = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
function openBrowser(url) {
|
|
6
|
+
const cmd = process.platform === "darwin"
|
|
7
|
+
? "open"
|
|
8
|
+
: process.platform === "win32"
|
|
9
|
+
? "start"
|
|
10
|
+
: "xdg-open";
|
|
11
|
+
(0, child_process_1.exec)(`${cmd} "${url}"`, (err) => {
|
|
12
|
+
if (err) {
|
|
13
|
+
console.log(`Open this URL in your browser:\n ${url}`);
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
exports.openBrowser = openBrowser;
|