@01.software/cli 0.1.1 → 0.2.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/dist/index.js +216 -35
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -9,25 +9,17 @@ import { CollectionClient, OrderApi, CartApi, ProductApi, parseApiKey } from "@0
|
|
|
9
9
|
import pc from "picocolors";
|
|
10
10
|
|
|
11
11
|
// src/lib/credentials.ts
|
|
12
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from "fs";
|
|
12
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, appendFileSync } from "fs";
|
|
13
13
|
import { join } from "path";
|
|
14
14
|
import { homedir } from "os";
|
|
15
15
|
var DIR_NAME = ".01software";
|
|
16
16
|
var FILE_NAME = "credentials.json";
|
|
17
|
+
var TENANTS_FILE = "tenants.json";
|
|
17
18
|
function getCredentialsPath() {
|
|
18
19
|
return join(homedir(), DIR_NAME, FILE_NAME);
|
|
19
20
|
}
|
|
20
21
|
function loadCredentials() {
|
|
21
|
-
|
|
22
|
-
if (!existsSync(filePath)) return null;
|
|
23
|
-
try {
|
|
24
|
-
const raw = readFileSync(filePath, "utf-8");
|
|
25
|
-
const data = JSON.parse(raw);
|
|
26
|
-
if (!data.clientKey || !data.secretKey) return null;
|
|
27
|
-
return data;
|
|
28
|
-
} catch {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
22
|
+
return loadCredentialsFrom(getCredentialsPath());
|
|
31
23
|
}
|
|
32
24
|
function saveCredentials(creds) {
|
|
33
25
|
const dir = join(homedir(), DIR_NAME);
|
|
@@ -44,6 +36,70 @@ function deleteCredentials() {
|
|
|
44
36
|
unlinkSync(filePath);
|
|
45
37
|
return true;
|
|
46
38
|
}
|
|
39
|
+
function getLocalCredentialsPath() {
|
|
40
|
+
return join(process.cwd(), DIR_NAME, FILE_NAME);
|
|
41
|
+
}
|
|
42
|
+
function loadLocalCredentials() {
|
|
43
|
+
return loadCredentialsFrom(getLocalCredentialsPath());
|
|
44
|
+
}
|
|
45
|
+
function saveLocalCredentials(creds) {
|
|
46
|
+
const dir = join(process.cwd(), DIR_NAME);
|
|
47
|
+
if (!existsSync(dir)) {
|
|
48
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
49
|
+
}
|
|
50
|
+
const filePath = getLocalCredentialsPath();
|
|
51
|
+
const data = { ...creds, storedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
52
|
+
writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: "utf-8", mode: 384 });
|
|
53
|
+
ensureGitignore();
|
|
54
|
+
}
|
|
55
|
+
function saveTenantList(tenants) {
|
|
56
|
+
const dir = join(homedir(), DIR_NAME);
|
|
57
|
+
if (!existsSync(dir)) {
|
|
58
|
+
mkdirSync(dir, { recursive: true, mode: 448 });
|
|
59
|
+
}
|
|
60
|
+
const filePath = join(homedir(), DIR_NAME, TENANTS_FILE);
|
|
61
|
+
writeFileSync(filePath, JSON.stringify(tenants, null, 2), { encoding: "utf-8", mode: 384 });
|
|
62
|
+
}
|
|
63
|
+
function loadTenantList() {
|
|
64
|
+
const filePath = join(homedir(), DIR_NAME, TENANTS_FILE);
|
|
65
|
+
if (!existsSync(filePath)) return null;
|
|
66
|
+
try {
|
|
67
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
68
|
+
const data = JSON.parse(raw);
|
|
69
|
+
if (!Array.isArray(data)) return null;
|
|
70
|
+
const valid = data.filter(
|
|
71
|
+
(t) => typeof t?.id === "string" && typeof t?.name === "string"
|
|
72
|
+
);
|
|
73
|
+
return valid.length > 0 ? valid : null;
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function loadCredentialsFrom(filePath) {
|
|
79
|
+
if (!existsSync(filePath)) return null;
|
|
80
|
+
try {
|
|
81
|
+
const raw = readFileSync(filePath, "utf-8");
|
|
82
|
+
const data = JSON.parse(raw);
|
|
83
|
+
if (!data.clientKey || !data.secretKey) return null;
|
|
84
|
+
return data;
|
|
85
|
+
} catch {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function ensureGitignore() {
|
|
90
|
+
const gitignorePath = join(process.cwd(), ".gitignore");
|
|
91
|
+
const entry = ".01software/";
|
|
92
|
+
if (existsSync(gitignorePath)) {
|
|
93
|
+
const content = readFileSync(gitignorePath, "utf-8");
|
|
94
|
+
if (content.includes(entry)) return;
|
|
95
|
+
appendFileSync(gitignorePath, `
|
|
96
|
+
${entry}
|
|
97
|
+
`, "utf-8");
|
|
98
|
+
} else {
|
|
99
|
+
writeFileSync(gitignorePath, `${entry}
|
|
100
|
+
`, "utf-8");
|
|
101
|
+
}
|
|
102
|
+
}
|
|
47
103
|
|
|
48
104
|
// src/lib/client.ts
|
|
49
105
|
function resolveClient(apiKeyFlag) {
|
|
@@ -62,6 +118,13 @@ function resolveClient(apiKeyFlag) {
|
|
|
62
118
|
clientKey = process.env.SOFTWARE_CLIENT_KEY;
|
|
63
119
|
secretKey = process.env.SOFTWARE_SECRET_KEY;
|
|
64
120
|
}
|
|
121
|
+
if (!clientKey || !secretKey) {
|
|
122
|
+
const local = loadLocalCredentials();
|
|
123
|
+
if (local) {
|
|
124
|
+
clientKey = local.clientKey;
|
|
125
|
+
secretKey = local.secretKey;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
65
128
|
if (!clientKey || !secretKey) {
|
|
66
129
|
const stored = loadCredentials();
|
|
67
130
|
if (stored) {
|
|
@@ -147,6 +210,8 @@ function printError(error) {
|
|
|
147
210
|
}
|
|
148
211
|
|
|
149
212
|
// src/commands/crud.ts
|
|
213
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
214
|
+
import { basename } from "path";
|
|
150
215
|
import { COLLECTIONS } from "@01.software/sdk";
|
|
151
216
|
|
|
152
217
|
// src/lib/parse.ts
|
|
@@ -179,6 +244,10 @@ function parseJsonArray(value, label) {
|
|
|
179
244
|
}
|
|
180
245
|
|
|
181
246
|
// src/commands/crud.ts
|
|
247
|
+
function readFileAsBlob(filePath) {
|
|
248
|
+
const buffer = readFileSync2(filePath);
|
|
249
|
+
return { blob: new Blob([buffer]), filename: basename(filePath) };
|
|
250
|
+
}
|
|
182
251
|
var collectionList = COLLECTIONS.join(", ");
|
|
183
252
|
function validateCollection(name) {
|
|
184
253
|
if (!COLLECTIONS.includes(name)) {
|
|
@@ -214,24 +283,34 @@ function registerCrudCommands(program2, getClient2, getFormat2) {
|
|
|
214
283
|
process.exit(1);
|
|
215
284
|
}
|
|
216
285
|
});
|
|
217
|
-
program2.command("create <collection>").description("Create a new document").requiredOption("--data <json>", "Document data (JSON)").action(async (collection, opts) => {
|
|
286
|
+
program2.command("create <collection>").description("Create a new document").requiredOption("--data <json>", "Document data (JSON)").option("--file <path>", "File to upload (for upload collections)").action(async (collection, opts) => {
|
|
218
287
|
try {
|
|
219
288
|
const col = validateCollection(collection);
|
|
220
289
|
const client = getClient2();
|
|
221
290
|
const data = parseJson(opts.data, "data");
|
|
222
|
-
|
|
291
|
+
let fileOpts;
|
|
292
|
+
if (opts.file) {
|
|
293
|
+
const { blob, filename } = readFileAsBlob(opts.file);
|
|
294
|
+
fileOpts = { file: blob, filename };
|
|
295
|
+
}
|
|
296
|
+
const result = await client.collections.from(col).create(data, fileOpts);
|
|
223
297
|
printResult(result, getFormat2());
|
|
224
298
|
} catch (e) {
|
|
225
299
|
printError(e);
|
|
226
300
|
process.exit(1);
|
|
227
301
|
}
|
|
228
302
|
});
|
|
229
|
-
program2.command("update <collection> <id>").description("Update a document by ID").requiredOption("--data <json>", "Document data (JSON)").action(async (collection, id, opts) => {
|
|
303
|
+
program2.command("update <collection> <id>").description("Update a document by ID").requiredOption("--data <json>", "Document data (JSON)").option("--file <path>", "File to upload (for upload collections)").action(async (collection, id, opts) => {
|
|
230
304
|
try {
|
|
231
305
|
const col = validateCollection(collection);
|
|
232
306
|
const client = getClient2();
|
|
233
307
|
const data = parseJson(opts.data, "data");
|
|
234
|
-
|
|
308
|
+
let fileOpts;
|
|
309
|
+
if (opts.file) {
|
|
310
|
+
const { blob, filename } = readFileAsBlob(opts.file);
|
|
311
|
+
fileOpts = { file: blob, filename };
|
|
312
|
+
}
|
|
313
|
+
const result = await client.collections.from(col).update(id, data, fileOpts);
|
|
235
314
|
printResult(result, getFormat2());
|
|
236
315
|
} catch (e) {
|
|
237
316
|
printError(e);
|
|
@@ -530,9 +609,8 @@ var ERROR_HTML = (msg) => `<!DOCTYPE html>
|
|
|
530
609
|
<html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width"><title>CLI Login Error</title>
|
|
531
610
|
<style>${PAGE_STYLE}</style>
|
|
532
611
|
</head><body><div class="card"><div class="icon err">!</div><h1>Authentication failed</h1><p>${escapeHtml(msg)}</p></div></body></html>`;
|
|
533
|
-
function
|
|
534
|
-
|
|
535
|
-
const state = randomBytes(32).toString("hex");
|
|
612
|
+
function startAuthServer(options) {
|
|
613
|
+
return new Promise((resolve, reject) => {
|
|
536
614
|
const server = createServer((req, res) => {
|
|
537
615
|
if (!req.url) {
|
|
538
616
|
res.writeHead(400).end();
|
|
@@ -547,6 +625,8 @@ function registerAuthCommands(program2) {
|
|
|
547
625
|
const clientKey = url.searchParams.get("clientKey");
|
|
548
626
|
const secretKey = url.searchParams.get("secretKey");
|
|
549
627
|
const tenant = url.searchParams.get("tenant");
|
|
628
|
+
const tenantIdParam = url.searchParams.get("tenantId");
|
|
629
|
+
const tenantsParam = url.searchParams.get("tenants");
|
|
550
630
|
const error = url.searchParams.get("error");
|
|
551
631
|
if (error) {
|
|
552
632
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(ERROR_HTML(error));
|
|
@@ -554,7 +634,7 @@ function registerAuthCommands(program2) {
|
|
|
554
634
|
cleanup(1);
|
|
555
635
|
return;
|
|
556
636
|
}
|
|
557
|
-
if (receivedState !== state) {
|
|
637
|
+
if (receivedState !== options.state) {
|
|
558
638
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(ERROR_HTML("State mismatch \u2014 possible CSRF attack."));
|
|
559
639
|
console.error(pc4.red("Login failed: state mismatch."));
|
|
560
640
|
cleanup(1);
|
|
@@ -566,12 +646,28 @@ function registerAuthCommands(program2) {
|
|
|
566
646
|
cleanup(1);
|
|
567
647
|
return;
|
|
568
648
|
}
|
|
569
|
-
|
|
649
|
+
options.saveFn({
|
|
650
|
+
clientKey,
|
|
651
|
+
secretKey,
|
|
652
|
+
...tenantIdParam ? { tenantId: tenantIdParam } : {},
|
|
653
|
+
tenantName: tenant
|
|
654
|
+
});
|
|
655
|
+
if (tenantsParam) {
|
|
656
|
+
try {
|
|
657
|
+
const parsed = JSON.parse(tenantsParam);
|
|
658
|
+
if (Array.isArray(parsed)) {
|
|
659
|
+
const valid = parsed.filter(
|
|
660
|
+
(t) => typeof t?.id === "string" && typeof t?.name === "string"
|
|
661
|
+
);
|
|
662
|
+
if (valid.length > 0) saveTenantList(valid);
|
|
663
|
+
}
|
|
664
|
+
} catch {
|
|
665
|
+
}
|
|
666
|
+
}
|
|
570
667
|
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" }).end(SUCCESS_HTML);
|
|
571
668
|
console.log(pc4.green(`
|
|
572
669
|
Logged in successfully!`));
|
|
573
670
|
console.log(pc4.dim(`Tenant: ${tenant}`));
|
|
574
|
-
console.log(pc4.dim(`Credentials saved to ${getCredentialsPath()}`));
|
|
575
671
|
cleanup(0);
|
|
576
672
|
});
|
|
577
673
|
let timeout;
|
|
@@ -585,26 +681,42 @@ Logged in successfully!`));
|
|
|
585
681
|
server.listen(0, "127.0.0.1", () => {
|
|
586
682
|
const addr = server.address();
|
|
587
683
|
if (!addr || typeof addr === "string") {
|
|
588
|
-
|
|
589
|
-
|
|
684
|
+
reject(new Error("Failed to start local server."));
|
|
685
|
+
return;
|
|
590
686
|
}
|
|
591
|
-
const port = addr.port;
|
|
592
|
-
const params = new URLSearchParams({ port: String(port), state });
|
|
593
|
-
const loginUrl = `${WEB_URL}/cli-auth?${params.toString()}`;
|
|
594
|
-
console.log(pc4.dim("Opening browser for login..."));
|
|
595
|
-
console.log(pc4.dim(`If the browser does not open, visit:
|
|
596
|
-
${loginUrl}`));
|
|
597
|
-
openBrowser(loginUrl);
|
|
598
687
|
timeout = setTimeout(() => {
|
|
599
688
|
console.error(pc4.red("\nLogin timed out (3 minutes). Please try again."));
|
|
600
689
|
cleanup(1);
|
|
601
690
|
}, TIMEOUT_MS);
|
|
691
|
+
resolve({ port: addr.port, cleanup });
|
|
602
692
|
});
|
|
603
693
|
server.on("error", (err) => {
|
|
604
|
-
|
|
605
|
-
process.exit(1);
|
|
694
|
+
reject(err);
|
|
606
695
|
});
|
|
607
696
|
});
|
|
697
|
+
}
|
|
698
|
+
function registerAuthCommands(program2) {
|
|
699
|
+
program2.command("login").description("Login via browser and store credentials").action(async () => {
|
|
700
|
+
const state = randomBytes(32).toString("hex");
|
|
701
|
+
try {
|
|
702
|
+
const { port } = await startAuthServer({
|
|
703
|
+
state,
|
|
704
|
+
saveFn: (creds) => {
|
|
705
|
+
saveCredentials(creds);
|
|
706
|
+
console.log(pc4.dim(`Credentials saved to ${getCredentialsPath()}`));
|
|
707
|
+
}
|
|
708
|
+
});
|
|
709
|
+
const params = new URLSearchParams({ port: String(port), state });
|
|
710
|
+
const loginUrl = `${WEB_URL}/cli-auth?${params.toString()}`;
|
|
711
|
+
console.log(pc4.dim("Opening browser for login..."));
|
|
712
|
+
console.log(pc4.dim(`If the browser does not open, visit:
|
|
713
|
+
${loginUrl}`));
|
|
714
|
+
openBrowser(loginUrl);
|
|
715
|
+
} catch (err) {
|
|
716
|
+
console.error(pc4.red(`Server error: ${err instanceof Error ? err.message : String(err)}`));
|
|
717
|
+
process.exit(1);
|
|
718
|
+
}
|
|
719
|
+
});
|
|
608
720
|
program2.command("logout").description("Remove stored credentials").action(() => {
|
|
609
721
|
const deleted = deleteCredentials();
|
|
610
722
|
if (deleted) {
|
|
@@ -614,16 +726,85 @@ ${loginUrl}`));
|
|
|
614
726
|
}
|
|
615
727
|
});
|
|
616
728
|
program2.command("whoami").description("Show current authentication status").action(() => {
|
|
617
|
-
const
|
|
729
|
+
const localCreds = loadLocalCredentials();
|
|
730
|
+
const globalCreds = loadCredentials();
|
|
731
|
+
const creds = localCreds || globalCreds;
|
|
732
|
+
const isLocal = !!localCreds;
|
|
618
733
|
if (!creds) {
|
|
619
734
|
console.log(pc4.dim('Not logged in. Run "01 login" to authenticate.'));
|
|
620
735
|
return;
|
|
621
736
|
}
|
|
622
737
|
const masked = creds.clientKey.length > 8 ? creds.clientKey.slice(0, 4) + "..." + creds.clientKey.slice(-4) : "****";
|
|
623
|
-
|
|
738
|
+
const scope = isLocal ? pc4.cyan(" (local)") : "";
|
|
739
|
+
console.log(`Tenant: ${pc4.bold(creds.tenantName)}${scope}`);
|
|
624
740
|
console.log(`Client Key: ${pc4.dim(masked)}`);
|
|
625
741
|
console.log(`Stored at: ${pc4.dim(creds.storedAt)}`);
|
|
626
|
-
console.log(`File: ${pc4.dim(getCredentialsPath())}`);
|
|
742
|
+
console.log(`File: ${pc4.dim(isLocal ? getLocalCredentialsPath() : getCredentialsPath())}`);
|
|
743
|
+
});
|
|
744
|
+
const tenant = program2.command("tenant").description("Manage tenant switching");
|
|
745
|
+
tenant.command("list").description("Show cached tenant list").action(() => {
|
|
746
|
+
const tenants = loadTenantList();
|
|
747
|
+
if (!tenants || tenants.length === 0) {
|
|
748
|
+
console.log(pc4.dim('No cached tenants. Run "01 login" first.'));
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
const localCreds = loadLocalCredentials();
|
|
752
|
+
const globalCreds = loadCredentials();
|
|
753
|
+
const activeCreds = localCreds || globalCreds;
|
|
754
|
+
const activeId = activeCreds?.tenantId;
|
|
755
|
+
const activeName = activeCreds?.tenantName;
|
|
756
|
+
console.log(pc4.bold("Cached tenants:\n"));
|
|
757
|
+
for (const t of tenants) {
|
|
758
|
+
const active = (activeId ? t.id === activeId : t.name === activeName) ? pc4.green(" *") : "";
|
|
759
|
+
console.log(` ${t.name}${active}`);
|
|
760
|
+
}
|
|
761
|
+
console.log();
|
|
762
|
+
if (activeName) {
|
|
763
|
+
const scope = localCreds ? "(local)" : "(global)";
|
|
764
|
+
console.log(pc4.dim(`* active ${scope}`));
|
|
765
|
+
}
|
|
766
|
+
});
|
|
767
|
+
tenant.command("use <name>").description("Switch to a different tenant via browser").option("--local", "Save credentials locally in the current project").action(async (name, opts) => {
|
|
768
|
+
const tenants = loadTenantList();
|
|
769
|
+
if (!tenants || tenants.length === 0) {
|
|
770
|
+
console.error(pc4.red('No cached tenants. Run "01 login" first.'));
|
|
771
|
+
process.exit(1);
|
|
772
|
+
}
|
|
773
|
+
const match = tenants.find((t) => t.name.toLowerCase() === name.toLowerCase());
|
|
774
|
+
if (!match) {
|
|
775
|
+
console.error(pc4.red(`Tenant "${name}" not found in cache.`));
|
|
776
|
+
console.error(pc4.dim(`Available: ${tenants.map((t) => t.name).join(", ")}`));
|
|
777
|
+
process.exit(1);
|
|
778
|
+
}
|
|
779
|
+
const state = randomBytes(32).toString("hex");
|
|
780
|
+
const isLocal = !!opts.local;
|
|
781
|
+
try {
|
|
782
|
+
const { port } = await startAuthServer({
|
|
783
|
+
state,
|
|
784
|
+
saveFn: (creds) => {
|
|
785
|
+
if (isLocal) {
|
|
786
|
+
saveLocalCredentials(creds);
|
|
787
|
+
console.log(pc4.dim(`Credentials saved to ${getLocalCredentialsPath()}`));
|
|
788
|
+
} else {
|
|
789
|
+
saveCredentials(creds);
|
|
790
|
+
console.log(pc4.dim(`Credentials saved to ${getCredentialsPath()}`));
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
const params = new URLSearchParams({
|
|
795
|
+
port: String(port),
|
|
796
|
+
state,
|
|
797
|
+
tenantId: match.id
|
|
798
|
+
});
|
|
799
|
+
const loginUrl = `${WEB_URL}/cli-auth?${params.toString()}`;
|
|
800
|
+
console.log(pc4.dim(`Switching to tenant "${match.name}"...`));
|
|
801
|
+
console.log(pc4.dim(`If the browser does not open, visit:
|
|
802
|
+
${loginUrl}`));
|
|
803
|
+
openBrowser(loginUrl);
|
|
804
|
+
} catch (err) {
|
|
805
|
+
console.error(pc4.red(`Server error: ${err instanceof Error ? err.message : String(err)}`));
|
|
806
|
+
process.exit(1);
|
|
807
|
+
}
|
|
627
808
|
});
|
|
628
809
|
}
|
|
629
810
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/lib/client.ts","../src/lib/credentials.ts","../src/lib/output.ts","../src/commands/crud.ts","../src/lib/parse.ts","../src/commands/order.ts","../src/commands/return.ts","../src/commands/cart.ts","../src/commands/stock.ts","../src/commands/transaction.ts","../src/commands/auth.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport { Command } from 'commander'\nimport { resolveClient } from './lib/client.js'\nimport { printError } from './lib/output.js'\nimport { registerCrudCommands } from './commands/crud.js'\nimport { registerOrderCommands } from './commands/order.js'\nimport { registerReturnCommands } from './commands/return.js'\nimport { registerCartCommands } from './commands/cart.js'\nimport { registerStockCommands } from './commands/stock.js'\nimport { registerTransactionCommands } from './commands/transaction.js'\nimport { registerAuthCommands } from './commands/auth.js'\n\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json') as { version: string }\n\nprocess.on('unhandledRejection', (err) => {\n printError(err)\n process.exit(1)\n})\n\nconst program = new Command()\n\nprogram\n .name('01')\n .description('CLI for the 01.software platform')\n .version(version)\n .option('--api-key <base64>', 'Base64-encoded API key (clientKey:secretKey)')\n .option('--format <format>', 'Output format: json (default) or table', 'json')\n\nconst getFormat = () => program.opts().format as string\nconst getClient = () => resolveClient(program.opts().apiKey as string | undefined)\n\nregisterCrudCommands(program, getClient, getFormat)\nregisterOrderCommands(program, getClient, getFormat)\nregisterReturnCommands(program, getClient, getFormat)\nregisterCartCommands(program, getClient, getFormat)\nregisterStockCommands(program, getClient, getFormat)\nregisterTransactionCommands(program, getClient, getFormat)\nregisterAuthCommands(program)\n\nprogram.parse()\n","import { CollectionClient, OrderApi, CartApi, ProductApi, parseApiKey } from '@01.software/sdk'\nimport pc from 'picocolors'\nimport { loadCredentials } from './credentials.js'\n\nexport interface ResolvedClient {\n collections: CollectionClient\n api: OrderApi\n cart: CartApi\n product: ProductApi\n}\n\nexport function resolveClient(apiKeyFlag?: string): ResolvedClient {\n let clientKey: string | undefined\n let secretKey: string | undefined\n\n if (apiKeyFlag) {\n try {\n const parsed = parseApiKey(apiKeyFlag)\n clientKey = parsed.clientKey\n secretKey = parsed.secretKey\n } catch {\n console.error(pc.red('Invalid --api-key value. Expected Base64-encoded \"clientKey:secretKey\".'))\n process.exit(1)\n }\n } else {\n clientKey = process.env.SOFTWARE_CLIENT_KEY\n secretKey = process.env.SOFTWARE_SECRET_KEY\n }\n\n // Fallback to stored credentials from \"01 login\"\n if (!clientKey || !secretKey) {\n const stored = loadCredentials()\n if (stored) {\n clientKey = stored.clientKey\n secretKey = stored.secretKey\n }\n }\n\n if (!clientKey || !secretKey) {\n console.error(pc.red('Authentication required.'))\n console.error(\n pc.dim(\n 'Run \"01 login\" to authenticate via browser,\\n' +\n 'or set SOFTWARE_CLIENT_KEY and SOFTWARE_SECRET_KEY environment variables,\\n' +\n 'or use the --api-key <base64> flag.',\n ),\n )\n process.exit(1)\n }\n\n const apiOpts = { clientKey, secretKey }\n\n return {\n collections: new CollectionClient(clientKey, secretKey),\n api: new OrderApi(apiOpts),\n cart: new CartApi(apiOpts),\n product: new ProductApi(apiOpts),\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\n\nexport interface StoredCredentials {\n clientKey: string\n secretKey: string\n tenantName: string\n storedAt: string\n}\n\nconst DIR_NAME = '.01software'\nconst FILE_NAME = 'credentials.json'\n\nexport function getCredentialsPath(): string {\n return join(homedir(), DIR_NAME, FILE_NAME)\n}\n\nexport function loadCredentials(): StoredCredentials | null {\n const filePath = getCredentialsPath()\n if (!existsSync(filePath)) return null\n\n try {\n const raw = readFileSync(filePath, 'utf-8')\n const data = JSON.parse(raw) as StoredCredentials\n if (!data.clientKey || !data.secretKey) return null\n return data\n } catch {\n return null\n }\n}\n\nexport function saveCredentials(creds: Omit<StoredCredentials, 'storedAt'>): void {\n const dir = join(homedir(), DIR_NAME)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n }\n\n const filePath = getCredentialsPath()\n const data: StoredCredentials = { ...creds, storedAt: new Date().toISOString() }\n writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: 'utf-8', mode: 0o600 })\n}\n\nexport function deleteCredentials(): boolean {\n const filePath = getCredentialsPath()\n if (!existsSync(filePath)) return false\n\n unlinkSync(filePath)\n return true\n}\n","import pc from 'picocolors'\n\nexport function printJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2))\n}\n\nexport function printTable(data: unknown): void {\n if (Array.isArray(data)) {\n if (data.length === 0) {\n console.log(pc.dim('(empty)'))\n return\n }\n const keys = Object.keys(data[0] as Record<string, unknown>)\n const widths = keys.map((k) =>\n Math.max(k.length, ...data.map((row) => String((row as Record<string, unknown>)[k] ?? '').length)),\n )\n\n // Header\n console.log(keys.map((k, i) => k.padEnd(widths[i]!)).join(' '))\n console.log(keys.map((_, i) => '-'.repeat(widths[i]!)).join(' '))\n\n // Rows\n for (const row of data) {\n console.log(\n keys.map((k, i) => String((row as Record<string, unknown>)[k] ?? '').padEnd(widths[i]!)).join(' '),\n )\n }\n } else if (data && typeof data === 'object') {\n const entries = Object.entries(data as Record<string, unknown>)\n const maxKey = Math.max(...entries.map(([k]) => k.length))\n for (const [key, value] of entries) {\n const display = typeof value === 'object' ? JSON.stringify(value) : String(value)\n console.log(`${pc.bold(key.padEnd(maxKey))} ${display}`)\n }\n } else {\n console.log(String(data))\n }\n}\n\nexport function printResult(data: unknown, format: string): void {\n if (format === 'table') {\n // For find responses with docs array, print the docs as table\n if (data && typeof data === 'object' && 'docs' in (data as Record<string, unknown>)) {\n const resp = data as { docs: unknown[]; totalDocs: number; page: number; totalPages: number }\n printTable(resp.docs)\n console.log(pc.dim(`\\n${resp.totalDocs} total | page ${resp.page}/${resp.totalPages}`))\n return\n }\n printTable(data)\n } else {\n printJson(data)\n }\n}\n\nexport function printError(error: unknown): void {\n if (error && typeof error === 'object' && 'message' in error) {\n const err = error as { message: string; code?: string; status?: number; suggestion?: string }\n console.error(pc.red(`Error: ${err.message}`))\n if (err.code) console.error(pc.dim(`Code: ${err.code}`))\n if (err.status) console.error(pc.dim(`Status: ${err.status}`))\n if (err.suggestion) console.error(pc.yellow(err.suggestion))\n } else {\n console.error(pc.red(String(error)))\n }\n}\n","import { Command } from 'commander'\nimport { COLLECTIONS } from '@01.software/sdk'\nimport type { ApiQueryOptions } from '@01.software/sdk'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJson } from '../lib/parse.js'\n\nconst collectionList = COLLECTIONS.join(', ')\n\nfunction validateCollection(name: string): string {\n if (!(COLLECTIONS as readonly string[]).includes(name)) {\n throw new Error(`Unknown collection \"${name}\". Available: ${collectionList}`)\n }\n return name\n}\n\nexport function registerCrudCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n program\n .command('query <collection>')\n .description('Query documents from a collection')\n .option('--where <json>', 'Filter conditions (JSON)')\n .option('--limit <n>', 'Max results', (v: string) => parseInt(v, 10))\n .option('--page <n>', 'Page number', (v: string) => parseInt(v, 10))\n .option('--sort <field>', 'Sort field (prefix with - for descending)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const options: Record<string, unknown> = {}\n if (opts.where) options.where = parseJson(opts.where, 'where')\n if (opts.limit) options.limit = opts.limit\n if (opts.page) options.page = opts.page\n if (opts.sort) options.sort = opts.sort\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).find(options)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('get <collection> <id>')\n .description('Get a document by ID')\n .action(async (collection: string, id: string) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).findById(id)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('create <collection>')\n .description('Create a new document')\n .requiredOption('--data <json>', 'Document data (JSON)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const data = parseJson(opts.data, 'data')\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).create(data)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('update <collection> <id>')\n .description('Update a document by ID')\n .requiredOption('--data <json>', 'Document data (JSON)')\n .action(async (collection: string, id: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const data = parseJson(opts.data, 'data')\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).update(id, data)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('delete <collection> <id>')\n .description('Delete a document by ID')\n .action(async (collection: string, id: string) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).remove(id)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('update-many <collection>')\n .description('Update multiple documents matching a filter')\n .requiredOption('--where <json>', 'Filter conditions (JSON)')\n .requiredOption('--data <json>', 'Update data (JSON)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const where = parseJson(opts.where, 'where') as ApiQueryOptions['where']\n const data = parseJson(opts.data, 'data')\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).updateMany(where, data)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('delete-many <collection>')\n .description('Delete multiple documents matching a filter')\n .requiredOption('--where <json>', 'Filter conditions (JSON)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const where = parseJson(opts.where, 'where') as ApiQueryOptions['where']\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).removeMany(where)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import pc from 'picocolors'\n\nexport function parseJson(value: string, label: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(value)\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n console.error(pc.red(`--${label} must be a JSON object.`))\n process.exit(1)\n }\n return parsed as Record<string, unknown>\n } catch {\n console.error(pc.red(`Invalid JSON for --${label}: ${value}`))\n process.exit(1)\n }\n}\n\nexport function parseJsonArray(value: string, label: string): unknown[] {\n try {\n const parsed = JSON.parse(value)\n if (!Array.isArray(parsed)) {\n console.error(pc.red(`--${label} must be a JSON array.`))\n process.exit(1)\n }\n return parsed\n } catch {\n console.error(pc.red(`Invalid JSON for --${label}: ${value}`))\n process.exit(1)\n }\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJson, parseJsonArray } from '../lib/parse.js'\n\nexport function registerOrderCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const order = program.command('order').description('Order management')\n\n order\n .command('create')\n .description('Create a new order')\n .requiredOption('--payment-id <id>', 'Payment ID')\n .requiredOption('--order-number <num>', 'Order number')\n .requiredOption('--email <email>', 'Customer email')\n .requiredOption('--shipping-address <json>', 'Shipping address (JSON)')\n .requiredOption('--products <json>', 'Order products array (JSON)')\n .requiredOption('--total-amount <n>', 'Total amount', parseFloat)\n .action(async (opts) => {\n try {\n const client = getClient()\n const result = await client.api.createOrder({\n paymentId: opts.paymentId,\n orderNumber: opts.orderNumber,\n email: opts.email,\n shippingAddress: parseJson(opts.shippingAddress, 'shipping-address'),\n orderProducts: parseJsonArray(opts.products, 'products') as Parameters<typeof client.api.createOrder>[0]['orderProducts'],\n totalAmount: opts.totalAmount,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('get <orderNumber>')\n .description('Get an order by order number')\n .action(async (orderNumber: string) => {\n try {\n const client = getClient()\n const result = await client.api.getOrder({ orderNumber })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('update <orderNumber>')\n .description('Update order status')\n .requiredOption('--status <status>', 'New status')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.updateOrder({\n orderNumber,\n status: opts.status,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('checkout')\n .description('Convert a cart to an order')\n .requiredOption('--cart-id <id>', 'Cart ID')\n .requiredOption('--payment-id <id>', 'Payment ID')\n .requiredOption('--order-number <num>', 'Order number')\n .requiredOption('--customer <json>', 'Customer snapshot (JSON)')\n .action(async (opts) => {\n try {\n const client = getClient()\n const result = await client.api.checkout({\n cartId: opts.cartId,\n paymentId: opts.paymentId,\n orderNumber: opts.orderNumber,\n customerSnapshot: parseJson(opts.customer, 'customer') as Parameters<typeof client.api.checkout>[0]['customerSnapshot'],\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('fulfill <orderNumber>')\n .description('Create a fulfillment for an order')\n .requiredOption('--items <json>', 'Fulfillment items array (JSON)')\n .option('--carrier <name>', 'Shipping carrier')\n .option('--tracking-number <num>', 'Tracking number')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.createFulfillment({\n orderNumber,\n items: parseJsonArray(opts.items, 'items') as Parameters<typeof client.api.createFulfillment>[0]['items'],\n carrier: opts.carrier,\n trackingNumber: opts.trackingNumber,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJsonArray } from '../lib/parse.js'\n\nexport function registerReturnCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const ret = program.command('return').description('Return management')\n\n ret\n .command('create <orderNumber>')\n .description('Create a return request')\n .requiredOption('--products <json>', 'Return products array (JSON)')\n .requiredOption('--refund-amount <n>', 'Refund amount', parseFloat)\n .option('--reason <reason>', 'Return reason (change_of_mind, defective, wrong_delivery, damaged, other)')\n .option('--reason-detail <text>', 'Detailed reason')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.createReturn({\n orderNumber,\n returnProducts: parseJsonArray(opts.products, 'products') as Parameters<typeof client.api.createReturn>[0]['returnProducts'],\n refundAmount: opts.refundAmount,\n reason: opts.reason,\n reasonDetail: opts.reasonDetail,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n ret\n .command('update <returnId>')\n .description('Update return status')\n .requiredOption('--status <status>', 'New status (processing, approved, rejected, completed)')\n .action(async (returnId: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.updateReturn({\n returnId,\n status: opts.status,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n ret\n .command('refund <orderNumber>')\n .description('Return with refund')\n .requiredOption('--products <json>', 'Return products array (JSON)')\n .requiredOption('--refund-amount <n>', 'Refund amount', parseFloat)\n .requiredOption('--payment-id <id>', 'Payment ID')\n .option('--reason <reason>', 'Return reason')\n .option('--reason-detail <text>', 'Detailed reason')\n .option('--refund-receipt-url <url>', 'Refund receipt URL')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.returnWithRefund({\n orderNumber,\n returnProducts: parseJsonArray(opts.products, 'products') as Parameters<typeof client.api.returnWithRefund>[0]['returnProducts'],\n refundAmount: opts.refundAmount,\n paymentId: opts.paymentId,\n reason: opts.reason,\n reasonDetail: opts.reasonDetail,\n refundReceiptUrl: opts.refundReceiptUrl,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\n\nexport function registerCartCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const cart = program.command('cart').description('Cart management')\n\n cart\n .command('add <cartId>')\n .description('Add an item to cart')\n .requiredOption('--product <id>', 'Product ID')\n .requiredOption('--variant <id>', 'Variant ID')\n .requiredOption('--option <id>', 'Option ID')\n .requiredOption('--quantity <n>', 'Quantity', (v: string) => parseInt(v, 10))\n .action(async (cartId: string, opts) => {\n try {\n const client = getClient()\n const result = await client.cart.addItem({\n cartId,\n product: opts.product,\n variant: opts.variant,\n option: opts.option,\n quantity: opts.quantity,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n cart\n .command('update <cartItemId>')\n .description('Update cart item quantity')\n .requiredOption('--quantity <n>', 'New quantity', (v: string) => parseInt(v, 10))\n .action(async (cartItemId: string, opts) => {\n try {\n const client = getClient()\n const result = await client.cart.updateItem({\n cartItemId,\n quantity: opts.quantity,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n cart\n .command('remove <cartItemId>')\n .description('Remove an item from cart')\n .action(async (cartItemId: string) => {\n try {\n const client = getClient()\n const result = await client.cart.removeItem({ cartItemId })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJsonArray } from '../lib/parse.js'\n\nexport function registerStockCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const stock = program.command('stock').description('Stock management')\n\n stock\n .command('check')\n .description('Check stock availability')\n .requiredOption('--items <json>', 'Items to check (JSON array of { optionId, quantity })')\n .action(async (opts) => {\n try {\n const client = getClient()\n const items = parseJsonArray(opts.items, 'items') as Parameters<typeof client.product.stockCheck>[0]['items']\n const result = await client.product.stockCheck({ items })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\n\nexport function registerTransactionCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const tx = program.command('transaction').description('Transaction management')\n\n tx\n .command('update')\n .description('Update transaction status')\n .requiredOption('--payment-id <id>', 'Payment ID')\n .requiredOption('--status <status>', 'New status (pending, paid, failed, canceled)')\n .requiredOption('--payment-method <method>', 'Payment method')\n .requiredOption('--receipt-url <url>', 'Receipt URL')\n .action(async (opts) => {\n try {\n const client = getClient()\n const result = await client.api.updateTransaction({\n paymentId: opts.paymentId,\n status: opts.status,\n paymentMethod: opts.paymentMethod,\n receiptUrl: opts.receiptUrl,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { randomBytes } from 'node:crypto'\nimport { createServer } from 'node:http'\nimport { execFile, exec } from 'node:child_process'\nimport { platform } from 'node:os'\nimport { URL } from 'node:url'\nimport type { Command } from 'commander'\nimport pc from 'picocolors'\nimport { loadCredentials, saveCredentials, deleteCredentials, getCredentialsPath } from '../lib/credentials.js'\n\nconst WEB_URL = process.env.SOFTWARE_WEB_URL || 'https://01.software'\nconst TIMEOUT_MS = 3 * 60 * 1000 // 3 minutes\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"')\n}\n\nfunction openBrowser(url: string): void {\n const os = platform()\n\n const onError = () => {\n console.log(pc.yellow(`Could not open browser automatically. Open this URL manually:\\n${url}`))\n }\n\n if (os === 'win32') {\n exec(`start \"\" \"${url}\"`, (err) => { if (err) onError() })\n } else {\n const cmd = os === 'darwin' ? 'open' : 'xdg-open'\n execFile(cmd, [url], (err) => { if (err) onError() })\n }\n}\n\nconst PAGE_STYLE = `*{margin:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;background:#fff;color:#252525}\n@media(prefers-color-scheme:dark){body{background:#252525;color:#f5f5f5}}\n.card{text-align:center;padding:2rem 2.5rem;border-radius:10px;max-width:380px;width:100%}\n.icon{width:40px;height:40px;margin:0 auto 1rem;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1.25rem}\n.icon.ok{background:rgba(0,0,0,.05);color:#252525}\n.icon.err{background:rgba(220,38,38,.08);color:#dc2626}\n@media(prefers-color-scheme:dark){.icon.ok{background:rgba(255,255,255,.08);color:#f5f5f5}}\nh1{font-size:.875rem;font-weight:600;margin-bottom:.375rem}\np{font-size:.75rem;color:#737373;line-height:1.5}`\n\nconst SUCCESS_HTML = `<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><title>CLI Login</title>\n<style>${PAGE_STYLE}</style>\n</head><body><div class=\"card\"><div class=\"icon ok\">\\u2713</div><h1>Authenticated</h1><p>You can close this tab and return to the terminal.</p></div></body></html>`\n\nconst ERROR_HTML = (msg: string) => `<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><title>CLI Login Error</title>\n<style>${PAGE_STYLE}</style>\n</head><body><div class=\"card\"><div class=\"icon err\">!</div><h1>Authentication failed</h1><p>${escapeHtml(msg)}</p></div></body></html>`\n\nexport function registerAuthCommands(program: Command): void {\n program\n .command('login')\n .description('Login via browser and store credentials')\n .action(async () => {\n const state = randomBytes(32).toString('hex')\n\n const server = createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400).end()\n return\n }\n\n const url = new URL(req.url, `http://localhost`)\n\n if (url.pathname !== '/callback') {\n res.writeHead(404).end()\n return\n }\n\n const receivedState = url.searchParams.get('state')\n const clientKey = url.searchParams.get('clientKey')\n const secretKey = url.searchParams.get('secretKey')\n const tenant = url.searchParams.get('tenant')\n const error = url.searchParams.get('error')\n\n if (error) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(ERROR_HTML(error))\n console.error(pc.red(`Login failed: ${error}`))\n cleanup(1)\n return\n }\n\n if (receivedState !== state) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(ERROR_HTML('State mismatch — possible CSRF attack.'))\n console.error(pc.red('Login failed: state mismatch.'))\n cleanup(1)\n return\n }\n\n if (!clientKey || !secretKey || !tenant) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(ERROR_HTML('Missing credentials in callback.'))\n console.error(pc.red('Login failed: missing credentials.'))\n cleanup(1)\n return\n }\n\n saveCredentials({ clientKey, secretKey, tenantName: tenant })\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(SUCCESS_HTML)\n\n console.log(pc.green(`\\nLogged in successfully!`))\n console.log(pc.dim(`Tenant: ${tenant}`))\n console.log(pc.dim(`Credentials saved to ${getCredentialsPath()}`))\n cleanup(0)\n })\n\n let timeout: ReturnType<typeof setTimeout>\n let completed = false\n\n function cleanup(exitCode = 0) {\n if (completed) return\n completed = true\n clearTimeout(timeout)\n server.close(() => process.exit(exitCode))\n }\n\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address()\n if (!addr || typeof addr === 'string') {\n console.error(pc.red('Failed to start local server.'))\n process.exit(1)\n }\n\n const port = addr.port\n const params = new URLSearchParams({ port: String(port), state })\n const loginUrl = `${WEB_URL}/cli-auth?${params.toString()}`\n\n console.log(pc.dim('Opening browser for login...'))\n console.log(pc.dim(`If the browser does not open, visit:\\n${loginUrl}`))\n openBrowser(loginUrl)\n\n timeout = setTimeout(() => {\n console.error(pc.red('\\nLogin timed out (3 minutes). Please try again.'))\n cleanup(1)\n }, TIMEOUT_MS)\n })\n\n server.on('error', (err) => {\n console.error(pc.red(`Server error: ${err.message}`))\n process.exit(1)\n })\n })\n\n program\n .command('logout')\n .description('Remove stored credentials')\n .action(() => {\n const deleted = deleteCredentials()\n if (deleted) {\n console.log(pc.green('Logged out. Credentials removed.'))\n } else {\n console.log(pc.dim('No stored credentials found.'))\n }\n })\n\n program\n .command('whoami')\n .description('Show current authentication status')\n .action(() => {\n const creds = loadCredentials()\n if (!creds) {\n console.log(pc.dim('Not logged in. Run \"01 login\" to authenticate.'))\n return\n }\n\n const masked = creds.clientKey.length > 8\n ? creds.clientKey.slice(0, 4) + '...' + creds.clientKey.slice(-4)\n : '****'\n\n console.log(`Tenant: ${pc.bold(creds.tenantName)}`)\n console.log(`Client Key: ${pc.dim(masked)}`)\n console.log(`Stored at: ${pc.dim(creds.storedAt)}`)\n console.log(`File: ${pc.dim(getCredentialsPath())}`)\n })\n}\n"],"mappings":"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","names":["pc","pc","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","pc","pc","program","require"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/lib/client.ts","../src/lib/credentials.ts","../src/lib/output.ts","../src/commands/crud.ts","../src/lib/parse.ts","../src/commands/order.ts","../src/commands/return.ts","../src/commands/cart.ts","../src/commands/stock.ts","../src/commands/transaction.ts","../src/commands/auth.ts"],"sourcesContent":["import { createRequire } from 'node:module'\nimport { Command } from 'commander'\nimport { resolveClient } from './lib/client.js'\nimport { printError } from './lib/output.js'\nimport { registerCrudCommands } from './commands/crud.js'\nimport { registerOrderCommands } from './commands/order.js'\nimport { registerReturnCommands } from './commands/return.js'\nimport { registerCartCommands } from './commands/cart.js'\nimport { registerStockCommands } from './commands/stock.js'\nimport { registerTransactionCommands } from './commands/transaction.js'\nimport { registerAuthCommands } from './commands/auth.js'\n\nconst require = createRequire(import.meta.url)\nconst { version } = require('../package.json') as { version: string }\n\nprocess.on('unhandledRejection', (err) => {\n printError(err)\n process.exit(1)\n})\n\nconst program = new Command()\n\nprogram\n .name('01')\n .description('CLI for the 01.software platform')\n .version(version)\n .option('--api-key <base64>', 'Base64-encoded API key (clientKey:secretKey)')\n .option('--format <format>', 'Output format: json (default) or table', 'json')\n\nconst getFormat = () => program.opts().format as string\nconst getClient = () => resolveClient(program.opts().apiKey as string | undefined)\n\nregisterCrudCommands(program, getClient, getFormat)\nregisterOrderCommands(program, getClient, getFormat)\nregisterReturnCommands(program, getClient, getFormat)\nregisterCartCommands(program, getClient, getFormat)\nregisterStockCommands(program, getClient, getFormat)\nregisterTransactionCommands(program, getClient, getFormat)\nregisterAuthCommands(program)\n\nprogram.parse()\n","import { CollectionClient, OrderApi, CartApi, ProductApi, parseApiKey } from '@01.software/sdk'\nimport pc from 'picocolors'\nimport { loadCredentials, loadLocalCredentials } from './credentials.js'\n\nexport interface ResolvedClient {\n collections: CollectionClient\n api: OrderApi\n cart: CartApi\n product: ProductApi\n}\n\nexport function resolveClient(apiKeyFlag?: string): ResolvedClient {\n let clientKey: string | undefined\n let secretKey: string | undefined\n\n if (apiKeyFlag) {\n try {\n const parsed = parseApiKey(apiKeyFlag)\n clientKey = parsed.clientKey\n secretKey = parsed.secretKey\n } catch {\n console.error(pc.red('Invalid --api-key value. Expected Base64-encoded \"clientKey:secretKey\".'))\n process.exit(1)\n }\n } else {\n clientKey = process.env.SOFTWARE_CLIENT_KEY\n secretKey = process.env.SOFTWARE_SECRET_KEY\n }\n\n // Fallback: local credentials (./01software/credentials.json)\n if (!clientKey || !secretKey) {\n const local = loadLocalCredentials()\n if (local) {\n clientKey = local.clientKey\n secretKey = local.secretKey\n }\n }\n\n // Fallback: global credentials (~/.01software/credentials.json)\n if (!clientKey || !secretKey) {\n const stored = loadCredentials()\n if (stored) {\n clientKey = stored.clientKey\n secretKey = stored.secretKey\n }\n }\n\n if (!clientKey || !secretKey) {\n console.error(pc.red('Authentication required.'))\n console.error(\n pc.dim(\n 'Run \"01 login\" to authenticate via browser,\\n' +\n 'or set SOFTWARE_CLIENT_KEY and SOFTWARE_SECRET_KEY environment variables,\\n' +\n 'or use the --api-key <base64> flag.',\n ),\n )\n process.exit(1)\n }\n\n const apiOpts = { clientKey, secretKey }\n\n return {\n collections: new CollectionClient(clientKey, secretKey),\n api: new OrderApi(apiOpts),\n cart: new CartApi(apiOpts),\n product: new ProductApi(apiOpts),\n }\n}\n","import { existsSync, mkdirSync, readFileSync, writeFileSync, unlinkSync, appendFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { homedir } from 'node:os'\n\nexport interface StoredCredentials {\n clientKey: string\n secretKey: string\n tenantId?: string\n tenantName: string\n storedAt: string\n}\n\nexport interface TenantInfo {\n id: string\n name: string\n}\n\nconst DIR_NAME = '.01software'\nconst FILE_NAME = 'credentials.json'\nconst TENANTS_FILE = 'tenants.json'\n\n// ---------------------------------------------------------------------------\n// Global credentials (~/.01software/credentials.json)\n// ---------------------------------------------------------------------------\n\nexport function getCredentialsPath(): string {\n return join(homedir(), DIR_NAME, FILE_NAME)\n}\n\nexport function loadCredentials(): StoredCredentials | null {\n return loadCredentialsFrom(getCredentialsPath())\n}\n\nexport function saveCredentials(creds: Omit<StoredCredentials, 'storedAt'>): void {\n const dir = join(homedir(), DIR_NAME)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n }\n\n const filePath = getCredentialsPath()\n const data: StoredCredentials = { ...creds, storedAt: new Date().toISOString() }\n writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: 'utf-8', mode: 0o600 })\n}\n\nexport function deleteCredentials(): boolean {\n const filePath = getCredentialsPath()\n if (!existsSync(filePath)) return false\n\n unlinkSync(filePath)\n return true\n}\n\n// ---------------------------------------------------------------------------\n// Local credentials (./01software/credentials.json)\n// ---------------------------------------------------------------------------\n\nexport function getLocalCredentialsPath(): string {\n return join(process.cwd(), DIR_NAME, FILE_NAME)\n}\n\nexport function loadLocalCredentials(): StoredCredentials | null {\n return loadCredentialsFrom(getLocalCredentialsPath())\n}\n\nexport function saveLocalCredentials(creds: Omit<StoredCredentials, 'storedAt'>): void {\n const dir = join(process.cwd(), DIR_NAME)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n }\n\n const filePath = getLocalCredentialsPath()\n const data: StoredCredentials = { ...creds, storedAt: new Date().toISOString() }\n writeFileSync(filePath, JSON.stringify(data, null, 2), { encoding: 'utf-8', mode: 0o600 })\n\n // Ensure .01software/ is in .gitignore\n ensureGitignore()\n}\n\n// ---------------------------------------------------------------------------\n// Tenant list cache (~/.01software/tenants.json)\n// ---------------------------------------------------------------------------\n\nexport function saveTenantList(tenants: TenantInfo[]): void {\n const dir = join(homedir(), DIR_NAME)\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true, mode: 0o700 })\n }\n\n const filePath = join(homedir(), DIR_NAME, TENANTS_FILE)\n writeFileSync(filePath, JSON.stringify(tenants, null, 2), { encoding: 'utf-8', mode: 0o600 })\n}\n\nexport function loadTenantList(): TenantInfo[] | null {\n const filePath = join(homedir(), DIR_NAME, TENANTS_FILE)\n if (!existsSync(filePath)) return null\n\n try {\n const raw = readFileSync(filePath, 'utf-8')\n const data = JSON.parse(raw)\n if (!Array.isArray(data)) return null\n const valid = data.filter(\n (t): t is TenantInfo => typeof t?.id === 'string' && typeof t?.name === 'string',\n )\n return valid.length > 0 ? valid : null\n } catch {\n return null\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nfunction loadCredentialsFrom(filePath: string): StoredCredentials | null {\n if (!existsSync(filePath)) return null\n\n try {\n const raw = readFileSync(filePath, 'utf-8')\n const data = JSON.parse(raw) as StoredCredentials\n if (!data.clientKey || !data.secretKey) return null\n return data\n } catch {\n return null\n }\n}\n\nfunction ensureGitignore(): void {\n const gitignorePath = join(process.cwd(), '.gitignore')\n const entry = '.01software/'\n\n if (existsSync(gitignorePath)) {\n const content = readFileSync(gitignorePath, 'utf-8')\n if (content.includes(entry)) return\n appendFileSync(gitignorePath, `\\n${entry}\\n`, 'utf-8')\n } else {\n writeFileSync(gitignorePath, `${entry}\\n`, 'utf-8')\n }\n}\n","import pc from 'picocolors'\n\nexport function printJson(data: unknown): void {\n console.log(JSON.stringify(data, null, 2))\n}\n\nexport function printTable(data: unknown): void {\n if (Array.isArray(data)) {\n if (data.length === 0) {\n console.log(pc.dim('(empty)'))\n return\n }\n const keys = Object.keys(data[0] as Record<string, unknown>)\n const widths = keys.map((k) =>\n Math.max(k.length, ...data.map((row) => String((row as Record<string, unknown>)[k] ?? '').length)),\n )\n\n // Header\n console.log(keys.map((k, i) => k.padEnd(widths[i]!)).join(' '))\n console.log(keys.map((_, i) => '-'.repeat(widths[i]!)).join(' '))\n\n // Rows\n for (const row of data) {\n console.log(\n keys.map((k, i) => String((row as Record<string, unknown>)[k] ?? '').padEnd(widths[i]!)).join(' '),\n )\n }\n } else if (data && typeof data === 'object') {\n const entries = Object.entries(data as Record<string, unknown>)\n const maxKey = Math.max(...entries.map(([k]) => k.length))\n for (const [key, value] of entries) {\n const display = typeof value === 'object' ? JSON.stringify(value) : String(value)\n console.log(`${pc.bold(key.padEnd(maxKey))} ${display}`)\n }\n } else {\n console.log(String(data))\n }\n}\n\nexport function printResult(data: unknown, format: string): void {\n if (format === 'table') {\n // For find responses with docs array, print the docs as table\n if (data && typeof data === 'object' && 'docs' in (data as Record<string, unknown>)) {\n const resp = data as { docs: unknown[]; totalDocs: number; page: number; totalPages: number }\n printTable(resp.docs)\n console.log(pc.dim(`\\n${resp.totalDocs} total | page ${resp.page}/${resp.totalPages}`))\n return\n }\n printTable(data)\n } else {\n printJson(data)\n }\n}\n\nexport function printError(error: unknown): void {\n if (error && typeof error === 'object' && 'message' in error) {\n const err = error as { message: string; code?: string; status?: number; suggestion?: string }\n console.error(pc.red(`Error: ${err.message}`))\n if (err.code) console.error(pc.dim(`Code: ${err.code}`))\n if (err.status) console.error(pc.dim(`Status: ${err.status}`))\n if (err.suggestion) console.error(pc.yellow(err.suggestion))\n } else {\n console.error(pc.red(String(error)))\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { basename } from 'node:path'\nimport { Command } from 'commander'\nimport { COLLECTIONS } from '@01.software/sdk'\nimport type { ApiQueryOptions } from '@01.software/sdk'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJson } from '../lib/parse.js'\n\nfunction readFileAsBlob(filePath: string): { blob: Blob; filename: string } {\n const buffer = readFileSync(filePath)\n return { blob: new Blob([buffer]), filename: basename(filePath) }\n}\n\nconst collectionList = COLLECTIONS.join(', ')\n\nfunction validateCollection(name: string): string {\n if (!(COLLECTIONS as readonly string[]).includes(name)) {\n throw new Error(`Unknown collection \"${name}\". Available: ${collectionList}`)\n }\n return name\n}\n\nexport function registerCrudCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n program\n .command('query <collection>')\n .description('Query documents from a collection')\n .option('--where <json>', 'Filter conditions (JSON)')\n .option('--limit <n>', 'Max results', (v: string) => parseInt(v, 10))\n .option('--page <n>', 'Page number', (v: string) => parseInt(v, 10))\n .option('--sort <field>', 'Sort field (prefix with - for descending)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const options: Record<string, unknown> = {}\n if (opts.where) options.where = parseJson(opts.where, 'where')\n if (opts.limit) options.limit = opts.limit\n if (opts.page) options.page = opts.page\n if (opts.sort) options.sort = opts.sort\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).find(options)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('get <collection> <id>')\n .description('Get a document by ID')\n .action(async (collection: string, id: string) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).findById(id)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('create <collection>')\n .description('Create a new document')\n .requiredOption('--data <json>', 'Document data (JSON)')\n .option('--file <path>', 'File to upload (for upload collections)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const data = parseJson(opts.data, 'data')\n let fileOpts: { file: Blob; filename: string } | undefined\n if (opts.file) {\n const { blob, filename } = readFileAsBlob(opts.file)\n fileOpts = { file: blob, filename }\n }\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).create(data, fileOpts)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('update <collection> <id>')\n .description('Update a document by ID')\n .requiredOption('--data <json>', 'Document data (JSON)')\n .option('--file <path>', 'File to upload (for upload collections)')\n .action(async (collection: string, id: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const data = parseJson(opts.data, 'data')\n let fileOpts: { file: Blob; filename: string } | undefined\n if (opts.file) {\n const { blob, filename } = readFileAsBlob(opts.file)\n fileOpts = { file: blob, filename }\n }\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).update(id, data, fileOpts)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('delete <collection> <id>')\n .description('Delete a document by ID')\n .action(async (collection: string, id: string) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).remove(id)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('update-many <collection>')\n .description('Update multiple documents matching a filter')\n .requiredOption('--where <json>', 'Filter conditions (JSON)')\n .requiredOption('--data <json>', 'Update data (JSON)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const where = parseJson(opts.where, 'where') as ApiQueryOptions['where']\n const data = parseJson(opts.data, 'data')\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).updateMany(where, data)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n program\n .command('delete-many <collection>')\n .description('Delete multiple documents matching a filter')\n .requiredOption('--where <json>', 'Filter conditions (JSON)')\n .action(async (collection: string, opts) => {\n try {\n const col = validateCollection(collection)\n const client = getClient()\n const where = parseJson(opts.where, 'where') as ApiQueryOptions['where']\n const result = await client.collections.from(col as typeof COLLECTIONS[number]).removeMany(where)\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import pc from 'picocolors'\n\nexport function parseJson(value: string, label: string): Record<string, unknown> {\n try {\n const parsed = JSON.parse(value)\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n console.error(pc.red(`--${label} must be a JSON object.`))\n process.exit(1)\n }\n return parsed as Record<string, unknown>\n } catch {\n console.error(pc.red(`Invalid JSON for --${label}: ${value}`))\n process.exit(1)\n }\n}\n\nexport function parseJsonArray(value: string, label: string): unknown[] {\n try {\n const parsed = JSON.parse(value)\n if (!Array.isArray(parsed)) {\n console.error(pc.red(`--${label} must be a JSON array.`))\n process.exit(1)\n }\n return parsed\n } catch {\n console.error(pc.red(`Invalid JSON for --${label}: ${value}`))\n process.exit(1)\n }\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJson, parseJsonArray } from '../lib/parse.js'\n\nexport function registerOrderCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const order = program.command('order').description('Order management')\n\n order\n .command('create')\n .description('Create a new order')\n .requiredOption('--payment-id <id>', 'Payment ID')\n .requiredOption('--order-number <num>', 'Order number')\n .requiredOption('--email <email>', 'Customer email')\n .requiredOption('--shipping-address <json>', 'Shipping address (JSON)')\n .requiredOption('--products <json>', 'Order products array (JSON)')\n .requiredOption('--total-amount <n>', 'Total amount', parseFloat)\n .action(async (opts) => {\n try {\n const client = getClient()\n const result = await client.api.createOrder({\n paymentId: opts.paymentId,\n orderNumber: opts.orderNumber,\n email: opts.email,\n shippingAddress: parseJson(opts.shippingAddress, 'shipping-address'),\n orderProducts: parseJsonArray(opts.products, 'products') as Parameters<typeof client.api.createOrder>[0]['orderProducts'],\n totalAmount: opts.totalAmount,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('get <orderNumber>')\n .description('Get an order by order number')\n .action(async (orderNumber: string) => {\n try {\n const client = getClient()\n const result = await client.api.getOrder({ orderNumber })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('update <orderNumber>')\n .description('Update order status')\n .requiredOption('--status <status>', 'New status')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.updateOrder({\n orderNumber,\n status: opts.status,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('checkout')\n .description('Convert a cart to an order')\n .requiredOption('--cart-id <id>', 'Cart ID')\n .requiredOption('--payment-id <id>', 'Payment ID')\n .requiredOption('--order-number <num>', 'Order number')\n .requiredOption('--customer <json>', 'Customer snapshot (JSON)')\n .action(async (opts) => {\n try {\n const client = getClient()\n const result = await client.api.checkout({\n cartId: opts.cartId,\n paymentId: opts.paymentId,\n orderNumber: opts.orderNumber,\n customerSnapshot: parseJson(opts.customer, 'customer') as Parameters<typeof client.api.checkout>[0]['customerSnapshot'],\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n order\n .command('fulfill <orderNumber>')\n .description('Create a fulfillment for an order')\n .requiredOption('--items <json>', 'Fulfillment items array (JSON)')\n .option('--carrier <name>', 'Shipping carrier')\n .option('--tracking-number <num>', 'Tracking number')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.createFulfillment({\n orderNumber,\n items: parseJsonArray(opts.items, 'items') as Parameters<typeof client.api.createFulfillment>[0]['items'],\n carrier: opts.carrier,\n trackingNumber: opts.trackingNumber,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJsonArray } from '../lib/parse.js'\n\nexport function registerReturnCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const ret = program.command('return').description('Return management')\n\n ret\n .command('create <orderNumber>')\n .description('Create a return request')\n .requiredOption('--products <json>', 'Return products array (JSON)')\n .requiredOption('--refund-amount <n>', 'Refund amount', parseFloat)\n .option('--reason <reason>', 'Return reason (change_of_mind, defective, wrong_delivery, damaged, other)')\n .option('--reason-detail <text>', 'Detailed reason')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.createReturn({\n orderNumber,\n returnProducts: parseJsonArray(opts.products, 'products') as Parameters<typeof client.api.createReturn>[0]['returnProducts'],\n refundAmount: opts.refundAmount,\n reason: opts.reason,\n reasonDetail: opts.reasonDetail,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n ret\n .command('update <returnId>')\n .description('Update return status')\n .requiredOption('--status <status>', 'New status (processing, approved, rejected, completed)')\n .action(async (returnId: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.updateReturn({\n returnId,\n status: opts.status,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n ret\n .command('refund <orderNumber>')\n .description('Return with refund')\n .requiredOption('--products <json>', 'Return products array (JSON)')\n .requiredOption('--refund-amount <n>', 'Refund amount', parseFloat)\n .requiredOption('--payment-id <id>', 'Payment ID')\n .option('--reason <reason>', 'Return reason')\n .option('--reason-detail <text>', 'Detailed reason')\n .option('--refund-receipt-url <url>', 'Refund receipt URL')\n .action(async (orderNumber: string, opts) => {\n try {\n const client = getClient()\n const result = await client.api.returnWithRefund({\n orderNumber,\n returnProducts: parseJsonArray(opts.products, 'products') as Parameters<typeof client.api.returnWithRefund>[0]['returnProducts'],\n refundAmount: opts.refundAmount,\n paymentId: opts.paymentId,\n reason: opts.reason,\n reasonDetail: opts.reasonDetail,\n refundReceiptUrl: opts.refundReceiptUrl,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\n\nexport function registerCartCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const cart = program.command('cart').description('Cart management')\n\n cart\n .command('add <cartId>')\n .description('Add an item to cart')\n .requiredOption('--product <id>', 'Product ID')\n .requiredOption('--variant <id>', 'Variant ID')\n .requiredOption('--option <id>', 'Option ID')\n .requiredOption('--quantity <n>', 'Quantity', (v: string) => parseInt(v, 10))\n .action(async (cartId: string, opts) => {\n try {\n const client = getClient()\n const result = await client.cart.addItem({\n cartId,\n product: opts.product,\n variant: opts.variant,\n option: opts.option,\n quantity: opts.quantity,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n cart\n .command('update <cartItemId>')\n .description('Update cart item quantity')\n .requiredOption('--quantity <n>', 'New quantity', (v: string) => parseInt(v, 10))\n .action(async (cartItemId: string, opts) => {\n try {\n const client = getClient()\n const result = await client.cart.updateItem({\n cartItemId,\n quantity: opts.quantity,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n\n cart\n .command('remove <cartItemId>')\n .description('Remove an item from cart')\n .action(async (cartItemId: string) => {\n try {\n const client = getClient()\n const result = await client.cart.removeItem({ cartItemId })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\nimport { parseJsonArray } from '../lib/parse.js'\n\nexport function registerStockCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const stock = program.command('stock').description('Stock management')\n\n stock\n .command('check')\n .description('Check stock availability')\n .requiredOption('--items <json>', 'Items to check (JSON array of { optionId, quantity })')\n .action(async (opts) => {\n try {\n const client = getClient()\n const items = parseJsonArray(opts.items, 'items') as Parameters<typeof client.product.stockCheck>[0]['items']\n const result = await client.product.stockCheck({ items })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { Command } from 'commander'\nimport type { ResolvedClient } from '../lib/client.js'\nimport { printResult, printError } from '../lib/output.js'\n\nexport function registerTransactionCommands(program: Command, getClient: () => ResolvedClient, getFormat: () => string) {\n const tx = program.command('transaction').description('Transaction management')\n\n tx\n .command('update')\n .description('Update transaction status')\n .requiredOption('--payment-id <id>', 'Payment ID')\n .requiredOption('--status <status>', 'New status (pending, paid, failed, canceled)')\n .requiredOption('--payment-method <method>', 'Payment method')\n .requiredOption('--receipt-url <url>', 'Receipt URL')\n .action(async (opts) => {\n try {\n const client = getClient()\n const result = await client.api.updateTransaction({\n paymentId: opts.paymentId,\n status: opts.status,\n paymentMethod: opts.paymentMethod,\n receiptUrl: opts.receiptUrl,\n })\n printResult(result, getFormat())\n } catch (e) {\n printError(e)\n process.exit(1)\n }\n })\n}\n","import { randomBytes } from 'node:crypto'\nimport { createServer } from 'node:http'\nimport { execFile, exec } from 'node:child_process'\nimport { platform } from 'node:os'\nimport { URL } from 'node:url'\nimport type { Command } from 'commander'\nimport pc from 'picocolors'\nimport {\n loadCredentials,\n saveCredentials,\n deleteCredentials,\n getCredentialsPath,\n loadLocalCredentials,\n saveLocalCredentials,\n getLocalCredentialsPath,\n loadTenantList,\n saveTenantList,\n type TenantInfo,\n} from '../lib/credentials.js'\n\nconst WEB_URL = process.env.SOFTWARE_WEB_URL || 'https://01.software'\nconst TIMEOUT_MS = 3 * 60 * 1000 // 3 minutes\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/\"/g, '"')\n}\n\nfunction openBrowser(url: string): void {\n const os = platform()\n\n const onError = () => {\n console.log(pc.yellow(`Could not open browser automatically. Open this URL manually:\\n${url}`))\n }\n\n if (os === 'win32') {\n exec(`start \"\" \"${url}\"`, (err) => { if (err) onError() })\n } else {\n const cmd = os === 'darwin' ? 'open' : 'xdg-open'\n execFile(cmd, [url], (err) => { if (err) onError() })\n }\n}\n\nconst PAGE_STYLE = `*{margin:0;box-sizing:border-box}\nbody{font-family:system-ui,-apple-system,sans-serif;display:flex;justify-content:center;align-items:center;min-height:100vh;background:#fff;color:#252525}\n@media(prefers-color-scheme:dark){body{background:#252525;color:#f5f5f5}}\n.card{text-align:center;padding:2rem 2.5rem;border-radius:10px;max-width:380px;width:100%}\n.icon{width:40px;height:40px;margin:0 auto 1rem;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:1.25rem}\n.icon.ok{background:rgba(0,0,0,.05);color:#252525}\n.icon.err{background:rgba(220,38,38,.08);color:#dc2626}\n@media(prefers-color-scheme:dark){.icon.ok{background:rgba(255,255,255,.08);color:#f5f5f5}}\nh1{font-size:.875rem;font-weight:600;margin-bottom:.375rem}\np{font-size:.75rem;color:#737373;line-height:1.5}`\n\nconst SUCCESS_HTML = `<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><title>CLI Login</title>\n<style>${PAGE_STYLE}</style>\n</head><body><div class=\"card\"><div class=\"icon ok\">\\u2713</div><h1>Authenticated</h1><p>You can close this tab and return to the terminal.</p></div></body></html>`\n\nconst ERROR_HTML = (msg: string) => `<!DOCTYPE html>\n<html lang=\"en\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width\"><title>CLI Login Error</title>\n<style>${PAGE_STYLE}</style>\n</head><body><div class=\"card\"><div class=\"icon err\">!</div><h1>Authentication failed</h1><p>${escapeHtml(msg)}</p></div></body></html>`\n\n/**\n * Start a local HTTP server that receives the OAuth-like callback from the browser.\n * Returns a promise that resolves with the received credentials, or rejects on error/timeout.\n */\nfunction startAuthServer(options: {\n state: string\n saveFn: (creds: { clientKey: string; secretKey: string; tenantId?: string; tenantName: string }) => void\n}): Promise<{ port: number; cleanup: (exitCode?: number) => void }> {\n return new Promise((resolve, reject) => {\n const server = createServer((req, res) => {\n if (!req.url) {\n res.writeHead(400).end()\n return\n }\n\n const url = new URL(req.url, `http://localhost`)\n\n if (url.pathname !== '/callback') {\n res.writeHead(404).end()\n return\n }\n\n const receivedState = url.searchParams.get('state')\n const clientKey = url.searchParams.get('clientKey')\n const secretKey = url.searchParams.get('secretKey')\n const tenant = url.searchParams.get('tenant')\n const tenantIdParam = url.searchParams.get('tenantId')\n const tenantsParam = url.searchParams.get('tenants')\n const error = url.searchParams.get('error')\n\n if (error) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(ERROR_HTML(error))\n console.error(pc.red(`Login failed: ${error}`))\n cleanup(1)\n return\n }\n\n if (receivedState !== options.state) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(ERROR_HTML('State mismatch — possible CSRF attack.'))\n console.error(pc.red('Login failed: state mismatch.'))\n cleanup(1)\n return\n }\n\n if (!clientKey || !secretKey || !tenant) {\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(ERROR_HTML('Missing credentials in callback.'))\n console.error(pc.red('Login failed: missing credentials.'))\n cleanup(1)\n return\n }\n\n // Save credentials using the provided save function\n options.saveFn({\n clientKey,\n secretKey,\n ...(tenantIdParam ? { tenantId: tenantIdParam } : {}),\n tenantName: tenant,\n })\n\n // Cache tenant list if provided\n if (tenantsParam) {\n try {\n const parsed = JSON.parse(tenantsParam)\n if (Array.isArray(parsed)) {\n const valid = parsed.filter(\n (t): t is TenantInfo => typeof t?.id === 'string' && typeof t?.name === 'string',\n )\n if (valid.length > 0) saveTenantList(valid)\n }\n } catch {\n // Ignore malformed tenants param\n }\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html; charset=utf-8' }).end(SUCCESS_HTML)\n\n console.log(pc.green(`\\nLogged in successfully!`))\n console.log(pc.dim(`Tenant: ${tenant}`))\n cleanup(0)\n })\n\n let timeout: ReturnType<typeof setTimeout>\n let completed = false\n\n function cleanup(exitCode = 0) {\n if (completed) return\n completed = true\n clearTimeout(timeout)\n server.close(() => process.exit(exitCode))\n }\n\n server.listen(0, '127.0.0.1', () => {\n const addr = server.address()\n if (!addr || typeof addr === 'string') {\n reject(new Error('Failed to start local server.'))\n return\n }\n\n timeout = setTimeout(() => {\n console.error(pc.red('\\nLogin timed out (3 minutes). Please try again.'))\n cleanup(1)\n }, TIMEOUT_MS)\n\n resolve({ port: addr.port, cleanup })\n })\n\n server.on('error', (err) => {\n reject(err)\n })\n })\n}\n\nexport function registerAuthCommands(program: Command): void {\n program\n .command('login')\n .description('Login via browser and store credentials')\n .action(async () => {\n const state = randomBytes(32).toString('hex')\n\n try {\n const { port } = await startAuthServer({\n state,\n saveFn: (creds) => {\n saveCredentials(creds)\n console.log(pc.dim(`Credentials saved to ${getCredentialsPath()}`))\n },\n })\n\n const params = new URLSearchParams({ port: String(port), state })\n const loginUrl = `${WEB_URL}/cli-auth?${params.toString()}`\n\n console.log(pc.dim('Opening browser for login...'))\n console.log(pc.dim(`If the browser does not open, visit:\\n${loginUrl}`))\n openBrowser(loginUrl)\n } catch (err) {\n console.error(pc.red(`Server error: ${err instanceof Error ? err.message : String(err)}`))\n process.exit(1)\n }\n })\n\n program\n .command('logout')\n .description('Remove stored credentials')\n .action(() => {\n const deleted = deleteCredentials()\n if (deleted) {\n console.log(pc.green('Logged out. Credentials removed.'))\n } else {\n console.log(pc.dim('No stored credentials found.'))\n }\n })\n\n program\n .command('whoami')\n .description('Show current authentication status')\n .action(() => {\n // Check local credentials first\n const localCreds = loadLocalCredentials()\n const globalCreds = loadCredentials()\n const creds = localCreds || globalCreds\n const isLocal = !!localCreds\n\n if (!creds) {\n console.log(pc.dim('Not logged in. Run \"01 login\" to authenticate.'))\n return\n }\n\n const masked = creds.clientKey.length > 8\n ? creds.clientKey.slice(0, 4) + '...' + creds.clientKey.slice(-4)\n : '****'\n\n const scope = isLocal ? pc.cyan(' (local)') : ''\n console.log(`Tenant: ${pc.bold(creds.tenantName)}${scope}`)\n console.log(`Client Key: ${pc.dim(masked)}`)\n console.log(`Stored at: ${pc.dim(creds.storedAt)}`)\n console.log(`File: ${pc.dim(isLocal ? getLocalCredentialsPath() : getCredentialsPath())}`)\n })\n\n // -------------------------------------------------------------------------\n // tenant subcommands\n // -------------------------------------------------------------------------\n const tenant = program\n .command('tenant')\n .description('Manage tenant switching')\n\n tenant\n .command('list')\n .description('Show cached tenant list')\n .action(() => {\n const tenants = loadTenantList()\n if (!tenants || tenants.length === 0) {\n console.log(pc.dim('No cached tenants. Run \"01 login\" first.'))\n return\n }\n\n // Determine active tenant\n const localCreds = loadLocalCredentials()\n const globalCreds = loadCredentials()\n const activeCreds = localCreds || globalCreds\n const activeId = activeCreds?.tenantId\n const activeName = activeCreds?.tenantName\n\n console.log(pc.bold('Cached tenants:\\n'))\n for (const t of tenants) {\n const active = (activeId ? t.id === activeId : t.name === activeName)\n ? pc.green(' *')\n : ''\n console.log(` ${t.name}${active}`)\n }\n console.log()\n if (activeName) {\n const scope = localCreds ? '(local)' : '(global)'\n console.log(pc.dim(`* active ${scope}`))\n }\n })\n\n tenant\n .command('use <name>')\n .description('Switch to a different tenant via browser')\n .option('--local', 'Save credentials locally in the current project')\n .action(async (name: string, opts: { local?: boolean }) => {\n const tenants = loadTenantList()\n if (!tenants || tenants.length === 0) {\n console.error(pc.red('No cached tenants. Run \"01 login\" first.'))\n process.exit(1)\n }\n\n const match = tenants.find((t) => t.name.toLowerCase() === name.toLowerCase())\n if (!match) {\n console.error(pc.red(`Tenant \"${name}\" not found in cache.`))\n console.error(pc.dim(`Available: ${tenants.map((t) => t.name).join(', ')}`))\n process.exit(1)\n }\n\n const state = randomBytes(32).toString('hex')\n const isLocal = !!opts.local\n\n try {\n const { port } = await startAuthServer({\n state,\n saveFn: (creds) => {\n if (isLocal) {\n saveLocalCredentials(creds)\n console.log(pc.dim(`Credentials saved to ${getLocalCredentialsPath()}`))\n } else {\n saveCredentials(creds)\n console.log(pc.dim(`Credentials saved to ${getCredentialsPath()}`))\n }\n },\n })\n\n const params = new URLSearchParams({\n port: String(port),\n state,\n tenantId: match.id,\n })\n const loginUrl = `${WEB_URL}/cli-auth?${params.toString()}`\n\n console.log(pc.dim(`Switching to tenant \"${match.name}\"...`))\n console.log(pc.dim(`If the browser does not open, visit:\\n${loginUrl}`))\n openBrowser(loginUrl)\n } catch (err) {\n console.error(pc.red(`Server error: ${err instanceof Error ? err.message : String(err)}`))\n process.exit(1)\n }\n })\n}\n"],"mappings":"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","names":["pc","readFileSync","pc","readFileSync","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","program","getClient","getFormat","pc","pc","program","require"]}
|