shopstack 0.2.0 → 0.2.2
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/LICENSE +21 -0
- package/README.md +39 -13
- package/SKILL.md +24 -7
- package/bin/shopstack +3 -1
- package/package.json +29 -5
- package/src/cli.js +210 -37
- package/src/client.d.ts +70 -9
- package/src/client.js +356 -81
- package/src/config.d.ts +22 -3
- package/src/config.js +56 -4
package/src/config.d.ts
CHANGED
|
@@ -7,11 +7,15 @@ export interface ShopstackProfile {
|
|
|
7
7
|
|
|
8
8
|
export interface PendingSignup {
|
|
9
9
|
accountType: "developer" | "personal";
|
|
10
|
+
attemptId?: string;
|
|
10
11
|
email: string;
|
|
11
|
-
expiresAt
|
|
12
|
-
id
|
|
13
|
-
|
|
12
|
+
expiresAt?: string;
|
|
13
|
+
id?: string;
|
|
14
|
+
idempotencyKey?: string;
|
|
15
|
+
pollToken?: string;
|
|
14
16
|
profile: string;
|
|
17
|
+
recoveryKey?: string;
|
|
18
|
+
signupId?: string;
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
export class ConfigStore {
|
|
@@ -25,6 +29,21 @@ export class ConfigStore {
|
|
|
25
29
|
useProfile(name: string): Promise<ShopstackProfile>;
|
|
26
30
|
savePendingSignup(signup: PendingSignup): Promise<PendingSignup>;
|
|
27
31
|
pendingSignup(signupId: string): Promise<PendingSignup | undefined>;
|
|
32
|
+
pendingSignups(): Promise<PendingSignup[]>;
|
|
33
|
+
findPendingSignup(input: {
|
|
34
|
+
accountType: "developer" | "personal";
|
|
35
|
+
email: string;
|
|
36
|
+
}): Promise<PendingSignup | undefined>;
|
|
37
|
+
completePendingSignup(
|
|
38
|
+
attemptId: string,
|
|
39
|
+
profileName: string,
|
|
40
|
+
result: {
|
|
41
|
+
account: { id: string };
|
|
42
|
+
api_key: string;
|
|
43
|
+
key_type: "developer" | "user";
|
|
44
|
+
user?: { id?: string };
|
|
45
|
+
},
|
|
46
|
+
): Promise<ShopstackProfile>;
|
|
28
47
|
deletePendingSignup(signupId: string): Promise<void>;
|
|
29
48
|
load(): Promise<{
|
|
30
49
|
active: string | null;
|
package/src/config.js
CHANGED
|
@@ -46,6 +46,7 @@ export class ConfigStore {
|
|
|
46
46
|
async write(config) {
|
|
47
47
|
const directory = dirname(this.path);
|
|
48
48
|
await mkdir(directory, { mode: 0o700, recursive: true });
|
|
49
|
+
await chmod(directory, 0o700);
|
|
49
50
|
const temporary = `${this.path}.${process.pid}.tmp`;
|
|
50
51
|
await writeFile(temporary, `${JSON.stringify(config, null, 2)}\n`, {
|
|
51
52
|
mode: 0o600,
|
|
@@ -83,19 +84,70 @@ export class ConfigStore {
|
|
|
83
84
|
|
|
84
85
|
async savePendingSignup(signup) {
|
|
85
86
|
const config = await this.load();
|
|
86
|
-
|
|
87
|
+
const key = signup.attemptId ?? signup.id;
|
|
88
|
+
if (typeof key !== "string" || key.length === 0) {
|
|
89
|
+
throw new Error("Pending signup identity is invalid.");
|
|
90
|
+
}
|
|
91
|
+
config.pendingSignups[key] = { ...signup };
|
|
87
92
|
await this.write(config);
|
|
88
|
-
return config.pendingSignups[
|
|
93
|
+
return config.pendingSignups[key];
|
|
89
94
|
}
|
|
90
95
|
|
|
91
96
|
async pendingSignup(signupId) {
|
|
92
97
|
const config = await this.load();
|
|
93
|
-
return
|
|
98
|
+
return (
|
|
99
|
+
config.pendingSignups[signupId] ??
|
|
100
|
+
Object.values(config.pendingSignups).find(
|
|
101
|
+
(pending) => pending.id === signupId || pending.signupId === signupId,
|
|
102
|
+
)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async pendingSignups() {
|
|
107
|
+
return Object.values((await this.load()).pendingSignups);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
async findPendingSignup({ accountType, email }) {
|
|
111
|
+
const normalizedEmail = email.trim().toLowerCase();
|
|
112
|
+
return Object.values((await this.load()).pendingSignups).find(
|
|
113
|
+
(pending) =>
|
|
114
|
+
pending.accountType === accountType &&
|
|
115
|
+
pending.email.trim().toLowerCase() === normalizedEmail,
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async completePendingSignup(attemptId, profileName, result) {
|
|
120
|
+
const config = await this.load();
|
|
121
|
+
const entry = Object.entries(config.pendingSignups).find(
|
|
122
|
+
([key, pending]) =>
|
|
123
|
+
key === attemptId ||
|
|
124
|
+
pending.id === attemptId ||
|
|
125
|
+
pending.signupId === attemptId,
|
|
126
|
+
);
|
|
127
|
+
if (entry === undefined) {
|
|
128
|
+
throw new Error("Pending signup is unavailable.");
|
|
129
|
+
}
|
|
130
|
+
config.profiles[profileName] = {
|
|
131
|
+
accountId: result.account.id,
|
|
132
|
+
apiKey: result.api_key,
|
|
133
|
+
keyType: result.key_type,
|
|
134
|
+
...(result.user?.id === undefined ? {} : { userId: result.user.id }),
|
|
135
|
+
};
|
|
136
|
+
config.active = profileName;
|
|
137
|
+
delete config.pendingSignups[entry[0]];
|
|
138
|
+
await this.write(config);
|
|
139
|
+
return config.profiles[profileName];
|
|
94
140
|
}
|
|
95
141
|
|
|
96
142
|
async deletePendingSignup(signupId) {
|
|
97
143
|
const config = await this.load();
|
|
98
|
-
|
|
144
|
+
const entry = Object.entries(config.pendingSignups).find(
|
|
145
|
+
([key, pending]) =>
|
|
146
|
+
key === signupId ||
|
|
147
|
+
pending.id === signupId ||
|
|
148
|
+
pending.signupId === signupId,
|
|
149
|
+
);
|
|
150
|
+
if (entry !== undefined) delete config.pendingSignups[entry[0]];
|
|
99
151
|
await this.write(config);
|
|
100
152
|
}
|
|
101
153
|
}
|